Bug 1523609 - avoid triggering nsChromeRegistryChrome::CheckForNewChrome (which does main thread I/O) during shutdown of system add-ons, r=kmag.
authorFlorian Quèze <florian@queze.net>
Fri, 22 Mar 2019 14:19:59 +0000
changeset 465752 25a055417a5ca6244bffd485e2ad058164969066
parent 465751 a8c448b929137723938b1e4da97a9693f0937048
child 465753 d96ed1741bded4ad4902a3bfc1bc59a43ee5df91
push id35746
push usershindli@mozilla.com
push dateSat, 23 Mar 2019 09:46:24 +0000
treeherdermozilla-central@02b7484f316b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskmag
bugs1523609
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1523609 - avoid triggering nsChromeRegistryChrome::CheckForNewChrome (which does main thread I/O) during shutdown of system add-ons, r=kmag. Differential Revision: https://phabricator.services.mozilla.com/D22380
browser/extensions/formautofill/api.js
browser/extensions/webcompat-reporter/experimentalAPIs/l10n.js
chrome/nsChromeRegistryChrome.cpp
toolkit/components/startup/public/nsIAppStartup.idl
toolkit/mozapps/extensions/AddonManagerStartup.cpp
--- a/browser/extensions/formautofill/api.js
+++ b/browser/extensions/formautofill/api.js
@@ -125,17 +125,21 @@ this.formautofill = class extends Extens
 
     // Listen for the autocomplete popup message to lazily append our stylesheet related to the popup.
     Services.mm.addMessageListener("FormAutoComplete:MaybeOpenPopup", onMaybeOpenPopup);
 
     formAutofillParent.init().catch(Cu.reportError);
     Services.mm.loadFrameScript("chrome://formautofill/content/FormAutofillFrameScript.js", true, true);
   }
 
-  onShutdown() {
+  onShutdown(reason) {
+    if (reason == "APP_SHUTDOWN") {
+      return;
+    }
+
     resProto.setSubstitution(RESOURCE_HOST, null);
 
     this.chromeHandle.destruct();
     this.chromeHandle = null;
 
     if (this.autofillManifest) {
       Components.manager.removeBootstrappedManifestLocation(this.autofillManifest);
     }
--- a/browser/extensions/webcompat-reporter/experimentalAPIs/l10n.js
+++ b/browser/extensions/webcompat-reporter/experimentalAPIs/l10n.js
@@ -12,17 +12,17 @@ XPCOMUtils.defineLazyGetter(this, "l10nS
   return Services.strings.createBundle(
     "chrome://webcompat-reporter/locale/webcompat.properties");
 });
 
 let l10nManifest;
 
 this.l10n = class extends ExtensionAPI {
   onShutdown(reason) {
-    if (l10nManifest) {
+    if (reason !== "APP_SHUTDOWN" && l10nManifest) {
       Components.manager.removeBootstrappedManifestLocation(l10nManifest);
     }
   }
   getAPI(context) {
     // Until we move to Fluent (bug 1446164), we're stuck with
     // chrome.manifest for handling localization since its what the
     // build system can handle for localized repacks.
     if (context.extension.rootURI instanceof Ci.nsIJARURI) {
--- a/chrome/nsChromeRegistryChrome.cpp
+++ b/chrome/nsChromeRegistryChrome.cpp
@@ -23,16 +23,17 @@
 #include "nsStringEnumerator.h"
 #include "nsTextFormatter.h"
 #include "nsXPCOMCIDInternal.h"
 
 #include "mozilla/LookAndFeel.h"
 #include "mozilla/Unused.h"
 #include "mozilla/intl/LocaleService.h"
 
+#include "nsIAppStartup.h"
 #include "nsIObserverService.h"
 #include "nsIPrefBranch.h"
 #include "nsIPrefService.h"
 #include "mozilla/Preferences.h"
 #include "nsIResProtocolHandler.h"
 #include "nsIScriptError.h"
 #include "nsIXULRuntime.h"
 
@@ -268,16 +269,22 @@ nsChromeRegistryChrome::Observe(nsISuppo
     NS_ERROR("Unexpected observer topic!");
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsChromeRegistryChrome::CheckForNewChrome() {
+  nsCOMPtr<nsIAppStartup> appStartup = components::AppStartup::Service();
+  if (appStartup->GetShuttingDown()) {
+    MOZ_ASSERT(false, "checking for new chrome during shutdown");
+    return NS_ERROR_UNEXPECTED;
+  }
+
   mPackagesHash.Clear();
   mOverrideTable.Clear();
 
   mDynamicRegistration = false;
 
   nsComponentManagerImpl::gComponentManager->RereadChromeManifests();
 
   mDynamicRegistration = true;
--- a/toolkit/components/startup/public/nsIAppStartup.idl
+++ b/toolkit/components/startup/public/nsIAppStartup.idl
@@ -2,18 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIToolkitProfile;
 
-[scriptable, uuid(6621f6d5-6c04-4a0e-9e74-447db221484e)]
-
+[scriptable, builtinclass, uuid(6621f6d5-6c04-4a0e-9e74-447db221484e)]
 interface nsIAppStartup : nsISupports
 {
     /**
      * Create the hidden window.
      */
     void createHiddenWindow();
 
     /**
@@ -137,17 +136,17 @@ interface nsIAppStartup : nsISupports
      *        This parameter modifies how the app is shutdown, and it is
      *        constructed from the constants defined above.
      */
     void quit(in uint32_t aMode);
 
     /**
      * True if the application is in the process of shutting down.
      */
-    readonly attribute boolean shuttingDown;
+    [infallible] readonly attribute boolean shuttingDown;
 
     /**
      * True if the application is in the process of starting up.
      *
      * Startup is complete once all observers of final-ui-startup have returned.
      */
     readonly attribute boolean startingUp;
 
--- a/toolkit/mozapps/extensions/AddonManagerStartup.cpp
+++ b/toolkit/mozapps/extensions/AddonManagerStartup.cpp
@@ -10,31 +10,33 @@
 #include "jsfriendapi.h"
 #include "js/ArrayBuffer.h"
 #include "js/JSON.h"
 #include "js/TracingAPI.h"
 #include "xpcpublic.h"
 
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/EndianUtils.h"
+#include "mozilla/Components.h"
 #include "mozilla/Compression.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ResultExtensions.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/Services.h"
 #include "mozilla/URLPreloader.h"
 #include "mozilla/Unused.h"
 #include "mozilla/ErrorResult.h"
 #include "mozilla/dom/ipc/StructuredCloneData.h"
 
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsAppRunner.h"
 #include "nsContentUtils.h"
 #include "nsChromeRegistry.h"
+#include "nsIAppStartup.h"
 #include "nsIDOMWindowUtils.h"  // for nsIJSRAIIHelper
 #include "nsIFileURL.h"
 #include "nsIIOService.h"
 #include "nsIJARURI.h"
 #include "nsIStringEnumerator.h"
 #include "nsIZipReader.h"
 #include "nsJARProtocolHandler.h"
 #include "nsJSUtils.h"
@@ -687,16 +689,23 @@ void RegistryEntries::Register() {
   }
 }
 
 NS_IMETHODIMP
 RegistryEntries::Destruct() {
   if (isInList()) {
     remove();
 
+    // No point in doing I/O to check for new chrome during shutdown, return
+    // early in that case.
+    nsCOMPtr<nsIAppStartup> appStartup = components::AppStartup::Service();
+    if (!appStartup || appStartup->GetShuttingDown()) {
+      return NS_OK;
+    }
+
     // When we remove dynamic entries from the registry, we need to rebuild it
     // in order to ensure a consistent state. See comments in Observe().
     RefPtr<nsChromeRegistry> cr = nsChromeRegistry::GetSingleton();
     return cr->CheckForNewChrome();
   }
   return NS_OK;
 }