Last active
January 4, 2016 20:19
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() {} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.