Mercurial > powerbox
changeset 4:1c02976d8809
Changed to Firebug's progress listener, which allows us to inject our code before any scripts are executed on target pages.
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Thu, 06 Aug 2009 17:18:45 -0700 |
parents | 413435fc6202 |
children | c01a64fefbf5 |
files | extension/content/js/xul/browser.js extension/modules/content-injector.js extension/modules/setup.js |
diffstat | 3 files changed, 63 insertions(+), 36 deletions(-) [+] |
line wrap: on
line diff
--- a/extension/content/js/xul/browser.js Thu Aug 06 15:50:24 2009 -0700 +++ b/extension/content/js/xul/browser.js Thu Aug 06 17:18:45 2009 -0700 @@ -1,5 +1,13 @@ (function() { var jsm = {}; Components.utils.import("resource://powerbox/modules/setup.js", jsm); - jsm.PowerboxSetup.installToWindow(window); + + window.addEventListener( + "load", + function onLoad(event) { + window.removeEventListener("load", onLoad, false); + jsm.PowerboxSetup.installToWindow(window); + }, + false + ); })();
--- a/extension/modules/content-injector.js Thu Aug 06 15:50:24 2009 -0700 +++ b/extension/modules/content-injector.js Thu Aug 06 17:18:45 2009 -0700 @@ -60,50 +60,74 @@ }; } +// Taken from Firebug's content/firebug/tabWatcher.js. +function safeGetName(request) { + try { + return request.name; + } catch (exc) { + return null; + } +} + var listener = { QueryInterface : XPCOMUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]), + // Much of this is taken from Firebug's content/firebug/tabWatcher.js, + // specifically the FrameProgressListener object. onStateChange : function (aWebProgress, aRequest, aStateFlags, aStatus) { - // STATE_START is too early, doc is still the old page. - // STATE_STOP is inconviently late (it's onload) - if (!(aStateFlags & Ci.nsIWebProgressListener.STATE_TRANSFERRING)) - return; - - var window = aWebProgress.DOMWindow; + if (aStateFlags & Ci.nsIWebProgressListener.STATE_IS_REQUEST && + aStateFlags & Ci.nsIWebProgressListener.STATE_START) { + // We need to get the hook in as soon as the new DOMWindow is + // created, but before it starts executing any scripts in the + // page. After lengthy analysis, it seems that the start of + // these "dummy" requests is the only state that works. - if (window.wrappedJSObject) { - var sandbox = Cu.Sandbox(window); - sandbox.importFunction(buildRequestor(window)); - sandbox.window = window.wrappedJSObject; + // TODO: Firebug's code mentions that XHTML doesn't dispatch + // any of these dummy requests, so we should probably use the + // Firebug's XHTML workaround here. + var safeName = safeGetName(aRequest); + var window = aWebProgress.DOMWindow; + if (window && window.wrappedJSObject && + (safeName == "about:layout-dummy-request" || + safeName == "about:document-onload-blocker")) { + // TODO: Firebug's code mentions that about:blank causes strange + // behavior here; I don't think it should apply to our use case, + // though. + var sandbox = Cu.Sandbox(window); + sandbox.importFunction(buildRequestor(window)); + sandbox.window = window.wrappedJSObject; - function setupPowerbox() { - window.powerbox = {request: request}; + function setupPowerbox() { + window.powerbox = {request: request}; + } + + Cu.evalInSandbox("(" + setupPowerbox.toString() + ")();", sandbox); } - - Cu.evalInSandbox("(" + setupPowerbox.toString() + ")();", sandbox); } }, - // stubs for the nsIWebProgressListener interfaces which we don't use. + // Stubs for the nsIWebProgressListener interfaces which we don't use. onProgressChange : function() { }, onLocationChange : function() { }, onStatusChange : function() { }, onSecurityChange : function() { } }; -function init() { - // WebProgressListener for getting notification of new doc loads. - // XXX Ugh. Since we're a chrome overlay, it would be nice to just - // use gBrowser.addProgressListener(). But that isn't sending - // STATE_TRANSFERRING, and the earliest we can get at the page is - // STATE_STOP (which is onload, and is inconviently late). - // We'll use the docloader service instead, but that means we need to - // filter out loads for other windows. - var docsvc = Cc["@mozilla.org/docloaderservice;1"]. - getService(Ci.nsIWebProgress); +function init(window) { + var tabbrowser = window.getBrowser(); + + function addListener(browser) { + browser.addProgressListener(listener, + Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT); + } - docsvc.addProgressListener(listener, - Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT); + tabbrowser.tabContainer.addEventListener( + "TabOpen", + function onTabOpen(event) { addListener(event.target.linkedBrowser); }, + false + ); + + tabbrowser.browsers.forEach(function(browser) { addListener(browser); }); }
--- a/extension/modules/setup.js Thu Aug 06 15:50:24 2009 -0700 +++ b/extension/modules/setup.js Thu Aug 06 17:18:45 2009 -0700 @@ -46,8 +46,6 @@ Cc["@mozilla.org/steel/application;1"] .getService(Ci.steelIApplication); -let gIsInitialized = false; - let PowerboxSetup = { getExtensionDirectory: function getExtensionDirectory() { let extMgr = Cc["@mozilla.org/extensions/manager;1"] @@ -82,11 +80,8 @@ }, installToWindow: function installToWindow(window) { - if (!gIsInitialized) { - gIsInitialized = true; - var Injector = {}; - Cu.import("resource://powerbox/modules/content-injector.js", Injector); - Injector.init(); - } + var Injector = {}; + Cu.import("resource://powerbox/modules/content-injector.js", Injector); + Injector.init(window); } };