Skip to content

Instantly share code, notes, and snippets.

@hallvors
Created July 11, 2014 21:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hallvors/16878737126e6c43d0aa to your computer and use it in GitHub Desktop.
Save hallvors/16878737126e6c43d0aa to your computer and use it in GitHub Desktop.
Firefox test add-on, trying to find the simplest way to monitor loading of pages in tabs
"use strict";
// exploring add-ons API
// Goal: monitor all tabs, run code when new page loads
// Optionally also listen for document mutations
// some standard vars / shortcuts into Gecko's internals: classes, interfaces, utils
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
// I want to have console.log() around, here's some code for that
var aConsoleService = Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService);
var console = {log:function(str){aConsoleService.logStringMessage(str);}}
// eventually we would like this method to run each time a page loads inside a tab
function tab_onLoad(evt){
console.log('TAB DOMContentLoaded!')
console.log(evt.type + ' on ' + evt.target.wrappedJSObject + ' (currentTarget : ' + evt.currentTarget+ ')');
// we need only one event per navigation, let's remove the listener again
evt.target.removeEventListener('DOMContentLoaded', tab_onLoad, false);
// manipulate document here.. presumably
}
// seems we have to attach something to every new window to start monitoring its tabs..
function win_onLoad(evt){
// adding tab progress listener in the new window
try{
this.gBrowser.addTabsProgressListener(tabProgressListener);
}catch(e){
console.log('this.gBrowser failed')
console.log(e);
}
}
var windowListener = {
onOpenWindow: function(aWindow) {
console.log('onOpenWindow ' + aWindow);
/*for(var prop in aWindow){ // explore the API manually..
console.log(prop);
}*/
// Wait for the window to finish loading
// some page on the internet says gBrowser might not be usable unless we do this..
let domWindow = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
domWindow.addEventListener("load", win_onLoad, false);
},
onCloseWindow: function(aWindow) {
// Do we have to clean up to avoid memory leaks? Or will the GC handle it all when the window is gone?
let domWindow = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
domWindow.removeEventListener("load", win_onLoad, false);
// If we need to clean up, we probably have to kill the progress listener too. This doesn't seem to work though:
// domWindow.gBrowser.removeTabsProgressListener(tabProgressListener);
},
onWindowTitleChange: function(aWindow, aTitle) {}
};
// To listen for the actual load event, we first detect location change events and attach load listener from there
var tabProgressListener = { onLocationChange:function(aBrowser, aWebProgress, aRequest, aLocation, aFlags){
if(aBrowser && aRequest){
if(aBrowser.getAttribute('type') === 'content-primary'){
aBrowser.contentWindow.addEventListener('DOMContentLoaded', tab_onLoad, false);
}
}
}, onProgressChange: function(aBrowser, aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress){} };
tabProgressListener.onSecurityChange = tabProgressListener.onStateChange = tabProgressListener.onStatusChange = tabProgressListener.onRefreshAttempted = tabProgressListener.onLinkIconAvailable = function(){}
function startup(aData, aReason) { console.log('startup ' + aData + ', ' + aReason);
// enumerate existing windows and add tab progress listener
let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
let windows = wm.getEnumerator("navigator:browser");
while (windows.hasMoreElements()) {
let domWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
domWindow.gBrowser.addTabsProgressListener(tabProgressListener);
}
// Load into any new windows
wm.addListener(windowListener);
}
function shutdown(aData, aReason) {
// When the application is shutting down we normally don't have to clean
// up any UI changes made
console.log('shutdown ' + aData + ' , ' + aReason);
if (aReason == APP_SHUTDOWN)
return;
let wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
// Stop listening for new windows
wm.removeListener(windowListener);
// Unload from any existing windows
let windows = wm.getEnumerator("navigator:browser");
while (windows.hasMoreElements()) {
let domWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
domWindow.removeEventListener("load", onLoad, false);
}
// TODO: we have more events to remove, how?
}
function install(aData, aReason) {} function uninstall(aData, aReason) {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment