let Ci = Components.interfaces;
let Cm = Components.manager;
let Cu = Components.utils;
-let application = Cc['@mozilla.org/fuel/application;1']
- .getService(Ci.fuelIApplication);
-let privateBrowsing = Cc['@mozilla.org/privatebrowsing;1']
- .getService(Ci.nsIPrivateBrowsingService);
Cu.import('resource://gre/modules/Services.jsm');
function log(str) {
dump(str + '\n');
}
-// watchWindows() and unload() are from Ed Lee's examples at
-// https://github.com/Mardak/restartless/blob/watchWindows/bootstrap.js
-/**
- * Apply a callback to each open and new browser windows.
- *
- * @param {function} callback 1-parameter function that gets a browser window.
- */
-function watchWindows(callback) {
- // Wrap the callback in a function that ignores failures
- function watcher(window) {
- try {
- // Now that the window has loaded, only handle browser windows
- let {documentElement} = window.document;
- if (documentElement.getAttribute('windowtype') == 'navigator:browser')
- callback(window);
- }
- catch (ex) {}
- }
-
- // Wait for the window to finish loading before running the callback
- function runOnLoad(window) {
- // Listen for one load event before checking the window type
- window.addEventListener('load', function runOnce() {
- window.removeEventListener('load', runOnce, false);
- watcher(window);
- }, false);
- }
- // Add functionality to existing windows
- let windows = Services.wm.getEnumerator(null);
- while (windows.hasMoreElements()) {
- // Only run the watcher immediately if the window is completely loaded
- let window = windows.getNext();
- if (window.document.readyState == 'complete')
- watcher(window);
- // Wait for the window to load before continuing
- else
- runOnLoad(window);
- }
- // Watch for new browser windows opening then wait for it to load
- function windowWatcher(subject, topic) {
- if (topic == 'domwindowopened')
- runOnLoad(subject);
- }
- Services.ww.registerNotification(windowWatcher);
-
- // Make sure to stop watching for windows if we're unloading
- unload(function() Services.ww.unregisterNotification(windowWatcher));
-}
-
-/**
- * Save callbacks to run when unloading. Optionally scope the callback to a
- * container, e.g., window. Provide a way to run all the callbacks.
- *
- * @param {function} callback 0-parameter function to call on unload.
- * @param {node} container Remove the callback when this container unloads.
- * @return {function} A 0-parameter function that undoes adding the callback.
- */
-function unload(callback, container) {
- // Initialize the array of unloaders on the first usage
- let unloaders = unload.unloaders;
- if (unloaders == null)
- unloaders = unload.unloaders = [];
-
- // Calling with no arguments runs all the unloader callbacks
- if (callback == null) {
- unloaders.slice().forEach(function(unloader) unloader());
- unloaders.length = 0;
- return;
- }
-
- // The callback is bound to the lifetime of the container if we have one
- if (container != null) {
- // Remove the unloader when the container unloads
- container.addEventListener('unload', removeUnloader, false);
-
- // Wrap the callback to additionally remove the unload listener
- let origCallback = callback;
- callback = function() {
- container.removeEventListener('unload', removeUnloader, false);
- origCallback();
- }
- }
-
- // Wrap the callback in a function that ignores failures
- function unloader() {
- try {
- callback();
- }
- catch (ex) {}
- }
- unloaders.push(unloader);
-
- // Provide a way to remove the unloader
- function removeUnloader() {
- let index = unloaders.indexOf(unloader);
- if (index != -1)
- unloaders.splice(index, 1);
- }
- return removeUnloader;
-}
-
-function messageCallback(event) {
- log(event.target.ownerDocument.currentScript);
- var message = event.target, doc = message.ownerDocument;
- var inPrivateBrowswing = privateBrowsing.privateBrowsingEnabled;
- // Verify the message came from a PDF.
- // TODO
- var action = message.getUserData('action');
- var data = message.getUserData('data');
- switch (action) {
- case 'download':
- Services.wm.getMostRecentWindow('navigator:browser').saveURL(data);
- break;
- case 'setDatabase':
- if (inPrivateBrowswing)
- return;
- application.prefs.setValue(EXT_PREFIX + '.database', data);
- break;
- case 'getDatabase':
- var response;
- if (inPrivateBrowswing)
- response = '{}';
- else
- response = application.prefs.getValue(EXT_PREFIX + '.database', '{}');
- message.setUserData('response', response, null);
- break;
- }
-}
-
-
-// All the boostrap functions:
function startup(aData, aReason) {
let manifestPath = 'chrome.manifest';
let manifest = Cc['@mozilla.org/file/local;1']
} catch (e) {
log(e);
}
-
- watchWindows(function(window) {
- window.addEventListener(PDFJS_EVENT_ID, messageCallback, false, true);
- unload(function() {
- window.removeEventListener(PDFJS_EVENT_ID, messageCallback, false, true);
- });
- });
}
function shutdown(aData, aReason) {
- if (Services.prefs.getBoolPref('extensions.pdf.js.active')) {
+ if (Services.prefs.getBoolPref('extensions.pdf.js.active'))
Services.prefs.setBoolPref('extensions.pdf.js.active', false);
- // Clean up with unloaders when we're deactivating
- if (aReason != APP_SHUTDOWN)
- unload();
- }
}
function install(aData, aReason) {
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
-
+const PDFJS_EVENT_ID = 'pdf.js.message';
const PDF_CONTENT_TYPE = 'application/pdf';
+const NS_ERROR_NOT_IMPLEMENTED = 0x80004001;
+const EXT_PREFIX = 'extensions.uriloader@pdf.js';
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
.logStringMessage(msg);
dump(msg + '\n');
}
+let application = Cc['@mozilla.org/fuel/application;1']
+ .getService(Ci.fuelIApplication);
+let privateBrowsing = Cc['@mozilla.org/privatebrowsing;1']
+ .getService(Ci.nsIPrivateBrowsingService);
+let inPrivateBrowswing = privateBrowsing.privateBrowsingEnabled;
+
+// All the priviledged actions.
+function ChromeActions() {
+ this.inPrivateBrowswing = privateBrowsing.privateBrowsingEnabled;
+}
+ChromeActions.prototype = {
+ download: function(data) {
+ Services.wm.getMostRecentWindow('navigator:browser').saveURL(data);
+ },
+ setDatabase: function() {
+ if (this.inPrivateBrowswing)
+ return;
+ application.prefs.setValue(EXT_PREFIX + '.database', data);
+ },
+ getDatabase: function() {
+ if (this.inPrivateBrowswing)
+ return '{}';
+ return application.prefs.getValue(EXT_PREFIX + '.database', '{}');
+ }
+};
+
+// Event listener to trigger chrome privedged code.
+function RequestListener(actions) {
+ this.actions = actions;
+}
+// Recieves an event and synchronously responds.
+RequestListener.prototype.recieve = function(event) {
+ var message = event.target;
+ var action = message.getUserData('action');
+ var data = message.getUserData('data');
+ var actions = this.actions;
+ if (!(action in actions)) {
+ log('Unknown action: ' + action);
+ return;
+ }
+ var response = actions[action].call(this.actions, data);
+ message.setUserData('response', response, null);
+};
-const NS_ERROR_NOT_IMPLEMENTED = 0x80004001;
function pdfContentHandler() {
}
// nsIRequestObserver::onStartRequest
onStartRequest: function(aRequest, aContext) {
+
// Setup the request so we can use it below.
aRequest.QueryInterface(Ci.nsIChannel);
// Cancel the request so the viewer can handle it.
.getService(Ci.nsIIOService);
var channel = ioService.newChannel(
'resource://pdf.js/web/viewer.html', null, null);
+
// Keep the URL the same so the browser sees it as the same.
channel.originalURI = aRequest.originalURI;
channel.asyncOpen(this.listener, aContext);
+
+ // Setup a global listener waiting for the next DOM to be created and verfiy
+ // that its the one we want by its URL. When the correct DOM is found create
+ // an event listener on that window for the pdf.js events that require
+ // chrome priviledges.
+ var url = aRequest.originalURI.spec;
+ var gb = Services.wm.getMostRecentWindow('navigator:browser');
+ var domListener = function domListener(event) {
+ var doc = event.originalTarget;
+ var win = doc.defaultView;
+ if (doc.location.href === url) {
+ gb.removeEventListener('DOMContentLoaded', domListener);
+ var requestListener = new RequestListener(new ChromeActions());
+ win.addEventListener(PDFJS_EVENT_ID, function(event) {
+ requestListener.recieve(event);
+ }, false, true);
+ }
+ };
+ gb.addEventListener('DOMContentLoaded', domListener, false);
},
// nsIRequestObserver::onStopRequest
onStopRequest: function(aRequest, aContext, aStatusCode) {
// Do nothing.
- return;
}
};