Skip to content

Instantly share code, notes, and snippets.

@Noitidart
Last active January 4, 2016 20:19
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save Noitidart/8673632 to your computer and use it in GitHub Desktop.
Demo on how to create ff-addon that listens to page loads and inserts a DIV element into it. This example inserts a blue div 200x200 pixels at top left if mozillazine is found in the address. This demo uses the nsIWindowMediatorListener and nsIWindowMediator method.
const {interfaces: Ci, utils: Cu} = Components;
Cu.import('resource://gre/modules/Services.jsm');
const locationToMatch = 'mozillazine';
const ignoreFrames = false;
function addDiv(theDoc) {
//Cu.reportError('addDiv');
if (!theDoc) {
Cu.reportError('no theDoc!')
//document not provided, it is undefined likely
return;
}
var location = (theDoc.location + '');
if (location.toLowerCase().indexOf(locationToMatch) == -1) {
return;
}
//Cu.reportError('theDoc location matches locationToMatch:' + theDoc.location)
if (!theDoc instanceof Ci.nsIDOMHTMLDocument) {
//not html document, so its likely an xul document
Cu.reportError('theDoc is not an HTML document, it is probably XUL, since i chose to add HTML element, i dont want to add to xul elements, so exit');
return;
}
removeDiv(theDoc);
var div = theDoc.createElement('div');
div.setAttribute('style', 'background-color:steelblue;width:200px;height:200px;position:absolute;top:0;left:0;')
div.innerHTML = 'hiiiii';
div.setAttribute('id', 'listenPageLoadDemo_div')
theDoc.documentElement.appendChild(div);
}
function removeDiv(theDoc) {
//Cu.reportError('removeDiv');
if (!theDoc) {
Cu.reportError('no theDoc!')
//document not provided, it is undefined likely
return;
}
var location = (theDoc.location + '');
if (location.toLowerCase().indexOf(locationToMatch) == -1) {
return;
}
//Cu.reportError('theDoc location matches locationToMatch:' + theDoc.location)
if (!theDoc instanceof Ci.nsIDOMHTMLDocument) {
//not html document, so its likely an xul document
Cu.reportError('theDoc is not an HTML document, it is probably XUL, since i chose to add HTML element, i dont want to add to xul elements, so exit');
return;
}
var alreadyThere = theDoc.querySelector('#listenPageLoadDemo_div');
if (alreadyThere) {
alreadyThere.parentNode.removeChild(alreadyThere);
}
}
function listenPageLoad(event) {
var win = event.originalTarget.defaultView;
var doc = win.document;
if (win.frameElement) {
//its a frame
//Cu.reportError('a frame loaded');
if (ignoreFrames) {
return;
}
}
addDiv(doc);
}
/*start - windowlistener*/
var windowListener = {
//DO NOT EDIT HERE
onOpenWindow: function (aXULWindow) {
// Wait for the window to finish loading
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
aDOMWindow.addEventListener("load", function () {
aDOMWindow.removeEventListener("load", arguments.callee, false);
windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
}, false);
},
onCloseWindow: function (aXULWindow) {},
onWindowTitleChange: function (aXULWindow, aNewTitle) {},
register: function () {
// Load into any existing windows
let XULWindows = Services.wm.getXULWindowEnumerator(null);
while (XULWindows.hasMoreElements()) {
let aXULWindow = XULWindows.getNext();
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
windowListener.loadIntoWindow(aDOMWindow, aXULWindow);
}
// Listen to new windows
Services.wm.addListener(windowListener);
},
unregister: function () {
// Unload from any existing windows
let XULWindows = Services.wm.getXULWindowEnumerator(null);
while (XULWindows.hasMoreElements()) {
let aXULWindow = XULWindows.getNext();
let aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
windowListener.unloadFromWindow(aDOMWindow, aXULWindow);
}
//Stop listening so future added windows dont get this attached
Services.wm.removeListener(windowListener);
},
//END - DO NOT EDIT HERE
loadIntoWindow: function (aDOMWindow, aXULWindow) {
if (!aDOMWindow) {
return;
}
if (aDOMWindow.gBrowser) {
aDOMWindow.gBrowser.addEventListener('DOMContentLoaded', listenPageLoad, false);
if (aDOMWindow.gBrowser.tabContainer) {
//has tabContainer
//start - go through all tabs in this window we just added to
var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
for (var i = 0; i < tabs.length; i++) {
Cu.reportError('DOING tab: ' + i);
var tabBrowser = tabs[i].linkedBrowser;
var win = tabBrowser.contentWindow;
loadIntoContentWindowAndItsFrames(win);
}
//end - go through all tabs in this window we just added to
} else {
//does not have tabContainer
var win = aDOMWindow.gBrowser.contentWindow;
loadIntoContentWindowAndItsFrames(win);
}
} else {
//window does not have gBrowser
}
},
unloadFromWindow: function (aDOMWindow, aXULWindow) {
if (!aDOMWindow) {
return;
}
if (aDOMWindow.gBrowser) {
aDOMWindow.gBrowser.removeEventListener('DOMContentLoaded', listenPageLoad, false);
if (aDOMWindow.gBrowser.tabContainer) {
//has tabContainer
//start - go through all tabs in this window we just added to
var tabs = aDOMWindow.gBrowser.tabContainer.childNodes;
for (var i = 0; i < tabs.length; i++) {
Cu.reportError('DOING tab: ' + i);
var tabBrowser = tabs[i].linkedBrowser;
var win = tabBrowser.contentWindow;
unloadFromContentWindowAndItsFrames(win);
}
//end - go through all tabs in this window we just added to
} else {
//does not have tabContainer
var win = aDOMWindow.gBrowser.contentWindow;
unloadFromContentWindowAndItsFrames(win);
}
} else {
//window does not have gBrowser
}
}
};
/*end - windowlistener*/
function loadIntoContentWindowAndItsFrames(theWin) {
var frames = theWin.frames;
var winArr = [theWin];
for (var j = 0; j < frames.length; j++) {
winArr.push(frames[j].window);
}
Cu.reportError('# of frames in tab: ' + frames.length);
for (var j = 0; j < winArr.length; j++) {
if (j == 0) {
Cu.reportError('**checking win: ' + j + ' location = ' + winArr[j].document.location);
} else {
Cu.reportError('**checking frame win: ' + j + ' location = ' + winArr[j].document.location);
}
var doc = winArr[j].document;
//START - edit below here
addDiv(doc);
if (ignoreFrames) {
break;
}
//END - edit above here
}
}
function unloadFromContentWindowAndItsFrames(theWin) {
var frames = theWin.frames;
var winArr = [theWin];
for (var j = 0; j < frames.length; j++) {
winArr.push(frames[j].window);
}
Cu.reportError('# of frames in tab: ' + frames.length);
for (var j = 0; j < winArr.length; j++) {
if (j == 0) {
Cu.reportError('**checking win: ' + j + ' location = ' + winArr[j].document.location);
} else {
Cu.reportError('**checking frame win: ' + j + ' location = ' + winArr[j].document.location);
}
var doc = winArr[j].document;
//START - edit below here
removeDiv(doc);
if (ignoreFrames) {
break;
}
//END - edit above here
}
}
function startup(aData, aReason) {
windowListener.register();
}
function shutdown(aData, aReason) {
if (aReason == APP_SHUTDOWN) return;
windowListener.unregister();
}
function install() {}
function uninstall() {}
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>listen-page-load-demo@jetpack</em:id>
<em:version>initial</em:version>
<em:type>2</em:type>
<em:bootstrap>true</em:bootstrap>
<em:unpack>false</em:unpack>
<!-- Firefox -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>7.0</em:minVersion>
<em:maxVersion>10.0a1</em:maxVersion>
</Description>
</em:targetApplication>
<!-- Front End MetaData -->
<em:name>listen page load demo</em:name>
<em:description>This addon shows how to listen to page loads and then do something with it.</em:description>
<em:creator>Noitidart</em:creator>
<em:iconURL/>
<em:icon64URL/>
<em:optionsType>2</em:optionsType>
</Description>
</RDF>
@Noitidart
Copy link
Author

regarding rev4:
updated gist so that bootstrap.js works perfectly fine for windows with gBrowser. however if window does not have gBrowser, it will only watch the content when that window initially opens. if location is changed in a non-gBrowsered window then the above will not catch it.

thats something im working on, for rev5, but its not so important because the only windows that don't have gBrowser are "Browser/Error Console", "Scratchpad", and other windows that web pages don't load in 99% of the time. Only loads html pages when people like power users, force them to load a page.

So this should be very good to go.

If you copy paste this, you will want to edit the "const locationToMatch = 'mozillazine';" and then edit the addDiv function portion starting at line23 and removeDiv function portion starting at line 47. Whatever you add in addDiv, remove it in removeDiv.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment