From 1cda4c7a4b101cb4b8cb704a72a043ee9a1750d7 Mon Sep 17 00:00:00 2001 From: Yury Delendik Date: Wed, 17 Sep 2014 16:14:04 -0500 Subject: [PATCH] Loading PDF.js extension into e10s windows --- extensions/firefox/bootstrap.js | 44 ++++++++++--- extensions/firefox/chrome.manifest | 2 + extensions/firefox/chrome/content.js | 98 ++++++++++++++++++++++++++++ extensions/firefox/install.rdf | 1 + make.js | 19 +++--- 5 files changed, 148 insertions(+), 16 deletions(-) create mode 100644 extensions/firefox/chrome/content.js diff --git a/extensions/firefox/bootstrap.js b/extensions/firefox/bootstrap.js index ebd6ff682..6d1f3dd92 100644 --- a/extensions/firefox/bootstrap.js +++ b/extensions/firefox/bootstrap.js @@ -16,7 +16,8 @@ */ /* jshint esnext:true */ /* globals Components, Services, dump, XPCOMUtils, PdfStreamConverter, - PdfRedirector, APP_SHUTDOWN, DEFAULT_PREFERENCES */ + PdfRedirector, APP_SHUTDOWN, PdfjsChromeUtils, PdfjsContentUtils, + DEFAULT_PREFERENCES */ 'use strict'; @@ -108,10 +109,10 @@ Factory.prototype = { } }; -var pdfStreamConverterUrl = null; var pdfStreamConverterFactory = new Factory(); -var pdfRedirectorUrl = null; +var pdfBaseUrl = null; var pdfRedirectorFactory = new Factory(); +var e10sEnabled = false; // As of Firefox 13 bootstrapped add-ons don't support automatic registering and // unregistering of resource urls and components/contracts. Until then we do @@ -125,15 +126,20 @@ function startup(aData, aReason) { var aliasURI = ioService.newURI('content/', 'UTF-8', aData.resourceURI); resProt.setSubstitution(RESOURCE_NAME, aliasURI); + pdfBaseUrl = aData.resourceURI.spec; + + Cu.import(pdfBaseUrl + 'content/PdfjsChromeUtils.jsm'); + PdfjsChromeUtils.init(); + Cu.import(pdfBaseUrl + 'content/PdfjsContentUtils.jsm'); + PdfjsContentUtils.init(); + // Load the component and register it. - pdfStreamConverterUrl = aData.resourceURI.spec + - 'content/PdfStreamConverter.jsm'; + var pdfStreamConverterUrl = pdfBaseUrl + 'content/PdfStreamConverter.jsm'; Cu.import(pdfStreamConverterUrl); pdfStreamConverterFactory.register(PdfStreamConverter); if (registerOverlayPreview) { - pdfRedirectorUrl = aData.resourceURI.spec + - 'content/PdfRedirector.jsm'; + var pdfRedirectorUrl = pdfBaseUrl + 'content/PdfRedirector.jsm'; Cu.import(pdfRedirectorUrl); pdfRedirectorFactory.register(PdfRedirector); @@ -141,6 +147,14 @@ function startup(aData, aReason) { 'data:application/x-moz-playpreview-pdfjs;,'); } + try { + let globalMM = Cc['@mozilla.org/globalmessagemanager;1'] + .getService(Ci.nsIFrameScriptLoader); + globalMM.loadFrameScript('chrome://pdf.js/content/content.js', true); + e10sEnabled = true; + } catch (ex) { + } + initializeDefaultPreferences(); } @@ -148,6 +162,14 @@ function shutdown(aData, aReason) { if (aReason === APP_SHUTDOWN) { return; } + + if (e10sEnabled) { + let globalMM = Cc['@mozilla.org/globalmessagemanager;1'] + .getService(Ci.nsIMessageBroadcaster); + globalMM.broadcastAsyncMessage('PDFJS:Child:shutdown'); + globalMM.removeDelayedFrameScript('chrome://pdf.js/content/content.js'); + } + var ioService = Services.io; var resProt = ioService.getProtocolHandler('resource') .QueryInterface(Ci.nsIResProtocolHandler); @@ -156,16 +178,22 @@ function shutdown(aData, aReason) { // Remove the contract/component. pdfStreamConverterFactory.unregister(); // Unload the converter + var pdfStreamConverterUrl = pdfBaseUrl + 'content/PdfStreamConverter.jsm'; Cu.unload(pdfStreamConverterUrl); - pdfStreamConverterUrl = null; if (registerOverlayPreview) { pdfRedirectorFactory.unregister(); + var pdfRedirectorUrl = pdfBaseUrl + 'content/PdfRedirector.jsm'; Cu.unload(pdfRedirectorUrl); pdfRedirectorUrl = null; Ph.unregisterPlayPreviewMimeType('application/pdf'); } + + PdfjsContentUtils.uninit(); + Cu.unload(pdfBaseUrl + 'content/PdfjsContentUtils.jsm'); + PdfjsChromeUtils.uninit(); + Cu.unload(pdfBaseUrl + 'content/PdfjsChromeUtils.jsm'); } function install(aData, aReason) { diff --git a/extensions/firefox/chrome.manifest b/extensions/firefox/chrome.manifest index 97b76306b..1a92e73ac 100644 --- a/extensions/firefox/chrome.manifest +++ b/extensions/firefox/chrome.manifest @@ -1,3 +1,5 @@ # Additional resources for pdf.js +content pdf.js chrome/ + # PDFJS_SUPPORTED_LOCALES diff --git a/extensions/firefox/chrome/content.js b/extensions/firefox/chrome/content.js new file mode 100644 index 000000000..982aa7d8a --- /dev/null +++ b/extensions/firefox/chrome/content.js @@ -0,0 +1,98 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ +/* Copyright 2014 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, PdfjsContentUtils, + PdfjsContentUtils, PdfStreamConverter, addMessageListener */ + +'use strict'; + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cm = Components.manager; +const Cu = Components.utils; +const Cr = Components.results; + +Cu.import('resource://gre/modules/XPCOMUtils.jsm'); +Cu.import('resource://gre/modules/Services.jsm'); + +var isRemote = Services.appinfo.processType === + Services.appinfo.PROCESS_TYPE_CONTENT; + +// Factory that registers/unregisters a constructor as a component. +function Factory() {} + +Factory.prototype = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]), + _targetConstructor: null, + + register: function register(targetConstructor) { + this._targetConstructor = targetConstructor; + var proto = targetConstructor.prototype; + var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar); + registrar.registerFactory(proto.classID, proto.classDescription, + proto.contractID, this); + }, + + unregister: function unregister() { + var proto = this._targetConstructor.prototype; + var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar); + registrar.unregisterFactory(proto.classID, this); + this._targetConstructor = null; + }, + + // nsIFactory + createInstance: function createInstance(aOuter, iid) { + if (aOuter !== null) { + throw Cr.NS_ERROR_NO_AGGREGATION; + } + return (new (this._targetConstructor)()).QueryInterface(iid); + }, + + // nsIFactory + lockFactory: function lockFactory(lock) { + // No longer used as of gecko 1.7. + throw Cr.NS_ERROR_NOT_IMPLEMENTED; + } +}; + +var pdfStreamConverterFactory = new Factory(); + +function startup() { + Cu.import('resource://pdf.js/PdfjsContentUtils.jsm'); + PdfjsContentUtils.init(); + + Cu.import('resource://pdf.js/PdfStreamConverter.jsm'); + pdfStreamConverterFactory.register(PdfStreamConverter); +} + +function shutdown() { + // Remove the contract/component. + pdfStreamConverterFactory.unregister(); + // Unload the converter + Cu.unload('resource://pdf.js/PdfStreamConverter.jsm'); + + PdfjsContentUtils.uninit(); + Cu.unload('resource://pdf.js/PdfjsContentUtils.jsm'); +} + +if (isRemote) { + startup(); + + addMessageListener('PDFJS:Child:shutdown', function (e) { + shutdown(); + }); +} diff --git a/extensions/firefox/install.rdf b/extensions/firefox/install.rdf index 8b18b783b..041e58934 100644 --- a/extensions/firefox/install.rdf +++ b/extensions/firefox/install.rdf @@ -46,6 +46,7 @@ true + true Mozilla Uses HTML5 to display PDF files directly in Firefox. https://github.com/mozilla/pdf.js/ diff --git a/make.js b/make.js index f923bc625..1d01b771d 100644 --- a/make.js +++ b/make.js @@ -44,6 +44,7 @@ var ROOT_DIR = __dirname + '/', // absolute path to project's root B2G_BUILD_DIR = BUILD_DIR + '/b2g/', JSDOC_DIR = BUILD_DIR + 'jsdoc', EXTENSION_SRC_DIR = 'extensions/', + FIREFOX_CONTENT_DIR = EXTENSION_SRC_DIR + '/firefox/content/', LOCALE_SRC_DIR = 'l10n/', GH_PAGES_DIR = BUILD_DIR + 'gh-pages/', GENERIC_DIR = BUILD_DIR + 'generic/', @@ -91,8 +92,12 @@ var COMMON_WEB_FILES = 'web/debugger.js'], COMMON_WEB_FILES_PREPROCESS = ['web/viewer.js', - 'web/viewer.html']; - + 'web/viewer.html'], + COMMON_FIREFOX_FILES_PREPROCESS = + [FIREFOX_CONTENT_DIR + 'PdfStreamConverter.jsm', + FIREFOX_CONTENT_DIR + 'PdfjsContentUtils.jsm', + FIREFOX_CONTENT_DIR + 'PdfjsChromeUtils.jsm', + FIREFOX_CONTENT_DIR + 'PdfRedirector.jsm']; // // make generic // Builds the generic production viewer that should be compatible with most @@ -584,7 +589,6 @@ target.firefox = function() { var FIREFOX_BUILD_CONTENT_DIR = FIREFOX_BUILD_DIR + '/content/', FIREFOX_EXTENSION_DIR = 'extensions/firefox/', - FIREFOX_CONTENT_DIR = EXTENSION_SRC_DIR + '/firefox/content/', FIREFOX_EXTENSION_FILES_TO_COPY = ['*.js', '*.rdf', @@ -592,6 +596,7 @@ target.firefox = function() { '*.png', '*.manifest', 'locale', + 'chrome', '../../LICENSE'], FIREFOX_EXTENSION_FILES = ['bootstrap.js', @@ -600,6 +605,7 @@ target.firefox = function() { 'icon.png', 'icon64.png', 'content', + 'chrome', 'locale', 'LICENSE'], FIREFOX_EXTENSION_NAME = 'pdf.js.xpi', @@ -639,9 +645,7 @@ target.firefox = function() { preprocess: [ [COMMON_WEB_FILES_PREPROCESS, FIREFOX_BUILD_CONTENT_DIR + '/web'], [BUILD_TARGETS, FIREFOX_BUILD_CONTENT_DIR + BUILD_DIR], - [FIREFOX_CONTENT_DIR + 'PdfStreamConverter.jsm', - FIREFOX_BUILD_CONTENT_DIR], - [FIREFOX_CONTENT_DIR + 'PdfRedirector.jsm', FIREFOX_BUILD_CONTENT_DIR], + [COMMON_FIREFOX_FILES_PREPROCESS, FIREFOX_BUILD_CONTENT_DIR], [SRC_DIR + 'core/network.js', FIREFOX_BUILD_CONTENT_DIR], [FIREFOX_EXTENSION_DIR + 'bootstrap.js', FIREFOX_BUILD_DIR] ], @@ -759,8 +763,7 @@ target.mozcentral = function() { [COMMON_WEB_FILES_PREPROCESS, MOZCENTRAL_CONTENT_DIR + '/web'], [BUILD_TARGETS, MOZCENTRAL_CONTENT_DIR + BUILD_DIR], [SRC_DIR + 'core/network.js', MOZCENTRAL_CONTENT_DIR], - [FIREFOX_CONTENT_DIR + 'PdfStreamConverter.jsm', MOZCENTRAL_CONTENT_DIR], - [FIREFOX_CONTENT_DIR + 'PdfRedirector.jsm', MOZCENTRAL_CONTENT_DIR], + [COMMON_FIREFOX_FILES_PREPROCESS, MOZCENTRAL_CONTENT_DIR], [FIREFOX_CONTENT_DIR + 'PdfJs.jsm', MOZCENTRAL_CONTENT_DIR] ], preprocessCSS: [