I'm building a Firefox Extension that, among other things, needs to replace body background color on one website. I'm interested in methods that work primarily on Firefox 4, compatibility with older versions of Firefox is not that important.
I have already done this in Chrome, Opera and Safari extensions, but I'm unable to do the same thing in Firefox extension after several hours of reading and trying various stuff. Please help.
I apologize in advance for such a long post, I tried to shorten it as much as possible.
What I tried so far:
1. DOMContentLoaded
This method does replace the color but it's doing it too late, Firefox first shows the original color and than replaces it with my color. It appears that my function is not executed until adsense or facebook widgets from that website do their job. If user has some kind of ad blocker than it works fine, but that obviously doesn't mean anything for my extension.
gBrowser.addEventListener("DOMContentLoaded", my_function, true);
my_function: function(event)
{
var doc = event.originalTarget;
doc.body.style.background = "#f00";
}
2. Observers
I tried these three observer types:
- chrome-document-global-created
- content-document-global-created
- document-element-inserted
I can't access body element from any of those listed observers.
Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService).addObserver(
{
observe: function(aSubject, aTopic, aData)
{
var doc = aSubject;
// doc.location - contains the url
// doc - [object XrayWrapper [object Window]]
// doc.document - [object XrayWrapper [object HTMLDocument]]
// doc.document.body - null
doc.document.body.style.background = "#f00"; // this will obviously not work because body is not yet created or I'm looking in the wrong place
}
}, "content-document-global-created", false);
3. WebProgressListener with NOTIFY_STATE_DOCUMENT
From STATE_TRANSFERRING I can't access body, from STATE_STOP it's too late.
browser.webProgress.addProgressListener(this, browser.webProgress.NOTIFY_STATE_DOCUMENT);
onStateChange: function(aWebProgress, aRequest, aFlag, aStatus)
{
var doc = aWebProgress.DOMWindow;
if (aFlag & Components.interfaces.nsIWebProgressListener.STATE_TRANSFERRING)
{
// doc.document.body - null
doc.document.body.style.background = "#f00"; // again this will obviously not work because body is not yet created or I'm looking in the wrong place
}
if (aFlag & Components.interfaces.nsIWebProgressListener.STATE_STOP)
{
// doc.document.body - [object XrayWrapper [object HTMLBodyElement]]
doc.document.body.style.background = "#f00"; // works but the same way DOMContentLoaded does, too slow
}
}
4. WebProgressListener with NOTIFY_PROGRESS (or NOTIFY_STATE_REQUEST or NOTIFY_STATE_ALL)
This does change the color right away, but I'm getting SO MUCH events for every website and resource that user accesses that I'm not comfortable using this for such a simple thing as changing a background color for just one website.
browser.webProgress.addProgressListener(this, browser.webProgress.NOTIFY_PROGRESS);
onProgressChange: function(aWebProgress, aRequest, curSelf, maxSelf, curTot, maxTot)
{
var doc = aWebProgress.DOMWindow;
doc.document.body.style.background = "#f00";
}
Is there perhaps any other method where I could access body element as soon as it's created? Or maybe some other method to change webpage styling (without involving some other extensions of course)? Could I maybe somehow attach NOTIFY_PROGRESS listener to just one website?