|
|
@ -3,17 +3,155 @@ |
|
|
|
|
|
|
|
|
|
|
|
'use strict'; |
|
|
|
'use strict'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const EXT_PREFIX = 'extensions.uriloader@pdf.js'; |
|
|
|
|
|
|
|
const PDFJS_EVENT_ID = 'pdf.js.message'; |
|
|
|
let Cc = Components.classes; |
|
|
|
let Cc = Components.classes; |
|
|
|
let Ci = Components.interfaces; |
|
|
|
let Ci = Components.interfaces; |
|
|
|
let Cm = Components.manager; |
|
|
|
let Cm = Components.manager; |
|
|
|
let Cu = Components.utils; |
|
|
|
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'); |
|
|
|
Cu.import('resource://gre/modules/Services.jsm'); |
|
|
|
|
|
|
|
|
|
|
|
function log(str) { |
|
|
|
function log(str) { |
|
|
|
dump(str + '\n'); |
|
|
|
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) { |
|
|
|
function startup(aData, aReason) { |
|
|
|
let manifestPath = 'chrome.manifest'; |
|
|
|
let manifestPath = 'chrome.manifest'; |
|
|
|
let manifest = Cc['@mozilla.org/file/local;1'] |
|
|
|
let manifest = Cc['@mozilla.org/file/local;1'] |
|
|
@ -26,11 +164,22 @@ function startup(aData, aReason) { |
|
|
|
} catch (e) { |
|
|
|
} catch (e) { |
|
|
|
log(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) { |
|
|
|
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); |
|
|
|
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) { |
|
|
|
function install(aData, aReason) { |
|
|
@ -39,5 +188,6 @@ function install(aData, aReason) { |
|
|
|
|
|
|
|
|
|
|
|
function uninstall(aData, aReason) { |
|
|
|
function uninstall(aData, aReason) { |
|
|
|
Services.prefs.clearUserPref('extensions.pdf.js.active'); |
|
|
|
Services.prefs.clearUserPref('extensions.pdf.js.active'); |
|
|
|
|
|
|
|
application.prefs.setValue(EXT_PREFIX + '.database', '{}'); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|