Debugging injected script in chrome extension - javascript

Say I have the following code:
in my content-script.js:
const script = document.createElement('script');
script.setAttribute("type", "application/javascript");
script.src = chrome.runtime.getURL('inject.js');
(document.head || document.documentElement).appendChild(script);
And then in my inject.js
window.addEventListener('message', (event) => {
console.log(event)
}
This does not print anything to the console. Now I know that the inject script is working as when I open the popup window from it, that functions as expected. How can I go about debugging the injected script? Where can I see it's stdout?

Output from a script injected in this way should show in the Dev Tools console as normal. If it isn't, one thing to check could be the "Selected context only" option above the console, which if checked limits which contexts output is shown from.
Another possibility of course is that there isn't a message event being fired on the page - you could replace the console.log with something like an alert to confirm if that's the case.
One last thing worth checking - make sure the script is exposed under the web_accessible_resources manifest key. Without this, the script will fail to load: https://developer.chrome.com/docs/extensions/mv3/manifest/web_accessible_resources/

Related

JavaScript is not function properly when set it locally

I want to import raphael-min.js for my jsp. I'm using
<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.2/raphael-min.js"></script>
tag for importing of the script. But the I want to include this js locally because when rendering this script is blocked by the browser. I copy the code from the url above and save it as a js file. and include as this
<script src="${pageContext.request.contextPath}/resources/raphael/raphael-min.js"></script>.
But the problem is js is not function at all. Are there any method to download this and include in jsp file?
We may load js file adding script tag in DOM:
Try the below code:
var script = document.createElement('script');
script.src = PATH;
script.onload = function(){
FILE LOADED
};
document.head.appendChild(script);
It seems weird that a browser is blocking a cloudflare.com URL - are you using AdBlock or similar extensions? Try accessing the page through incognito or private browsing mode (assuming that the extension is disabled - the default - in that mode) for Chrome and Firefox respectively.
If you are seeing a particular error message, please post the error message - it will probably give clues as to why it is being blocked.
P.S: I would've posted a comment if my reputation allowed it. If you post clarifications, I can edit this answer accordingly.

How to redirect page after "Enable Unsafe Scripts" is enabled?

I have a website that requires "Load Unsafe Scripts" to be enabled to load. What I want is the site to redirect to another after the user enables the "Load Unsafe Scripts" option is enabled. I can work with HTML, and JavaScript. Any help would be appreciated!
As already mentioned, you really should focus on fixing the unsafe script by serving everything (or nothing) from HTTPS.
If you absolutely can't for some reason, and for the sake of exercise: there is no trigger that you can directly react to when this occurs.
Your only real option would be to periodically try to add the script again if it hasn't been already. This wouldn't involve a redirect, but just pulling the script(s) in again.
Something like this:
function loadUnsafe() {
if (!somethingInYourScript) {
const script = document.createElement('script');
script.src = 'https://path.to/my-script.js';
document.appendChild(script);
setTimeout(loadUnsafe, 10000); // wait 10 seconds to try again
}
}
loadUnsafe();
This will try to pull in your script every 10 seconds if somethingInYourScript doesn't exist. Once it does exist, it'll stop.
The somethingInYourScript would be something that the script pulls in (for example, if you were trying to bring in jQuery, you could check if jQuery variable exists because it will once the script is loaded.
You could try to pull in the main file you want (if your site can handle that), or you could try to pull in an unsafe script that would cause a redirect/refresh.
You can load a script from an unsave source which redirect to the other page.
Something like
var locationn = "https://google.com";
window.location = locationn;
But you realy need to make your scripts save...

Passing params with javascript to php

I use the chrome extension called tubeoffline. It uses the following script to find the video src of movies from viooz.co
function injectJs(link)
{
var scr = document.createElement('script');
scr.type="text/javascript";
scr.src=link;
document.getElementsByTagName('head')[0].appendChild(scr)
//document.body.appendChild(scr);
}
injectJs('http://www.tubeoffline.com/js/plugin/getSrc.php');
injectJs('http://www.tubeoffline.com/js/plugin/DlExec.php');
How do I find out the values of the parameters which are being passed ?
As far as i can see there are missing parameters in the URLs. Whatever parameters these should be must be somewhere in documentation... else it is just guessing
I use Firebug for this sort of stuff, however Chrome has its own set of development tools. I believe it's accessed the same way - by hitting your F12 button.
This will have several tabs that you can click on. There should be a "Network" tab that shows which pages are being called. If you refresh the page with the developer tools open, you should see what is going on behind the scenes.

How to disable facebook hotkeys with Chrome extension?

I have created a Chrome extension that uses the hotkeys [Alt]+[0...9] only to discover facebook uses the same hotkeys. Is there any way possible my extension could disable facebook's hotkeys so that mine fire alone? I'm fairly certain I have identified the code facebook uses to implement their [Alt]+[0...9] hotkeys:
document.documentElement.onkeydown=function(a){a=a||window.event;var b=a.target||a.srcElement;var c=a.keyCode==13&&!a.altKey&&!a.ctrlKey&&!a.metaKey&&!a.shiftKey&&CSS.hasClass...
This is in a script called from the head of the root document. I have tried the following to disable them:
//contents script:
$().ready( function() {
document.documentElement.onkeydown = '';
});
and even
$().ready( function() {
document.documentElement.onkeydown = function(e){};
});
I am guessing further that the reason neither of these attempts work is because although Chrome extension content scripts share a DOM with any webpage on which they run, perhaps they do not share coding environments? Any insight would be appreciated!
Chrome's Content scripts are executed in a Sandboxed environment [source]. There is no direct way to communicate with the global (window) object.
Another common pitfall is that the developer forgets how/when the script is injected.
By default, the script is injected at a point called "document_idle". At this point, the document is not busy (DOMContentLoaded has fired, window.onload may or may not have fired).
As a result, the functions in the script may be overwritten immediately after declaration.
To inject a small script, I recommend to add the code directly to the Content Script:
var actualCode = '/* Code here (see below for inspiration) */';
var script = document.createElement('script');
script.appendChild(document.createTextNode(actualCode));
(document.head || document.documentElement).appendChild(script);
script.parentNode.removeChild(script);
If you want to make sure that the method is not going to be overwritten, you can use Object.defineProperty, to define an immutable property:
Object.defineProperty(document.documentElement, 'onkeydown', {
value: function() {},
writable: false, /* Cannot be overwritten, default false */
configurable: false, /* Cannot be deleted, or modified */
enumerable: true /* Does not really matter. If true, it's visible in
a for-loop. If false, it's not*/
});
The previously mentioned method is supported in Firefox 4+ and at least Chrome 5+. If you want to also support Firefox 2+ and Chrome 1+, you can play with the __defineSetter__, to prevent onkeydown from being defined:
document.documentElement.__defineSetter__('onkeydown', function(){});
Your intuition is correct, the JavaScript that runs from a content script as part of a Chrome Extension is run in a sandbox that does not have access to the JavaScript that is executed in the containing page.
Per the Chrome doc on Content Scripts:
However, content scripts have some limitations. They cannot:
* Use chrome.* APIs (except for parts of chrome.extension)
* Use variables or functions defined by their extension's pages
* Use variables or functions defined by web pages or by other content scripts
First off, I would recommend that you consider different shortcut keys. Overriding the functionality of existing shortcut keys for your own extension could provide a jarring user experience for someone that is expecting the Facebook shortcut key. Imagine if an extension overrode the ctrl-c and ctrl-p shortcuts that are a part of the desktop OS for copy and paste - I think you would have some upset users that would probably remove the thing that changed the behavior they learned prior.
However, if you are insistent, then here is a workaround to loading JavaScript that will execute in the context of the containing page:
Edit: Updated per comment to reference JS file in a plugin instead of one hosted on the web
First, you will need to create a JavaScript file in your chrome plugin: override-fb-hotkeys.js.
First, you will need to host a JavaScript file somewhere on the web that contains the script that you want to execute in the page, let us say you host it at: http://example.com/override-fb-hotkeys.js.
Then, from your content script, you can insert a script tag into the DOM that references your JavaScript file, something like this:
var script = document.createElement('script');
script.setAttribute("type", "text/javascript");
script.setAttribute("async", true);
script.setAttribute("src", chrome.extension.getURL("override-fb-hotkeys.js")); //Assuming your host supports both http and https
var head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
head.insertBefore(script, head.firstChild)
The JavaScript will then be fetched and executed in the context of the containing page, not the sandboxed code from the Chrome plugin.
This is how you can do it using jQuery
Remove all shortcuts for any webpage:
$('[accessKey]').attr('accessKey','')

CKEditor variable is available in console, but not from a Chrome userscript?

I'm writing a Chrome userscript to locally auto-save content in a CKEditor. I'm using this CKEditor auto-save plugin as inspiration.
I have written a function that fires every half second (via an interval) to register the CKEditor event handler:
var intervalId = window.setInterval(function() {
if (CKEDITOR) {
window.clearInterval(intervalId);
CKEDITOR.plugins.add("user-script-auto-save", {
init : function(editor) {
editor.on('key', startTimer);
}
});
}
}, 500);
However, it never properly completes, and complains that "CKEDITOR is undefined" on the if (CKEDITOR) statement.
Meanwhile, if I drop into Chrome's console and type CKEDITOR, the console prints out the expected object.
What am I missing? The editor is embedded within an iframe; might that have an impact on scoping? Or am I fighting against Chrome's sandboxing here? And if so, is there some other way I can dig into CKEditor to pull out the content every second or something to do the auto-saves?
I have not yet tried the script in Firefox; that's next on my list.
Worth noting: I'm a long-time JavaScript novice. So I could easily be doing something dumb with scoping or something like that.
According to this little tutorial video on YouTube, all the 3 "devices" are separated from each other in order to prevent XSS attacks from the user script to the browser / website and vice versa. Although the user scripts / content scripts are running in the website's context, they are still kept separated from the actual website script context. You can easily acknowledge this by simply trying to access for example jQuery from a content script. Just as the CKEditor, it will not be available.
So what I've come up with in order to deal with this is using the content script to include external JavaScripts in the head tag. AFAIK, this is not possible for files directly in the extension's root directory, so I've taken a remote server to host my files.
I'm not sure if this is the best approach and I think it is an ugly bypass, possibly way to powerfull and disabled by the Chromium Project some time.
(Edited by OP, so I can select this answer and route karma appropriately)
This answer, combined with some of the suggestions and links in the comments, ended up getting me to where I needed to be.
I ended up with the following function:
var insertScriptIntoDocument = function(scriptUrl, doc) {
// inspired by http://blog.afterthedeadline.com/2010/05/14/how-to-jump-through-hoops-and-make-a-chrome-extension/
var scriptText = doc.createTextNode(
'(function(loc) { \
var embeddedScript = document.createElement("script"); \
embeddedScript.type = "text/javascript"; \
embeddedScript.src = loc; \
document.getElementsByTagName("head")[0].appendChild(embeddedScript); \
})("' + scriptUrl + '");');
var injectorElement = doc.createElement('script');
injectorElement.appendChild(scriptText);
doc.body.appendChild(injectorElement);
};
Usage looks like so:
var embeddedScriptUrl = chrome.extension.getURL("embedded-script.js");
insertScriptIntoDocument(embeddedScriptUrl, document);
For now, I'm executing this from within a Chrome extension, but I suspect that the pattern might work in a GreaseMonkey script deployed via the Chrome TamperMonkey extension provided that the URL of the script to be embedded was hosted somewhere reachable.
FTR, as it turns out, I did not actually need to get to the iframe -- the CKEDITOR variable was defined in the top-level document, but was simply not visible because of the rules of the Chrome sandbox

Categories

Resources