-content/
metadata.inc
chrome.manifest.inc
locale/
resource pdf.js content/
-component {d0c5195d-e798-49d4-b1d3-9324328b2291} components/PdfStreamConverter.js
-contract @mozilla.org/streamconv;1?from=application/pdf&to=*/* {d0c5195d-e798-49d4-b1d3-9324328b2291}
+resource pdf.js.components components/
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
+const MOZ_CENTRAL = PDFJSSCRIPT_MOZ_CENTRAL;
const PDFJS_EVENT_ID = 'pdf.js.message';
const PDF_CONTENT_TYPE = 'application/pdf';
const PREF_PREFIX = 'PDFJSSCRIPT_PREF_PREFIX';
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/NetUtil.jsm');
-Cu.import('resource://gre/modules/AddonManager.jsm');
let appInfo = Cc['@mozilla.org/xre/app-info;1']
.getService(Ci.nsIXULAppInfo);
let privateBrowsing, inPrivateBrowsing;
+let mimeService = Cc['@mozilla.org/mime;1']
+ .getService(Ci.nsIMIMEService);
if (appInfo.ID === FIREFOX_ID) {
privateBrowsing = Cc['@mozilla.org/privatebrowsing;1']
return win;
}
+function isEnabled() {
+ if (MOZ_CENTRAL) {
+ var enabled = getBoolPref(PREF_PREFIX + '.enabled', false);
+ if (!enabled)
+ return false;
+ // To also be considered enabled the "Preview in Firefox" option must be
+ // selected in the Application preferences.
+ var handlerInfo = mimeService.
+ getFromTypeAndExtension('application/pdf', 'pdf');
+ return handlerInfo && (handlerInfo.alwaysAskBeforeHandling == false &&
+ handlerInfo.preferredAction == Ci.nsIHandlerInfo.handleInternally);
+ }
+ // Always returns true for the extension since enabling/disabling is handled
+ // by the add-on manager.
+ return true;
+}
+
function getLocalizedStrings(path) {
var stringBundle = Cc['@mozilla.org/intl/stringbundle;1'].
getService(Ci.nsIStringBundleService).
// nsIStreamConverter::asyncConvertData
asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
+ if (!isEnabled())
+ throw Cr.NS_ERROR_NOT_IMPLEMENTED;
// Ignoring HTTP POST requests -- pdf.js has to repeat the request.
var skipConversion = false;
try {
--- /dev/null
+var EXPORTED_SYMBOLS = ["PdfJs"];
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+const Cr = Components.results;
+const Cm = Components.manager;
+const Cu = Components.utils;
+
+const PREF_PREFIX = 'pdfjs';
+const PREF_ENABLED = PREF_PREFIX + '.enabled';
+const PDFJS_HANDLER_CHANGED = 'pdfjs:handlerChanged';
+
+Cu.import('resource://gre/modules/Services.jsm');
+Cu.import('resource://pdf.js.components/PdfStreamConverter.js');
+
+let mimeService = Cc["@mozilla.org/mime;1"]
+ .getService(Ci.nsIMIMEService);
+
+function getBoolPref(pref, def) {
+ try {
+ return Services.prefs.getBoolPref(pref);
+ } catch (ex) {
+ return def;
+ }
+}
+
+// Register/unregister a class as a component.
+let Factory = {
+ registrar: null,
+ aClass: null,
+ register: function(aClass) {
+ if (this.aClass) {
+ dump('Cannot register more than one class');
+ return;
+ }
+ this.registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+ this.aClass = aClass;
+ var proto = aClass.prototype;
+ this.registrar.registerFactory(proto.classID, proto.classDescription,
+ proto.contractID, this);
+ },
+ unregister: function() {
+ if (!this.aClass) {
+ dump('Class was never registered.');
+ return;
+ }
+ var proto = this.aClass.prototype;
+ this.registrar.unregisterFactory(proto.classID, this);
+ this.aClass = null;
+ },
+ // nsIFactory::createInstance
+ createInstance: function(outer, iid) {
+ if (outer !== null)
+ throw Cr.NS_ERROR_NO_AGGREGATION;
+ return (new (this.aClass)).QueryInterface(iid);
+ }
+};
+
+let PdfJs = {
+ _registered: false,
+ init: function() {
+ if (this.enabled)
+ this._register();
+ else
+ this._unregister();
+
+ // Listen for when pdf.js is completely disabled or a different pdf handler
+ // is chosen.
+ Services.prefs.addObserver(PREF_ENABLED, this, false);
+ Services.obs.addObserver(this, PDFJS_HANDLER_CHANGED, false);
+ },
+ observe: function(subject, topic, data) {
+ if (topic != 'nsPref:changed' && topic != PDFJS_HANDLER_CHANGED)
+ return;
+
+ if (this.enabled)
+ this._register();
+ else
+ this._unregister();
+ },
+ // pdf.js is only enabled if we're both selected as the pdf viewer and if the
+ // global switch enabling us is true.
+ get enabled() {
+ var handlerInfo = mimeService.
+ getFromTypeAndExtension('application/pdf', 'pdf');
+
+ var selectedAsHandler = handlerInfo && (handlerInfo.alwaysAskBeforeHandling == false &&
+ handlerInfo.preferredAction == Ci.nsIHandlerInfo.handleInternally);
+ return getBoolPref(PREF_ENABLED, false) && selectedAsHandler;
+ },
+ _register: function() {
+ if (this._registered)
+ return;
+
+ Factory.register(PdfStreamConverter);
+ this._registered = true;
+ },
+ _unregister: function() {
+ if (!this._registered)
+ return;
+
+ Factory.unregister();
+ this._registered = false;
+ }
+};
sed('-i', /PDFJSSCRIPT_STREAM_CONVERTER_ID/, FIREFOX_STREAM_CONVERTER_ID, FIREFOX_BUILD_DIR + 'components/PdfStreamConverter.js');
sed('-i', /PDFJSSCRIPT_PREF_PREFIX/, FIREFOX_PREF_PREFIX, FIREFOX_BUILD_DIR + 'components/PdfStreamConverter.js');
+ sed('-i', /PDFJSSCRIPT_MOZ_CENTRAL/, 'false', FIREFOX_BUILD_DIR + 'components/PdfStreamConverter.js');
// Update localized metadata
var localizedMetadata = cat(EXTENSION_SRC_DIR + '/firefox/metadata.inc');
mkdir('-p', MOZCENTRAL_CONTENT_DIR + BUILD_DIR);
mkdir('-p', MOZCENTRAL_CONTENT_DIR + '/web');
+ cp(FIREFOX_CONTENT_DIR + 'PdfJs.jsm', MOZCENTRAL_CONTENT_DIR)
+
// Copy extension files
cd('extensions/firefox');
cp('-R', FIREFOX_EXTENSION_FILES_TO_COPY, ROOT_DIR + MOZCENTRAL_EXTENSION_DIR);
sed('-i', /PDFJSSCRIPT_STREAM_CONVERTER_ID/, MOZCENTRAL_STREAM_CONVERTER_ID, MOZCENTRAL_EXTENSION_DIR + 'components/PdfStreamConverter.js');
sed('-i', /PDFJSSCRIPT_PREF_PREFIX/, MOZCENTRAL_PREF_PREFIX, MOZCENTRAL_EXTENSION_DIR + 'components/PdfStreamConverter.js');
+ sed('-i', /PDFJSSCRIPT_MOZ_CENTRAL/, 'true', MOZCENTRAL_EXTENSION_DIR + 'components/PdfStreamConverter.js');
// List all files for mozilla-central
cd(MOZCENTRAL_EXTENSION_DIR);
_BROWSER_TEST_FILES = \
browser_pdfjs_main.js \
+ browser_pdfjs_savedialog.js \
file_pdfjs_test.pdf \
$(NULL)
const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
function test() {
- var tab;
+ var tab, oldAction;
+
+ oldAction = changeMimeHandler();
+
+ const Cc = Components.classes;
+ const Ci = Components.interfaces;
+ let handlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension('application/pdf', 'pdf');
+
+ info('Pref action: ' + handlerInfo.preferredAction);
waitForExplicitFinish();
registerCleanupFunction(function() {
// Runs tests after all 'load' event handlers have fired off
setTimeout(function() {
- runTests(document, window);
+ runTests(document, window, function() {
+ revertMimeHandler(oldAction);
+ finish();
+ });
}, 0);
}, true);
}
-function runTests(document, window) {
+function changeMimeHandler() {
+ let oldAction;
+
+ const Cc = Components.classes;
+ const Ci = Components.interfaces;
+ let handlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension('application/pdf', 'pdf');
+
+ oldAction = handlerInfo.preferredAction;
+
+ // Change and save mime handler settings
+ handlerInfo.alwaysAskBeforeHandling = false;
+ handlerInfo.preferredAction = Ci.nsIHandlerInfo.handleInternally;
+ handlerService.store(handlerInfo);
+
+ Services.obs.notifyObservers(null, 'pdfjs:handlerChanged', null);
+
+ // Refresh data
+ mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ handlerInfo = mimeService.getFromTypeAndExtension('application/pdf', 'pdf');
+
+ //
+ // Test: Mime handler was updated
+ //
+ is(handlerInfo.alwaysAskBeforeHandling, false, 'always-ask prompt change successful');
+ is(handlerInfo.preferredAction, Ci.nsIHandlerInfo.handleInternally, 'mime handler change successful');
+
+ return oldAction;
+}
+
+function revertMimeHandler(oldAction) {
+ const Cc = Components.classes;
+ const Ci = Components.interfaces;
+ let handlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension('application/pdf', 'pdf');
+
+ // Change and save mime handler settings
+ handlerInfo.alwaysAskBeforeHandling = true;
+ handlerInfo.preferredAction = oldAction;
+ handlerService.store(handlerInfo);
+}
+
+
+function runTests(document, window, callback) {
+
//
// Overall sanity tests
//
viewBookmark.click();
ok(viewBookmark.href.length > 0, 'viewBookmark button has href');
- finish();
+ callback();
}
--- /dev/null
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+const RELATIVE_DIR = "browser/extensions/pdfjs/test/";
+const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
+
+function test() {
+ var tab;
+
+ const Cc = Components.classes;
+ const Ci = Components.interfaces;
+ let handlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
+ let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+ let handlerInfo = mimeService.getFromTypeAndExtension('application/pdf', 'pdf');
+
+ //
+ // Test: Default mime handler
+ //
+ is(handlerInfo.alwaysAskBeforeHandling, true, 'mime handler: default is always-ask prompt');
+
+ //
+ // Test: "Open with" dialog comes up
+ //
+ addWindowListener('chrome://mozapps/content/downloads/unknownContentType.xul', finish);
+
+ waitForExplicitFinish();
+ registerCleanupFunction(function() {
+ gBrowser.removeTab(tab);
+ });
+
+ tab = gBrowser.addTab(TESTROOT + "file_pdfjs_test.pdf");
+ var newTabBrowser = gBrowser.getBrowserForTab(tab);
+}
+
+
+function addWindowListener(aURL, aCallback) {
+ Services.wm.addListener({
+ onOpenWindow: function(aXULWindow) {
+ info("window opened, waiting for focus");
+ Services.wm.removeListener(this);
+
+ var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindow);
+ waitForFocus(function() {
+ is(domwindow.document.location.href, aURL, "should have seen the right window open");
+ domwindow.close();
+ aCallback();
+ }, domwindow);
+ },
+ onCloseWindow: function(aXULWindow) { },
+ onWindowTitleChange: function(aXULWindow, aNewTitle) { }
+ });
+}