Mercurial > powerbox
view extension/modules/content-injector.js @ 3:413435fc6202
We now show a notification box when a page calls window.powerbox.request().
author | Atul Varma <varmaa@toolness.com> |
---|---|
date | Thu, 06 Aug 2009 15:50:24 -0700 |
parents | 889c2fd4c9cf |
children | 1c02976d8809 |
line wrap: on
line source
var EXPORTED_SYMBOLS = ["init"]; const Cc = Components.classes; const Ci = Components.interfaces; const Cu = Components.utils; const REQUEST_BOX_NAME = "powerbox_superpower_request"; const REQUEST_BOX_TEXT = "This web page wants superpowers."; const REQUEST_BOX_BUTTON_TEXT = "Huh?"; Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); function getParentChromeWindow(window) { var mainWindow = window.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIWebNavigation) .QueryInterface(Ci.nsIDocShellTreeItem) .rootTreeItem .QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIDOMWindow); return mainWindow.wrappedJSObject; } function showRequestNotificationBox(window, caps, callback) { var tabbrowser = getParentChromeWindow(window).getBrowser(); var browser = tabbrowser.getBrowserForDocument(window.document); if (browser) { var nBox = tabbrowser.getNotificationBox(browser); var oldNotification = nBox.getNotificationWithValue(REQUEST_BOX_NAME); if (oldNotification) nBox.removeNotification(oldNotification); nBox.appendNotification(REQUEST_BOX_TEXT, REQUEST_BOX_NAME, null, nBox.PRIORITY_INFO_MEDIUM, [{accessKey: null, // TODO: Implement a real callback. callback: function() {}, label: REQUEST_BOX_BUTTON_TEXT, popup: null}]); } } function buildRequestor(window) { return function request(caps, callback) { if (!(typeof(caps) == "object" || typeof(caps) == "string")) throw new Error("Must provide capabilities as first parameter."); if (typeof(callback) != "function") throw new Error("Must provide callback as second parameter"); if (typeof(caps) == "object") caps = new XPCSafeJSObjectWrapper(caps); callback = new XPCSafeJSObjectWrapper(callback); showRequestNotificationBox(window, caps, callback); }; } var listener = { QueryInterface : XPCOMUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]), 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 (window.wrappedJSObject) { var sandbox = Cu.Sandbox(window); sandbox.importFunction(buildRequestor(window)); sandbox.window = window.wrappedJSObject; function setupPowerbox() { window.powerbox = {request: request}; } Cu.evalInSandbox("(" + setupPowerbox.toString() + ")();", sandbox); } }, // 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); docsvc.addProgressListener(listener, Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT); }