summaryrefslogtreecommitdiffstats
path: root/browser/extensions/pdfjs/content/PdfJs.jsm
diff options
context:
space:
mode:
Diffstat (limited to 'browser/extensions/pdfjs/content/PdfJs.jsm')
-rw-r--r--browser/extensions/pdfjs/content/PdfJs.jsm348
1 files changed, 348 insertions, 0 deletions
diff --git a/browser/extensions/pdfjs/content/PdfJs.jsm b/browser/extensions/pdfjs/content/PdfJs.jsm
new file mode 100644
index 000000000..b3d85436e
--- /dev/null
+++ b/browser/extensions/pdfjs/content/PdfJs.jsm
@@ -0,0 +1,348 @@
+/* Copyright 2012 Mozilla Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* jshint esnext:true */
+/* globals Components, Services, XPCOMUtils, PdfjsChromeUtils,
+ PdfjsContentUtils, PdfStreamConverter */
+
+'use strict';
+
+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_DISABLED = PREF_PREFIX + '.disabled';
+const PREF_MIGRATION_VERSION = PREF_PREFIX + '.migrationVersion';
+const PREF_PREVIOUS_ACTION = PREF_PREFIX + '.previousHandler.preferredAction';
+const PREF_PREVIOUS_ASK = PREF_PREFIX +
+ '.previousHandler.alwaysAskBeforeHandling';
+const PREF_DISABLED_PLUGIN_TYPES = 'plugin.disable_full_page_plugin_for_types';
+const TOPIC_PDFJS_HANDLER_CHANGED = 'pdfjs:handlerChanged';
+const TOPIC_PLUGINS_LIST_UPDATED = 'plugins-list-updated';
+const TOPIC_PLUGIN_INFO_UPDATED = 'plugin-info-updated';
+const PDF_CONTENT_TYPE = 'application/pdf';
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+Cu.import('resource://gre/modules/Services.jsm');
+
+var Svc = {};
+XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
+ '@mozilla.org/mime;1',
+ 'nsIMIMEService');
+XPCOMUtils.defineLazyServiceGetter(Svc, 'pluginHost',
+ '@mozilla.org/plugin/host;1',
+ 'nsIPluginHost');
+XPCOMUtils.defineLazyModuleGetter(this, 'PdfjsChromeUtils',
+ 'resource://pdf.js/PdfjsChromeUtils.jsm');
+XPCOMUtils.defineLazyModuleGetter(this, 'PdfjsContentUtils',
+ 'resource://pdf.js/PdfjsContentUtils.jsm');
+
+function getBoolPref(aPref, aDefaultValue) {
+ try {
+ return Services.prefs.getBoolPref(aPref);
+ } catch (ex) {
+ return aDefaultValue;
+ }
+}
+
+function getIntPref(aPref, aDefaultValue) {
+ try {
+ return Services.prefs.getIntPref(aPref);
+ } catch (ex) {
+ return aDefaultValue;
+ }
+}
+
+function isDefaultHandler() {
+ if (Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_CONTENT) {
+ return PdfjsContentUtils.isDefaultHandlerApp();
+ }
+ return PdfjsChromeUtils.isDefaultHandlerApp();
+}
+
+function initializeDefaultPreferences() {
+ var DEFAULT_PREFERENCES =
+{
+ "showPreviousViewOnLoad": true,
+ "defaultZoomValue": "",
+ "sidebarViewOnLoad": 0,
+ "enableHandToolOnLoad": false,
+ "enableWebGL": false,
+ "pdfBugEnabled": false,
+ "disableRange": false,
+ "disableStream": false,
+ "disableAutoFetch": false,
+ "disableFontFace": false,
+ "disableTextLayer": false,
+ "useOnlyCssZoom": false,
+ "externalLinkTarget": 0,
+ "enhanceTextSelection": false,
+ "renderInteractiveForms": false,
+ "disablePageLabels": false
+}
+
+
+ var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.');
+ var defaultValue;
+ for (var key in DEFAULT_PREFERENCES) {
+ defaultValue = DEFAULT_PREFERENCES[key];
+ switch (typeof defaultValue) {
+ case 'boolean':
+ defaultBranch.setBoolPref(key, defaultValue);
+ break;
+ case 'number':
+ defaultBranch.setIntPref(key, defaultValue);
+ break;
+ case 'string':
+ defaultBranch.setCharPref(key, defaultValue);
+ break;
+ }
+ }
+}
+
+// Register/unregister a constructor as a factory.
+function Factory() {}
+Factory.prototype = {
+ register: function register(targetConstructor) {
+ var proto = targetConstructor.prototype;
+ this._classID = proto.classID;
+
+ var factory = XPCOMUtils._getFactory(targetConstructor);
+ this._factory = factory;
+
+ var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+ registrar.registerFactory(proto.classID, proto.classDescription,
+ proto.contractID, factory);
+
+ if (proto.classID2) {
+ this._classID2 = proto.classID2;
+ registrar.registerFactory(proto.classID2, proto.classDescription,
+ proto.contractID2, factory);
+ }
+ },
+
+ unregister: function unregister() {
+ var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
+ registrar.unregisterFactory(this._classID, this._factory);
+ if (this._classID2) {
+ registrar.unregisterFactory(this._classID2, this._factory);
+ }
+ this._factory = null;
+ }
+};
+
+var PdfJs = {
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
+ _registered: false,
+ _initialized: false,
+
+ init: function init(remote) {
+ if (Services.appinfo.processType !==
+ Services.appinfo.PROCESS_TYPE_DEFAULT) {
+ throw new Error('PdfJs.init should only get called ' +
+ 'in the parent process.');
+ }
+ PdfjsChromeUtils.init();
+ if (!remote) {
+ PdfjsContentUtils.init();
+ }
+ this.initPrefs();
+ this.updateRegistration();
+ },
+
+ initPrefs: function initPrefs() {
+ if (this._initialized) {
+ return;
+ }
+ this._initialized = true;
+
+ if (!getBoolPref(PREF_DISABLED, true)) {
+ this._migrate();
+ }
+
+ // Listen for when pdf.js is completely disabled or a different pdf handler
+ // is chosen.
+ Services.prefs.addObserver(PREF_DISABLED, this, false);
+ Services.prefs.addObserver(PREF_DISABLED_PLUGIN_TYPES, this, false);
+ Services.obs.addObserver(this, TOPIC_PDFJS_HANDLER_CHANGED, false);
+ Services.obs.addObserver(this, TOPIC_PLUGINS_LIST_UPDATED, false);
+ Services.obs.addObserver(this, TOPIC_PLUGIN_INFO_UPDATED, false);
+
+ initializeDefaultPreferences();
+ },
+
+ updateRegistration: function updateRegistration() {
+ if (this.enabled) {
+ this._ensureRegistered();
+ } else {
+ this._ensureUnregistered();
+ }
+ },
+
+ uninit: function uninit() {
+ if (this._initialized) {
+ Services.prefs.removeObserver(PREF_DISABLED, this, false);
+ Services.prefs.removeObserver(PREF_DISABLED_PLUGIN_TYPES, this, false);
+ Services.obs.removeObserver(this, TOPIC_PDFJS_HANDLER_CHANGED, false);
+ Services.obs.removeObserver(this, TOPIC_PLUGINS_LIST_UPDATED, false);
+ Services.obs.removeObserver(this, TOPIC_PLUGIN_INFO_UPDATED, false);
+ this._initialized = false;
+ }
+ this._ensureUnregistered();
+ },
+
+ _migrate: function migrate() {
+ const VERSION = 2;
+ var currentVersion = getIntPref(PREF_MIGRATION_VERSION, 0);
+ if (currentVersion >= VERSION) {
+ return;
+ }
+ // Make pdf.js the default pdf viewer on the first migration.
+ if (currentVersion < 1) {
+ this._becomeHandler();
+ }
+ if (currentVersion < 2) {
+ // cleaning up of unused database preference (see #3994)
+ Services.prefs.clearUserPref(PREF_PREFIX + '.database');
+ }
+ Services.prefs.setIntPref(PREF_MIGRATION_VERSION, VERSION);
+ },
+
+ _becomeHandler: function _becomeHandler() {
+ let handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, 'pdf');
+ let prefs = Services.prefs;
+ if (handlerInfo.preferredAction !== Ci.nsIHandlerInfo.handleInternally &&
+ handlerInfo.preferredAction !== false) {
+ // Store the previous settings of preferredAction and
+ // alwaysAskBeforeHandling in case we need to revert them in a hotfix that
+ // would turn pdf.js off.
+ prefs.setIntPref(PREF_PREVIOUS_ACTION, handlerInfo.preferredAction);
+ prefs.setBoolPref(PREF_PREVIOUS_ASK, handlerInfo.alwaysAskBeforeHandling);
+ }
+
+ let handlerService = Cc['@mozilla.org/uriloader/handler-service;1'].
+ getService(Ci.nsIHandlerService);
+
+ // Change and save mime handler settings.
+ handlerInfo.alwaysAskBeforeHandling = false;
+ handlerInfo.preferredAction = Ci.nsIHandlerInfo.handleInternally;
+ handlerService.store(handlerInfo);
+
+ // Also disable any plugins for pdfs.
+ var stringTypes = '';
+ var types = [];
+ if (prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES)) {
+ stringTypes = prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES);
+ }
+ if (stringTypes !== '') {
+ types = stringTypes.split(',');
+ }
+
+ if (types.indexOf(PDF_CONTENT_TYPE) === -1) {
+ types.push(PDF_CONTENT_TYPE);
+ }
+ prefs.setCharPref(PREF_DISABLED_PLUGIN_TYPES, types.join(','));
+
+ // Update the category manager in case the plugins are already loaded.
+ let categoryManager = Cc['@mozilla.org/categorymanager;1'];
+ categoryManager.getService(Ci.nsICategoryManager).
+ deleteCategoryEntry('Gecko-Content-Viewers',
+ PDF_CONTENT_TYPE,
+ false);
+ },
+
+ // nsIObserver
+ observe: function observe(aSubject, aTopic, aData) {
+ this.updateRegistration();
+ if (Services.appinfo.processType ===
+ Services.appinfo.PROCESS_TYPE_DEFAULT) {
+ let jsm = 'resource://pdf.js/PdfjsChromeUtils.jsm';
+ let PdfjsChromeUtils = Components.utils.import(jsm, {}).PdfjsChromeUtils;
+ PdfjsChromeUtils.notifyChildOfSettingsChange();
+ }
+ },
+
+ /**
+ * pdf.js is only enabled if it is both selected as the pdf viewer and if the
+ * global switch enabling it is true.
+ * @return {boolean} Whether or not it's enabled.
+ */
+ get enabled() {
+ var disabled = getBoolPref(PREF_DISABLED, true);
+ if (disabled) {
+ return false;
+ }
+
+ // Check if the 'application/pdf' preview handler is configured properly.
+ if (!isDefaultHandler()) {
+ return false;
+ }
+
+ // Check if we have disabled plugin handling of 'application/pdf' in prefs
+ if (Services.prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES)) {
+ let disabledPluginTypes =
+ Services.prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES).split(',');
+ if (disabledPluginTypes.indexOf(PDF_CONTENT_TYPE) >= 0) {
+ return true;
+ }
+ }
+
+ // Check if there is an enabled pdf plugin.
+ // Note: this check is performed last because getPluginTags() triggers
+ // costly plugin list initialization (bug 881575)
+ let tags = Cc['@mozilla.org/plugin/host;1'].
+ getService(Ci.nsIPluginHost).
+ getPluginTags();
+ let enabledPluginFound = tags.some(function(tag) {
+ if (tag.disabled) {
+ return false;
+ }
+ let mimeTypes = tag.getMimeTypes();
+ return mimeTypes.some(function(mimeType) {
+ return mimeType === PDF_CONTENT_TYPE;
+ });
+ });
+
+ // Use pdf.js if pdf plugin is not present or disabled
+ return !enabledPluginFound;
+ },
+
+ _ensureRegistered: function _ensureRegistered() {
+ if (this._registered) {
+ return;
+ }
+ this._pdfStreamConverterFactory = new Factory();
+ Cu.import('resource://pdf.js/PdfStreamConverter.jsm');
+ this._pdfStreamConverterFactory.register(PdfStreamConverter);
+
+ this._registered = true;
+ },
+
+ _ensureUnregistered: function _ensureUnregistered() {
+ if (!this._registered) {
+ return;
+ }
+ this._pdfStreamConverterFactory.unregister();
+ Cu.unload('resource://pdf.js/PdfStreamConverter.jsm');
+ delete this._pdfStreamConverterFactory;
+
+ this._registered = false;
+ }
+};
+