From 681a500716b05ad6a7cf2f83bd716c873b267314 Mon Sep 17 00:00:00 2001 From: Cosmin Sabou Date: Thu, 2 Aug 2018 11:16:01 +0300 Subject: [PATCH] Backed out changeset f0ccbdcaa8a1 (bug 1479245) for causing a spike on timeouts on browser_pdfjs_views.js --HG-- rename : browser/extensions/pdfjs/pdfjs.js => browser/extensions/pdfjs/content/PdfJsRegistration.jsm --- .../performance/browser_startup_content.js | 4 + browser/components/nsBrowserGlue.js | 9 ++ browser/extensions/pdfjs/content/PdfJs.jsm | 33 ++++++- .../pdfjs/content/PdfJsRegistration.jsm | 89 +++++++++++++++++++ .../pdfjs/content/PdfjsChromeUtils.jsm | 19 ++++ .../pdfjs/content/PdfjsContentUtils.jsm | 49 +++++++++- .../content/pdfjschildbootstrap-enabled.js | 30 +++++++ .../pdfjs/content/pdfjschildbootstrap.js | 26 ++++++ browser/extensions/pdfjs/moz.build | 5 -- browser/extensions/pdfjs/pdfjs.js | 37 -------- browser/extensions/pdfjs/pdfjs.manifest | 3 - browser/installer/package-manifest.in | 4 - dom/base/nsContentUtils.cpp | 12 ++- 13 files changed, 263 insertions(+), 57 deletions(-) create mode 100644 browser/extensions/pdfjs/content/PdfJsRegistration.jsm create mode 100644 browser/extensions/pdfjs/content/pdfjschildbootstrap-enabled.js create mode 100644 browser/extensions/pdfjs/content/pdfjschildbootstrap.js delete mode 100644 browser/extensions/pdfjs/pdfjs.js delete mode 100644 browser/extensions/pdfjs/pdfjs.manifest diff --git a/browser/base/content/test/performance/browser_startup_content.js b/browser/base/content/test/performance/browser_startup_content.js index fd4f4503e713..e99a78a0ea0c 100644 --- a/browser/base/content/test/performance/browser_startup_content.js +++ b/browser/base/content/test/performance/browser_startup_content.js @@ -64,6 +64,10 @@ const whitelist = { "resource://gre/modules/TelemetrySession.jsm", // bug 1470339 "resource://gre/modules/TelemetryUtils.jsm", // bug 1470339 + // PDF.js + "resource://pdf.js/PdfJsRegistration.jsm", + "resource://pdf.js/PdfjsContentUtils.jsm", + // Extensions "resource://gre/modules/ExtensionUtils.jsm", "resource://gre/modules/MessageChannel.jsm", diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js index 612d4b229017..a3db91ef2401 100644 --- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -968,6 +968,15 @@ BrowserGlue.prototype = { // the first browser window has finished initializing _onFirstWindowLoaded: function BG__onFirstWindowLoaded(aWindow) { + // Set up listeners and, if PdfJs is enabled, register the PDF stream converter. + // We delay all of the parent's initialization other than stream converter + // registration, because it requires file IO from HandlerService.js + Services.ppmm.loadProcessScript("resource://pdf.js/pdfjschildbootstrap.js", true); + if (PdfJs.enabled) { + PdfJs.ensureRegistered(); + Services.ppmm.loadProcessScript("resource://pdf.js/pdfjschildbootstrap-enabled.js", true); + } + TabCrashHandler.init(); if (AppConstants.MOZ_CRASHREPORTER) { PluginCrashReporter.init(); diff --git a/browser/extensions/pdfjs/content/PdfJs.jsm b/browser/extensions/pdfjs/content/PdfJs.jsm index 645e40d21c8f..b4d6863e36d2 100644 --- a/browser/extensions/pdfjs/content/PdfJs.jsm +++ b/browser/extensions/pdfjs/content/PdfJs.jsm @@ -45,8 +45,12 @@ XPCOMUtils.defineLazyServiceGetter(Svc, "pluginHost", "nsIPluginHost"); ChromeUtils.defineModuleGetter(this, "PdfjsChromeUtils", "resource://pdf.js/PdfjsChromeUtils.jsm"); +ChromeUtils.defineModuleGetter(this, "PdfjsContentUtils", + "resource://pdf.js/PdfjsContentUtils.jsm"); ChromeUtils.defineModuleGetter(this, "PdfJsDefaultPreferences", "resource://pdf.js/PdfJsDefaultPreferences.jsm"); +ChromeUtils.defineModuleGetter(this, "PdfJsRegistration", + "resource://pdf.js/PdfJsRegistration.jsm"); function getBoolPref(aPref, aDefaultValue) { try { @@ -102,9 +106,11 @@ var PdfJs = { "in the parent process."); } PdfjsChromeUtils.init(); + if (!remote) { + PdfjsContentUtils.init(); + } this.initPrefs(); - - Services.ppmm.sharedData.set("pdfjs.enabled", this.checkEnabled()); + this.updateRegistration(); }, initPrefs: function initPrefs() { @@ -128,6 +134,14 @@ var PdfJs = { initializeDefaultPreferences(); }, + updateRegistration: function updateRegistration() { + if (this.checkEnabled()) { + this.ensureRegistered(); + } else { + this.ensureUnregistered(); + } + }, + uninit: function uninit() { if (this._initialized) { Services.prefs.removeObserver(PREF_DISABLED, this); @@ -137,6 +151,7 @@ var PdfJs = { Services.obs.removeObserver(this, TOPIC_PLUGIN_INFO_UPDATED); this._initialized = false; } + this.ensureUnregistered(); }, _migrate: function migrate() { @@ -255,7 +270,11 @@ var PdfJs = { "handler changes."); } - Services.ppmm.sharedData.set("pdfjs.enabled", this.checkEnabled()); + this.updateRegistration(); + let jsm = "resource://pdf.js/PdfjsChromeUtils.jsm"; + // eslint-disable-next-line no-shadow + let PdfjsChromeUtils = ChromeUtils.import(jsm, {}).PdfjsChromeUtils; + PdfjsChromeUtils.notifyChildOfSettingsChange(this.enabled); }, /** @@ -280,5 +299,13 @@ var PdfJs = { } return Services.prefs.getBoolPref(PREF_ENABLED_CACHE_STATE, true); }, + + ensureRegistered: function ensureRegistered() { + PdfJsRegistration.ensureRegistered(); + }, + + ensureUnregistered: function ensureUnregistered() { + PdfJsRegistration.ensureUnregistered(); + }, }; diff --git a/browser/extensions/pdfjs/content/PdfJsRegistration.jsm b/browser/extensions/pdfjs/content/PdfJsRegistration.jsm new file mode 100644 index 000000000000..cb173aab5c0f --- /dev/null +++ b/browser/extensions/pdfjs/content/PdfJsRegistration.jsm @@ -0,0 +1,89 @@ +/* Copyright 2018 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. + */ + +"use strict"; + +var EXPORTED_SYMBOLS = ["PdfJsRegistration"]; + +const Cm = Components.manager; + +ChromeUtils.defineModuleGetter(this, "PdfStreamConverter", + "resource://pdf.js/PdfStreamConverter.jsm"); + +// Register/unregister a constructor as a factory. +function StreamConverterFactory() {} +StreamConverterFactory.prototype = { + + // properties required for XPCOM registration: + _classID: Components.ID("{d0c5195d-e798-49d4-b1d3-9324328b2291}"), + _classDescription: "pdf.js Component", + _contractID: "@mozilla.org/streamconv;1?from=application/pdf&to=*/*", + + _classID2: Components.ID("{d0c5195d-e798-49d4-b1d3-9324328b2292}"), + _contractID2: "@mozilla.org/streamconv;1?from=application/pdf&to=text/html", + + register: function register() { + var factory = { + createInstance(outer, iid) { + if (outer) + throw Cr.NS_ERROR_NO_AGGREGATION; + return (new PdfStreamConverter()).QueryInterface(iid); + }, + QueryInterface: ChromeUtils.generateQI([Ci.nsIFactory]) + }; + + this._factory = factory; + + var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar); + registrar.registerFactory(this._classID, this._classDescription, + this._contractID, factory); + registrar.registerFactory(this._classID2, this._classDescription, + this._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 PdfJsRegistration = { + _registered: false, + + ensureRegistered: function ensureRegistered() { + if (this._registered) { + return; + } + this._pdfStreamConverterFactory = new StreamConverterFactory(); + this._pdfStreamConverterFactory.register(); + + this._registered = true; + }, + + ensureUnregistered: function ensureUnregistered() { + if (!this._registered) { + return; + } + this._pdfStreamConverterFactory.unregister(); + delete this._pdfStreamConverterFactory; + + this._registered = false; + }, + +}; diff --git a/browser/extensions/pdfjs/content/PdfjsChromeUtils.jsm b/browser/extensions/pdfjs/content/PdfjsChromeUtils.jsm index 1ba3973b5832..fbe3edb4e6d0 100644 --- a/browser/extensions/pdfjs/content/PdfjsChromeUtils.jsm +++ b/browser/extensions/pdfjs/content/PdfjsChromeUtils.jsm @@ -90,6 +90,25 @@ var PdfjsChromeUtils = { } }, + /* + * Called by the main module when preference changes are picked up + * in the parent process. Observers don't propagate so we need to + * instruct the child to refresh its configuration and (possibly) + * the module's registration. + */ + notifyChildOfSettingsChange(enabled) { + if (Services.appinfo.processType === + Services.appinfo.PROCESS_TYPE_DEFAULT && this._ppmm) { + // XXX kinda bad, we want to get the parent process mm associated + // with the content process. _ppmm is currently the global process + // manager, which means this is going to fire to every child process + // we have open. Unfortunately I can't find a way to get at that + // process specific mm from js. + this._ppmm.broadcastAsyncMessage("PDFJS:Child:updateSettings", + { enabled, }); + } + }, + /* * Events */ diff --git a/browser/extensions/pdfjs/content/PdfjsContentUtils.jsm b/browser/extensions/pdfjs/content/PdfjsContentUtils.jsm index babe9bbcc3de..f3b47bda668d 100644 --- a/browser/extensions/pdfjs/content/PdfjsContentUtils.jsm +++ b/browser/extensions/pdfjs/content/PdfjsContentUtils.jsm @@ -20,12 +20,31 @@ var EXPORTED_SYMBOLS = ["PdfjsContentUtils"]; ChromeUtils.import("resource://gre/modules/Services.jsm"); var PdfjsContentUtils = { - _mm: Services.cpmm, + _mm: null, /* * Public API */ + init() { + // child *process* mm, or when loaded into the parent for in-content + // support the psuedo child process mm 'child PPMM'. + if (!this._mm) { + this._mm = Services.cpmm; + this._mm.addMessageListener("PDFJS:Child:updateSettings", this); + + Services.obs.addObserver(this, "quit-application"); + } + }, + + uninit() { + if (this._mm) { + this._mm.removeMessageListener("PDFJS:Child:updateSettings", this); + Services.obs.removeObserver(this, "quit-application"); + } + this._mm = null; + }, + /* * prefs utilities - the child does not have write access to prefs. * note, the pref names here are cross-checked against a list of @@ -81,5 +100,33 @@ var PdfjsContentUtils = { accessKey: aAccessKey, }); }, + + /* + * Events + */ + + observe(aSubject, aTopic, aData) { + if (aTopic === "quit-application") { + this.uninit(); + } + }, + + receiveMessage(aMsg) { + switch (aMsg.name) { + case "PDFJS:Child:updateSettings": + // Only react to this if we are remote. + if (Services.appinfo.processType === + Services.appinfo.PROCESS_TYPE_CONTENT) { + let jsm = "resource://pdf.js/PdfJsRegistration.jsm"; + let pdfjsr = ChromeUtils.import(jsm, {}).PdfJsRegistration; + if (aMsg.data.enabled) { + pdfjsr.ensureRegistered(); + } else { + pdfjsr.ensureUnregistered(); + } + } + break; + } + }, }; diff --git a/browser/extensions/pdfjs/content/pdfjschildbootstrap-enabled.js b/browser/extensions/pdfjs/content/pdfjschildbootstrap-enabled.js new file mode 100644 index 000000000000..1f98a4d01889 --- /dev/null +++ b/browser/extensions/pdfjs/content/pdfjschildbootstrap-enabled.js @@ -0,0 +1,30 @@ +/* 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. +*/ + +"use strict"; + +/* + * pdfjschildbootstrap-enabled.js loads into the content process to + * take care of initializing our built-in version of pdfjs when + * running remote. It will only be run when PdfJs.enable is true. + */ + +ChromeUtils.import("resource://gre/modules/Services.jsm"); +ChromeUtils.import("resource://pdf.js/PdfJsRegistration.jsm"); + +if (Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_CONTENT) { + // register various pdfjs factories that hook us into content loading. + PdfJsRegistration.ensureRegistered(); +} diff --git a/browser/extensions/pdfjs/content/pdfjschildbootstrap.js b/browser/extensions/pdfjs/content/pdfjschildbootstrap.js new file mode 100644 index 000000000000..dce51483146d --- /dev/null +++ b/browser/extensions/pdfjs/content/pdfjschildbootstrap.js @@ -0,0 +1,26 @@ +/* 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. +*/ + +"use strict"; + +/* + * pdfjschildbootstrap.js loads into the content process to take care of + * initializing our built-in version of pdfjs when running remote. + */ + +ChromeUtils.import("resource://pdf.js/PdfjsContentUtils.jsm"); + +// init content utils shim pdfjs will use to access privileged apis. +PdfjsContentUtils.init(); diff --git a/browser/extensions/pdfjs/moz.build b/browser/extensions/pdfjs/moz.build index c203fe8df685..3b413a8e9087 100644 --- a/browser/extensions/pdfjs/moz.build +++ b/browser/extensions/pdfjs/moz.build @@ -10,8 +10,3 @@ with Files("**"): BROWSER_CHROME_MANIFESTS += ['test/browser.ini'] JAR_MANIFESTS += ['jar.mn'] - -EXTRA_COMPONENTS += [ - 'pdfjs.js', - 'pdfjs.manifest', -] diff --git a/browser/extensions/pdfjs/pdfjs.js b/browser/extensions/pdfjs/pdfjs.js deleted file mode 100644 index fc315fd508c8..000000000000 --- a/browser/extensions/pdfjs/pdfjs.js +++ /dev/null @@ -1,37 +0,0 @@ -/* Copyright 2018 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. - */ - -"use strict"; - -ChromeUtils.import("resource://gre/modules/Services.jsm"); -ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); - -ChromeUtils.defineModuleGetter(this, "PdfStreamConverter", - "resource://pdf.js/PdfStreamConverter.jsm"); - -// Register/unregister a constructor as a factory. -function StreamConverterFactory() { - if (Services.cpmm.sharedData.get("pdfjs.enabled")) { - return new PdfStreamConverter(); - } - throw Cr.NS_ERROR_FACTORY_NOT_REGISTERED; -} -StreamConverterFactory.prototype = { - // properties required for XPCOM registration: - classID: Components.ID("{d0c5195d-e798-49d4-b1d3-9324328b2291}"), - classDescription: "pdf.js Component", -}; - -var NSGetFactory = XPCOMUtils.generateNSGetFactory([StreamConverterFactory]); diff --git a/browser/extensions/pdfjs/pdfjs.manifest b/browser/extensions/pdfjs/pdfjs.manifest deleted file mode 100644 index a4fbbf5bac53..000000000000 --- a/browser/extensions/pdfjs/pdfjs.manifest +++ /dev/null @@ -1,3 +0,0 @@ -component {d0c5195d-e798-49d4-b1d3-9324328b2291} pdfjs.js -contract @mozilla.org/streamconv;1?from=application/pdf&to=*/* {d0c5195d-e798-49d4-b1d3-9324328b2291} -contract @mozilla.org/streamconv;1?from=application/pdf&to=text/html {d0c5195d-e798-49d4-b1d3-9324328b2291} diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index 08950f4c773b..739efbc7e678 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -373,10 +373,6 @@ @RESPATH@/components/shield.manifest @RESPATH@/components/shield-content-process.js -; [PDF Viewer] -@RESPATH@/browser/components/pdfjs.manifest -@RESPATH@/browser/components/pdfjs.js - ; Modules @RESPATH@/browser/modules/* @RESPATH@/modules/* diff --git a/dom/base/nsContentUtils.cpp b/dom/base/nsContentUtils.cpp index 5ecc21c01ac1..4b78106170d5 100644 --- a/dom/base/nsContentUtils.cpp +++ b/dom/base/nsContentUtils.cpp @@ -176,7 +176,6 @@ #include "nsIScriptObjectPrincipal.h" #include "nsIScriptSecurityManager.h" #include "nsIScrollable.h" -#include "nsIStreamConverter.h" #include "nsIStreamConverterService.h" #include "nsIStringBundle.h" #include "nsIURI.h" @@ -6937,9 +6936,14 @@ nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal) bool nsContentUtils::IsPDFJSEnabled() { - nsCOMPtr conv = do_CreateInstance( - "@mozilla.org/streamconv;1?from=application/pdf&to=text/html"); - return conv; + nsCOMPtr convServ = + do_GetService("@mozilla.org/streamConverters;1"); + nsresult rv = NS_ERROR_FAILURE; + bool canConvert = false; + if (convServ) { + rv = convServ->CanConvert("application/pdf", "text/html", &canConvert); + } + return NS_SUCCEEDED(rv) && canConvert; } already_AddRefed