Forked from Noitidart/_template-bootstrapSkeleton.xpi
Last active
August 29, 2015 13:56
-
-
Save Noitidart/9287185 to your computer and use it in GitHub Desktop.
_ff-addon-template-BootstrapWatchHostEventListener - Uses event listener (DOMContentLoaded) to watch page loads in all tabs and windows with gBrowser. When a page matching a certain host name is found it will inject into it. It also shows you how to attach event listeners to injected elements and elements that were already in the webpage.
This file contains 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 ignoreFrames = true; | |
const hostPattern = 'bing.com'; //if a page load matches this host it will inject into it | |
function addDiv(theDoc) { | |
Cu.reportError('addDiv host = ' + theDoc.location.host); | |
if (!theDoc) { Cu.reportError('no doc!'); return; } //document not provided, it is undefined likely | |
if(!(theDoc.location && theDoc.location.host.indexOf(hostPattern) > -1)) { Cu.reportError('location not match host:' + theDoc.location.host); return; } | |
//if (!theDoc instanceof Ci.nsIDOMHTMLDocument) { Cu.reportError('not html doc'); return; } //not html document, so its likely an xul document //you probably dont need this check, checking host is enought | |
Cu.reportError('host pass'); | |
removeDiv(theDoc, true); //remove my div if it was already there, this is just a precaution | |
//add your stuff here | |
var myDiv = theDoc.createElement('div'); | |
myDiv.setAttribute('id','my-div'); | |
myDiv.setAttribute('style','cursor:pointer; min-width:200px; min-height:200px; position:fixed; bottom:0; left:0; background-color:steelblue; z-index:9999; color:#fff; padding:5px; border-radius:5px;'); | |
var myBr = theDoc.createElement('br'); | |
var myTextNode = theDoc.createTextNode('this div was injected because criteria was matched!'); | |
myDiv.appendChild(myTextNode); | |
myDiv.appendChild(myBr); | |
myDiv.appendChild(theDoc.createElement('br')); | |
myDiv.appendChild(theDoc.createTextNode('LOCATION DETAILS:')); | |
myDiv.appendChild(theDoc.createElement('br')); | |
myDiv.appendChild(theDoc.createTextNode('theDoc.location.hash = "' + theDoc.location.hash + '"')); | |
myDiv.appendChild(theDoc.createElement('br')); | |
myDiv.appendChild(theDoc.createTextNode('theDoc.location.host = "' + theDoc.location.host + '"')); | |
myDiv.appendChild(theDoc.createElement('br')); | |
myDiv.appendChild(theDoc.createTextNode('theDoc.location.hostname = "' + theDoc.location.hostname + '"')); | |
myDiv.appendChild(theDoc.createElement('br')); | |
myDiv.appendChild(theDoc.createTextNode('theDoc.location.href = "' + theDoc.location.href + '"')); | |
myDiv.appendChild(theDoc.createElement('br')); | |
myDiv.appendChild(theDoc.createTextNode('theDoc.location.protocol = "' + theDoc.location.protocol + '"')); | |
var myEventListener = function() { | |
removeDiv(theDoc); | |
}; | |
myDiv.addEventListener('click', myEventListener, false); | |
theDoc.documentElement.appendChild(myDiv); | |
var bingSearchBtns = theDoc.querySelectorAll('[name=go]'); //selects all elements in theDoc have attribute name=go | |
[].forEach.call(bingSearchBtns, function(btn) { | |
btn.addEventListener('click', bingBtnEventListener, true); | |
btn.style.outline = '10px solid red'; | |
}); | |
myDiv.appendChild(theDoc.createElement('br')); | |
myDiv.appendChild(theDoc.createElement('br')); | |
myDiv.appendChild(theDoc.createTextNode('Found ' + bingSearchBtns.length + ' bing search buttons on this page and added click listener to all of them')); | |
} | |
function bingBtnEventListener(event) { | |
var win = event.view; | |
var doc = win.document; | |
event.stopPropagation(); | |
event.preventDefault(); | |
event.returnValue = false; | |
win.alert('you click on a bing logo! this is a function in the privelaged addon scope'); | |
} | |
function removeDiv(theDoc, skipChecks) { | |
//Cu.reportError('removeDiv'); | |
if (!skipChecks) { | |
if (!theDoc) { Cu.reportError('no doc!'); return; } //document not provided, it is undefined likely | |
if(!(theDoc.location && theDoc.location.host.indexOf(hostPattern) > -1)) { Cu.reportError('location not match host:' + theDoc.location.host); return; } | |
//if (!theDoc instanceof Ci.nsIDOMHTMLDocument) { Cu.reportError('not html doc'); return; } //not html document, so its likely an xul document //you probably dont need this check, checking host is enought | |
} | |
var myDiv = theDoc.getElementById('my-div'); //test if myDiv is in the page | |
if (myDiv) { | |
var alreadyThere = true; | |
} | |
if (alreadyThere) { | |
//my stuff was found in the document so remove it | |
myDiv.parentNode.removeChild(myDiv); | |
var bingSearchBtns = theDoc.querySelectorAll('[name=go]'); //selects all elements in theDoc have attribute name=go | |
[].forEach.call(bingSearchBtns, function(btn) { | |
btn.removeEventListener('click', bingBtnEventListener, true); | |
btn.style.outline = 'initial'; | |
}); | |
} else { | |
//else its not there so no need to do anything | |
} | |
} | |
function listenPageLoad(event) { | |
var win = event.originalTarget.defaultView; | |
var doc = win.document; | |
Cu.reportError('page loaded loc = ' + doc.location); | |
if (win.frameElement) { | |
//its a frame | |
Cu.reportError('its a frame'); | |
if (ignoreFrames) { | |
return;//dont want to watch frames | |
} | |
} | |
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 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>Bootstrap-Watch-Host-Event-Listener@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>4.0</em:minVersion> | |
<em:maxVersion>27.0.1</em:maxVersion> | |
</Description> | |
</em:targetApplication> | |
<!-- Front End MetaData --> | |
<em:name>Bootstrap Watch Host Event Listener</em:name> | |
<em:description>Uses event listener (DOMContentLoaded) to watch page loads in all tabs and windows with gBrowser. When a page matching a certain host name is found it will inject into it. It also shows you how to attach event listeners to injected elements and elements that were already in the webpage.</em:description> | |
<em:creator>Noitidart</em:creator> | |
</Description> | |
</RDF> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
README
Rev1 to Rev2
Ignore these revisions. They are apart of the forked Gist.
Rev3
First revision specific to _ff-addon-template-BootstrapWatchHostEventListener
Set up to watch page loads of
bing.com
, when found it will add a blue div at the top left of the page, fixed, and will display location details.bootstrap.js
theDoc.location.href
this change would have to be made on Line 9 and Line 53addDiv
, whatever you add there, be sure to remove inremoveDiv
skipChecks
argument ofremoveDiv
is meant only for if runningremoveDiv
inaddDiv
function. For example you want to ensure that the old stuff is removed before adding the new stuff so you runremoveDiv(theDoc, true)
before adding.Rev4
This revision shows how to make elements in the document loaded execute functiosn from your addon.
bootstrap.js
Rev5
This shows how to add event listener to existing HTML element and how to remove it. On add this disables the Bing search button and makes it pop open an alert saying you clicked it, it also prevents the search button from working. It puts an outline around the Bing search button on add, and removes the outline on remove.
bootstrap.js
Rev6
install.rdf