I want to know from within javascript in a webpage if any chrome extension installed in Chrome is reading the DOM. I want to be able to do this even if the extension does not insert any HTML or script into the DOM. Is there some way I can do this? Basically I want to prevent scraping of the website content.
I see this option
http://blog.kotowicz.net/2012/02/intro-to-chrome-addons-hacking.html
but this requires that I know the ids of the extension. I want to be able to do this more natively across all extensions that are installed.
Is there some event I can get based on when a DOM element is ready or some DOM function is called?
Thanks in advance for your help.
There are lots of methods for reading the DOM, so catching everything would be difficult. However, one approach you can do is wrap individual DOM querying methods. For example:
const origFn = HTMLDocument.prototype.querySelector;
HTMLDocument.prototype.querySelector = function(...args) {
const error = new Error();
console.log(`querySelector was called. Args:`, args, ', Stack trace', error.stack);
return orig.apply(this, args);
}
This will do a console.log whenever document.querySelector is called. I'm not 100% sure if the stack trace will reference Chrome extension JavaScript, but it's worth a shot. Also, it's not guaranteed that all prototypes will be overwriteable like this.
Related
I am trying to write a small script to copy in the web console of a live page, and part of what this script needs to do is take several screenshots of the document body. This script will be for personal use, for a very specific task, so I think it would not be a problem to use Firefox's built in helper function :screenshot, instead of a more cross-compatible solution.
I have read this question about the same topic, which explains why it is not possible to call such helper functions from the webpage's console in JavaScript. But what I thought I could do instead, is to use Firefox's browser console, which gives access to the entire browser. Again, I have been literaly just copying and pasting functions into the console to use while interacting with the page, so if I can call the :screenshot function programmatically from the browser console I would just need to figure out how to access the DOM of a particular document or tab and I will get the same result.
I have tried to import and use html2canvas, but it did not work most probably because the content that I am trying to screenshot resides inside a shadow-root. I know that one alternative is to write my own extension, but I would like to avoid such a job for this task. Eventually, do you know if it is possible to achieve similar results in a Chromium based browser (Brave)?
Thank you very much :D
The good news is that, yes, you can invoke the devtools screenshot functionality from the browser console. Conveniently the default selected node is the document body.
(async()=>{
const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm");
const { gDevTools } = require("devtools/client/framework/devtools");
const { TargetFactory } = require("devtools/client/framework/target");
const target = await TargetFactory.forTab(gBrowser.selectedTab);
const toolbox = await gDevTools.showToolbox(target, "inspector");
const inspector = toolbox.getPanel("inspector");
inspector.screenshotNode();
})()
Now the bad news. Accessing the DOM of content page from the browser console is unbearably tricky :(
You are going about solving the problem in the wrong manner. Firefox since version 57 has built in tools to provide what you want. To accomplish this you want to use Firefox's headless mode with Webdriver if needed.
The simple example from MDN is
/path/to/firefox -P my-profile -headless --screenshot https://developer.mozilla.org/
I want to read a value of DOM element. I am new to browser extensions. I came across codes which provided help in executing a code in browser context but how do I fetch a value and use in extension's context?
var value = document.getElementById('id1'); // Here document should be of browser context.
Try
var value = document.getElementById('id1').value;
// note the extra .value.
You have to access the DOM from content scripts.
If you are looking to get the currently active tab, you would do this: https://developer.chrome.com/extensions/activeTab
How this will work will depend on whether you are in browser context, content scripts or background though.
I highly recommend reading the chrome extension guides: https://developer.chrome.com/extensions/getstarted. They help quite a bit, and the different scopes of the chrome extension are crucial to understand to successfully develop on it.
I am creating a Firefox extension, and one feature of it that I would like is the ability for the user to inject a script or stylesheet into a specific website, rather like Greasemonkey (except that this will only be for one site). I am adding some functions for the scripts to make use of, which I intended to add from the Content Script into the main (unsafe) window. On the MDN blog, it says that they have made changes to how it should be implemented, so I have based my code on the new implementation as advised in the post, so this is what I have:
var $jq = jQuery.noConflict();//Yes, I am also injecting jQuery at the same time
console.log("created jquery object"); //This works
exportFunction($jq, unsafeWindow, {defineAs: "$jq"});
console.log("This will never be called");
But execution of the script just stops, and in the console it prints Message: TypeError: window is null.
I am testing in Firefox 28 predominantly (I can't seem to get Firefox for Ubuntu to update beyond that right now, and a whole load of issues are forcing me to use Ubuntu in a VM for this), but in Nightly 31a1 (Win7) nothing is ever injected, including a hardcoded style (that works on FF28) so I will have to figure that out at some point. (The PageMod code is here:
var lttWorker = sdk.pageMod.PageMod({
include:["*"],
/*contentScriptFile: [sdk.data.url("jquery.large.js"), sdk.data.url("scripts/bootstrapper.js")],
contentScriptWhen: "ready",*/ //This is commented to test whether it was an issue with the script. It's not.
contentStyle: "#header_bar{background-color:green;}", //This is injected in FF28 but not 31
attachTo: ["existing", "top"],
onAttach: function(){desktopNotifications({title:"attached content worker", text:"The content worker has been successfully attached"})} //This is called in FF28 but not 31
});
lttWorker.on("error", function(){callError("pageWorker failed");}); //This never gets called. Ever.
if anybody is interested)
EDIT: I have now tried it on Firefox 30b and there are still a load of issues, although they seem to be slightly different to both FF28 and 31...
First of all: These new functions are supported in Firefox 30 and later. See #canuckistani answer.
The exportFunction API is way too limited to actually inject something like jQuery with all the complex objects being or containing DOM nodes. That simply won't fly with the structured-clone algorithm that is applied to arguments.
The API is meant as a way for add-ons to communicate with pages bi-directionally, and not to inject complex libraries.
Your best bet is actually creating a script tag using the DOM APIs and putting jQuery there.
I'm trying to create a Firefox extension that fires my Javascript code before any of the current page's Javascript is fired. My Javascript code will basically control whether or not the page's Javascript code can be executed or denied.
I first started out by trying to follow this answer, but I couldn't really figure out how to get it to work and realized I was relying on onDOMContentLoaded, which loads after the Javascript has already executed.
I then turned my attention toward XPCOM, but once again didn't really understand what the Firefox tutorials were telling me.
I've recently been trying to make an extension through Firebug, but I seem to hit the same problem... only having access to the Javascript after it's been parsed/executed. Here's the resulting code that I wrote. I think if I could access the file's objects in the onExamineResponse event, my problem could be solved, but I don't know how to do that... I'm talking about this code:
BeepbopListener.prototype = {
onRequest: function(context, file) {
...
},
onExamineResponse: function(context, file) {
FBTrace.sysout("onexamineresponse " + file); // this returns something like
// '[xpconnect wrapped (nsISupports, nsIHttpChannel, nsIRequest, nsIUploadChannel, nsITraceableChannel, nsIHttpChannelInternal)]'
// but I don't know how to access those elements...
var pattern = /\.js$/;
if (pattern.test(file.href) && FBTrace.DBG_BEEPBOP) {
FBTrace.sysout("ONEXAMINE DOESN'T EVEN GET IN THIS IF SO YOU WON'T SEE THIS");
}
},
...
};
So my question is... is there a tutorial out there that shows me how I can get access to all Javascript code on a page before it's executed? Also, if anyone has any helpful insight, I'd love to hear it. Oh, and if y'all need more code from me, just let me know, and I'll post it.
You can access a new document before any JavaScript code runs by listening to the content-document-global-created observer notification. However, the document will be empty at this point and JavaScript code will run as soon as the parser adds a <script> tag - you cannot really prevent it. Here are the options to control script execution that I am aware of.
1) Disable all JavaScript for a window using nsIDocShell.allowJavascript:
wnd.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShell)
.allowJavascript = false;
This is an all or nothing approach. Note that JavaScript stays disabled even when a new document loads into the same frame.
2) Implement the nsIContentPolicy interface in an XPCOM component and register it in the content-policy category (via nsICategoryManager). Your shouldLoad() function will be able to block scripts selectively - but it will only called for external scripts (meaning <script src="...">), not for inline scripts on the page.
3) Use JavaScript debugger service to intercept script execution. You could use jsdIDebuggerService.interruptHook to step through JavaScript execution and abort the script whenever you like. But that would slow down JavaScript execution very significantly of course. At the very least you should use jsdIDebuggerService.addFilter() to restrict it to a particular document, otherwise you will slow down the entire browser (including browser UI).
I'm trying to create a Firefox extension that fires my Javascript code before any of the current page's Javascript is fired. My Javascript code will basically control whether or not the page's Javascript code can be executed or denied.
Start by completely preventing the document from getting parsed altogether then on the side, fetch the same document, do any processing on this document and then inject the resulting document in the page. Here is how I currently do just that https://stackoverflow.com/a/36097573/6085033
is it possible for Firefox extension (toolbar) to access document's variables? detailed explanation follows..
loaded document:
<script type="text/javascript">
var variableForExtension = 'something';
</script>
extension:
var win = window.top.getBrowser().selectedBrowser.contentWindow;
alert(win.variableForExtension); // undefined
it was first thing to try, and it's inaccessible this way because of security mechanisms (XPCNativeWrapper). i've read about accessing it trough wrappedJSObject and using events (adding listener to document and dispatching event from extension), but no luck. didn't try too hard, though. so, before i dig deeper ('events method' sounds like a way to go) i'd like to know is this even possible?
thanks
Yes, accessing a JS variable in content is and always was possible. Doing this the naive way wasn't safe (in the sense that a malicious web page could get chrome privileges) in older Firefox versions.
1) If you control the web page and want to pass information to the extension, you should indeed use the events technique. This worked and was/is safe in all Firefox versions.
2) If you want to read a value from the content document, you can just bypass the XPCNativeWrapper:
var win = window.top.getBrowser().selectedBrowser.contentWindow;
// By the way, this could just be
// var win = content;
// or
// var win = gBrowser.contentWindow;
alert(win.variableForExtension); // undefined
win.wrappedJSObject.variableForExtension // voila!
This was unsafe prior to Firefox 3. In Firefox 3 and later it is OK to use, you get another kind of wrapper (XPCSafeJSObjectWrapper), which looks the same as the object from the content page to your code, but ensures the content page won't be able to do anything malicious.
3) If you need to call a function in a content web page or run your own code in the page's context, it's more complicated. It was asked and answered elsewhere many times, but unfortunately never documented fully. Since this is unrelated to your question, I won't go into the details.
not so hard :)
in extension:
var jso=window.content.document.defaultView.wrappedJSObject;
now you can access any function or global variable in the webpage from the extension:
alert(jso.pagevar);
jso.pagefunction("hey");
If you are working with the new High-Level SDKs then accessing the variable via content scripts is a little different. You can't access the JavaScript objects directly from the add on code, but you can reach them from content scripts that have been attached to an open page via the unsafeWindow object. For example:
require("sdk/tabs").open({
url: 'http://www.example.com/some/page/',
onOpen: function(tab) {
var worker = tab.attach({
contentScript: 'unsafeWindow.variableForExtension = 1000;'
});
}
});
To read the variables you'll need to use the port methods on the worker variable as described in Mozilla's content script article.
Note that there are some security restrictions when dealing with objects and functions. See the articles for details.