Bug 1380267: Add 1s max delay to extension shutdown blocker. r=aswan
authorKris Maglione <maglione.k@gmail.com>
Mon, 31 Jul 2017 12:02:23 -0700
changeset 420926 f23f75bc9d39980d863e4d3d845dbd97d9de8f5c
parent 420925 373c6ebaad861dcb63107fe3557bf28b21a7c425
child 420927 581c2f16e306a154a53aad253a8b812c42812942
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaswan
bugs1380267
milestone56.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 1380267: Add 1s max delay to extension shutdown blocker. r=aswan MozReview-Commit-ID: GqFPiVVgXUs
toolkit/components/extensions/Extension.jsm
--- a/toolkit/components/extensions/Extension.jsm
+++ b/toolkit/components/extensions/Extension.jsm
@@ -72,16 +72,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
                                   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
                                   "resource://gre/modules/Preferences.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "require",
                                   "resource://devtools/shared/Loader.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Schemas",
                                   "resource://gre/modules/Schemas.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "setTimeout",
+                                  "resource://gre/modules/Timer.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
                                   "resource://gre/modules/TelemetryStopwatch.jsm");
 
 XPCOMUtils.defineLazyGetter(
   this, "processScript",
   () => Cc["@mozilla.org/webextensions/extension-process-script;1"]
           .getService().wrappedJSObject);
 
@@ -109,16 +111,18 @@ const {
   EventEmitter,
   getUniqueId,
 } = ExtensionUtils;
 
 XPCOMUtils.defineLazyGetter(this, "console", ExtensionUtils.getConsole);
 
 XPCOMUtils.defineLazyGetter(this, "LocaleData", () => ExtensionCommon.LocaleData);
 
+// The maximum time to wait for extension shutdown blockers to complete.
+const SHUTDOWN_BLOCKER_MAX_MS = 1000;
 
 // The list of properties that themes are allowed to contain.
 XPCOMUtils.defineLazyGetter(this, "allowedThemeProperties", () => {
   Cu.import("resource://gre/modules/ExtensionParent.jsm");
   let propertiesInBaseManifest = ExtensionParent.baseManifestProperties;
 
   // The properties found in the base manifest contain all of the properties that
   // themes are allowed to have. However, the list also contains several properties
@@ -1082,19 +1086,16 @@ this.Extension = class extends Extension
       Services.perms.removeFromPrincipal(principal, "indexedDB");
       Services.perms.removeFromPrincipal(principal, "persistent-storage");
     }
   }
 
   startup() {
     this.startupPromise = this._startup();
 
-    this._startupComplete = this.startupPromise.catch(() => {});
-    OS.File.shutdown.addBlocker("Extension startup", this._startupComplete);
-
     return this.startupPromise;
   }
 
   async _startup() {
     if (shutdownPromises.has(this.id)) {
       await shutdownPromises.get(this.id);
     }
 
@@ -1204,30 +1205,38 @@ this.Extension = class extends Extension
       // caches. These caches may keep the file open.
       file.remove(false);
     }).catch(Cu.reportError);
   }
 
   async shutdown(reason) {
     let promise = this._shutdown(reason);
 
+    let blocker = () => {
+      return Promise.race([
+        promise,
+        new Promise(resolve => setTimeout(resolve, SHUTDOWN_BLOCKER_MAX_MS)),
+      ]);
+    };
+
     AsyncShutdown.profileChangeTeardown.addBlocker(
       `Extension Shutdown: ${this.id} (${this.manifest && this.name})`,
-      promise.catch(() => {}));
+      blocker);
 
     // If we already have a shutdown promise for this extension, wait
     // for it to complete before replacing it with a new one. This can
     // sometimes happen during tests with rapid startup/shutdown cycles
     // of multiple versions.
     if (shutdownPromises.has(this.id)) {
       await shutdownPromises.get(this.id);
     }
 
     let cleanup = () => {
       shutdownPromises.delete(this.id);
+      AsyncShutdown.profileChangeTeardown.removeBlocker(blocker);
     };
     shutdownPromises.set(this.id, promise.then(cleanup, cleanup));
 
     return Promise.resolve(promise);
   }
 
   async _shutdown(reason) {
     try {