Forked from Noitidart/_ff-addon-template-BootstrapWatchHostEventListener.xpi
Last active
August 29, 2015 13:57
-
-
Save Noitidart/9406437 to your computer and use it in GitHub Desktop.
_ff-addon-template-BootstrapWatchHostEventListenerInjectFiles - Uses event listener (DOMContentLoaded) to watch page loads in all tabs and windows with gBrowser once it finds matching host it will inject files that are packaged with the addon.
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
alert('hello from injected script!'); |
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
<html> | |
<head> | |
<!--<LINK REL=StyleSheet HREF="/_resource_for_injected_website-style.css" TYPE="text/css" MEDIA=screen>--> | |
<LINK REL=StyleSheet HREF="chrome://bootstrap-watch-host-event-listener-inject-files/content/_resource_for_injected_website-style.css" TYPE="text/css" MEDIA=screen> | |
</head> | |
<body> | |
This is an injected website with an image.<br> | |
<img src="/_inject-image.png"> | |
<br><br> | |
Note the above image is a relative file in the source file. This below is full path to "chrome://bootstrap-watch-host-event-listener-inject-files/content/_inject-image.png" | |
<img src="chrome://bootstrap-watch-host-event-listener-inject-files/content/_inject-image.png"> | |
<br><br> | |
Note the same is done in the head. I commented out the relative path one and left the full path to the css file "chrome://bootstrap-watch-host-event-listener-inject-files/content/_resource_for_injected_website-style.css". | |
</body> | |
</html> |
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
body { | |
background-color: steelblue; | |
} |
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 {classes: Cc, interfaces: Ci, utils: Cu} = Components; | |
const self = { | |
id: 'Bootstrap-Watch-Host-Event-Listener-Inject-Files', | |
suffix: '@jetpack', | |
path: 'chrome://bootstrap-watch-host-event-listener-inject-files/content/', | |
aData: 0, | |
}; | |
const ignoreFrames = true; | |
const hostPattern = 'bing.com'; //if a page load matches this host it will inject into it | |
Cu.import('resource://gre/modules/Services.jsm'); | |
function addInjections(theDoc) { | |
Cu.reportError('addInjections 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'); | |
removeInjections(theDoc, true); //remove my div if it was already there, this is just a precaution | |
//add your stuff here | |
var myIFrame = theDoc.createElement('iframe'); | |
myIFrame.setAttribute('id','injected-iframe'); | |
myIFrame.setAttribute('type','content'); | |
//myIFrame.setAttribute('accessibleType','100A'); | |
myIFrame.setAttribute('src',self.path + '_inject-website.htm'); | |
var myScript = theDoc.createElement('script'); | |
myScript.setAttribute('src', self.path + '_inject-script.js'); | |
myScript.setAttribute('id','injected-script'); | |
var myImage = theDoc.createElement('img'); | |
myImage.setAttribute('src', self.path + '_inject-image.png'); | |
myImage.setAttribute('id','injected-image'); | |
theDoc.documentElement.appendChild(myIFrame); | |
theDoc.documentElement.appendChild(myScript); | |
theDoc.documentElement.appendChild(myImage); | |
} | |
function removeInjections(theDoc, skipChecks) { | |
//Cu.reportError('removeInjections'); | |
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 myScript = theDoc.getElementById('injected-script'); //test if myDiv is in the page | |
if (myScript) { | |
var alreadyThere = true; | |
} | |
if (alreadyThere) { | |
//my stuff was found in the document so remove it | |
var myIFrame = theDoc.getElementById('injected-iframe'); | |
var myImage = theDoc.getElementById('injected-image'); | |
myScript.parentNode.removeChild(myScript); | |
myIFrame.parentNode.removeChild(myIFrame); | |
myImage.parentNode.removeChild(myImage); | |
} 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 | |
} | |
} | |
addInjections(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 | |
addInjections(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 | |
removeInjections(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
content bootstrap-watch-host-event-listener-inject-files ./ contentaccessible=true |
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-Inject-Files@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 and Inject Files</em:name> | |
<em:description>Uses event listener (DOMContentLoaded) to watch page loads in all tabs and windows with gBrowser once it finds matching host it will inject files that are packaged with the addon.</em:description> | |
<em:creator>Noitidart</em:creator> | |
</Description> | |
</RDF> |
Interesting thing to note I discovered during dev of DragControl. In DragControl initial.rev1 I am able to set src of a panel to a htm file packaged in my addon but contentaccessible is not set in its chrome.manifest, so I suspect that in order to set iframe src you have to do so from a non-contentaccessible path. Need to test that out in this Gist.
Fix css import to <link rel="stylesheet" type="text/css" href="style/main.css">
Try to inject https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
README
Rev1 - Rev5
Rev6
Rev7
First applicable rev to this specific gist/description*
Install that and then navigate to bing.com and scroll to the bottom you will see the inject iframe with blue background and injected image. You will also see the inject script run on load of bing, it will be an alert box.
This version has a bug, the
iframe
attributesrc
when set to the path of_inject-website.htm
it's throwing security error, I am investigating how to fix thisRev8
Rev9