Backed out 2 changesets (bug 1452618) for frequently failing mochitest on Android on a CLOSED TREE
authorGurzau Raul <rgurzau@mozilla.com>
Sun, 15 Apr 2018 13:12:56 +0300
changeset 466963 e63607c0931b04d353a1021237360ffa0a1a0cab
parent 466962 5bf3bfedd867cc3504fccf7b17b4272851861fba
child 466964 2b7cbea0291d31ab704b238f7b86de376660dbaf
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1452618
milestone61.0a1
backs out5bf3bfedd867cc3504fccf7b17b4272851861fba
fdcb9f2ec9d9b6d1a291d9969249d5a3c0cb054e
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
Backed out 2 changesets (bug 1452618) for frequently failing mochitest on Android on a CLOSED TREE Backed out changeset 5bf3bfedd867 (bug 1452618) Backed out changeset fdcb9f2ec9d9 (bug 1452618)
toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
toolkit/mozapps/extensions/internal/XPIInstall.jsm
toolkit/mozapps/extensions/internal/XPIProvider.jsm
toolkit/mozapps/extensions/internal/XPIProviderUtils.js
toolkit/mozapps/extensions/nsBlocklistService.js
toolkit/mozapps/extensions/test/xpcshell/test_blocklist_severities.js
toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js
toolkit/mozapps/extensions/test/xpcshell/test_upgrade_incompatible.js
xpcom/system/nsIBlocklistService.idl
--- a/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
+++ b/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm
@@ -121,18 +121,17 @@ class MockBlocklist {
   unregister() {
     MockRegistrar.unregister(this.originalCID);
   }
 
   getAddonBlocklistState(addon, appVersion, toolkitVersion) {
     return this.addons.get(addon.id, Ci.nsIBlocklistService.STATE_NOT_BLOCKED);
   }
 
-  async getAddonBlocklistEntry(addon, appVersion, toolkitVersion) {
-    await Promise.resolve();
+  getAddonBlocklistEntry(addon, appVersion, toolkitVersion) {
     let state = this.getAddonBlocklistState(addon, appVersion, toolkitVersion);
     if (state != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
       return {
         state,
         url: "http://example.com/",
       };
     }
     return null;
--- a/toolkit/mozapps/extensions/internal/XPIInstall.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
@@ -862,17 +862,17 @@ function generateTemporaryInstallID(aFil
   const sess = TEMP_INSTALL_ID_GEN_SESSION;
   hasher.update(sess, sess.length);
   hasher.update(data, data.length);
   let id = `${getHashStringForCrypto(hasher)}${TEMPORARY_ADDON_SUFFIX}`;
   logger.info(`Generated temp id ${id} (${sess.join("")}) for ${aFile.path}`);
   return id;
 }
 
-var loadManifest = async function(aPackage, aInstallLocation, aOldAddon) {
+var loadManifest = async function(aPackage, aInstallLocation) {
   async function loadFromRDF(aUri) {
     let manifest = await aPackage.readString("install.rdf");
     let addon = await loadManifestFromRDF(aUri, manifest);
 
     if (await aPackage.hasResource("icon.png")) {
       addon.icons[32] = "icon.png";
       addon.icons[48] = "icon.png";
     }
@@ -915,28 +915,28 @@ var loadManifest = async function(aPacka
         throw new Error(`Webextension is signed with an invalid id (${addon.id})`);
       }
     }
     if (!addon.id && aInstallLocation.name == KEY_APP_TEMPORARY) {
       addon.id = generateTemporaryInstallID(aPackage.file);
     }
   }
 
-  await addon.updateBlocklistState({oldAddon: aOldAddon});
+  addon.updateBlocklistState();
   addon.appDisabled = !isUsableAddon(addon);
 
   defineSyncGUID(addon);
 
   return addon;
 };
 
-var loadManifestFromFile = async function(aFile, aInstallLocation, aOldAddon) {
+var loadManifestFromFile = async function(aFile, aInstallLocation) {
   let pkg = Package.get(aFile);
   try {
-    let addon = await loadManifest(pkg, aInstallLocation, aOldAddon);
+    let addon = await loadManifest(pkg, aInstallLocation);
     return addon;
   } finally {
     pkg.close();
   }
 };
 
 function flushChromeCaches() {
   // Init this, so it will get the notification.
@@ -1436,17 +1436,17 @@ class AddonInstall {
     try {
       pkg = Package.get(file);
     } catch (e) {
       return Promise.reject([AddonManager.ERROR_CORRUPT_FILE, e]);
     }
 
     try {
       try {
-        this.addon = await loadManifest(pkg, this.installLocation, this.existingAddon);
+        this.addon = await loadManifest(pkg, this.installLocation);
       } catch (e) {
         return Promise.reject([AddonManager.ERROR_CORRUPT_FILE, e]);
       }
 
       if (!this.addon.id) {
         let err = new Error(`Cannot find id for addon ${file.path}`);
         return Promise.reject([AddonManager.ERROR_CORRUPT_FILE, err]);
       }
@@ -1904,17 +1904,17 @@ var LocalAddonInstall = class extends Ad
       return;
     }
 
     let addon = await new Promise(resolve => {
       XPIDatabase.getVisibleAddonForID(this.addon.id, resolve);
     });
 
     this.existingAddon = addon;
-    await this.addon.updateBlocklistState({oldAddon: this.existingAddon});
+    this.addon.updateBlocklistState({oldAddon: this.existingAddon});
     this.addon.updateDate = Date.now();
     this.addon.installDate = addon ? addon.installDate : this.addon.updateDate;
 
     if (!this.addon.isCompatible) {
       this.state = AddonManager.STATE_CHECKING;
 
       await new Promise(resolve => {
         new UpdateChecker(this.addon, {
@@ -2297,30 +2297,30 @@ var DownloadAddonInstall = class extends
       logger.debug("downloadFailed: listener changed AddonInstall state for " +
           this.sourceURI.spec + " to " + this.state);
   }
 
   /**
    * Notify listeners that the download completed.
    */
   downloadCompleted() {
-    XPIDatabase.getVisibleAddonForID(this.addon.id, async aAddon => {
+    XPIDatabase.getVisibleAddonForID(this.addon.id, aAddon => {
       if (aAddon)
         this.existingAddon = aAddon;
 
       this.state = AddonManager.STATE_DOWNLOADED;
       this.addon.updateDate = Date.now();
 
       if (this.existingAddon) {
         this.addon.existingAddonID = this.existingAddon.id;
         this.addon.installDate = this.existingAddon.installDate;
       } else {
         this.addon.installDate = this.addon.updateDate;
       }
-      await this.addon.updateBlocklistState({oldAddon: this.existingAddon});
+      this.addon.updateBlocklistState({oldAddon: this.existingAddon});
 
       if (AddonManagerPrivate.callInstallListeners("onDownloadEnded",
                                                    this.listeners,
                                                    this.wrapper)) {
         // If a listener changed our state then do not proceed with the install
         if (this.state != AddonManager.STATE_DOWNLOADED)
           return;
 
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -806,21 +806,16 @@ function isUsableAddon(aAddon) {
     return false;
   }
 
   if (aAddon.blocklistState == nsIBlocklistService.STATE_BLOCKED) {
     logger.warn(`Add-on ${aAddon.id} is blocklisted.`);
     return false;
   }
 
-  // If we can't read it, it's not usable:
-  if (aAddon.brokenManifest) {
-    return false;
-  }
-
   // Experiments are installed through an external mechanism that
   // limits target audience to compatible clients. We trust it knows what
   // it's doing and skip compatibility checks.
   //
   // This decision does forfeit defense in depth. If the experiments system
   // is ever wrong about targeting an add-on to a specific application
   // or platform, the client will likely see errors.
   if (aAddon.type == "experiment")
@@ -917,21 +912,21 @@ function getAllAliasesForTypes(aTypes) {
 
   return [...typeset];
 }
 
 /**
  * A synchronous method for loading an add-on's manifest. This should only ever
  * be used during startup or a sync load of the add-ons DB
  */
-function syncLoadManifestFromFile(aFile, aInstallLocation, aOldAddon) {
+function syncLoadManifestFromFile(aFile, aInstallLocation) {
   let success = undefined;
   let result = null;
 
-  loadManifestFromFile(aFile, aInstallLocation, aOldAddon).then(val => {
+  loadManifestFromFile(aFile, aInstallLocation).then(val => {
     success = true;
     result = val;
   }, val => {
     success = false;
     result = val;
   });
 
   Services.tm.spinEventLoopUntil(() => success !== undefined);
@@ -4506,40 +4501,40 @@ AddonInternal.prototype = {
       if (targetApp.id == Services.appinfo.ID)
         return targetApp;
       if (targetApp.id == TOOLKIT_ID)
         app = targetApp;
     }
     return app;
   },
 
-  async findBlocklistEntry() {
+  findBlocklistEntry() {
     let staticItem = findMatchingStaticBlocklistItem(this);
     if (staticItem) {
       let url = Services.urlFormatter.formatURLPref(PREF_BLOCKLIST_ITEM_URL);
       return {
         state: staticItem.level,
         url: url.replace(/%blockID%/g, staticItem.blockID)
       };
     }
 
     return Blocklist.getAddonBlocklistEntry(this.wrapper);
   },
 
-  async updateBlocklistState(options = {}) {
+  updateBlocklistState(options = {}) {
     let {applySoftBlock = true, oldAddon = null, updateDatabase = true} = options;
 
     if (oldAddon) {
       this.userDisabled = oldAddon.userDisabled;
       this.softDisabled = oldAddon.softDisabled;
       this.blocklistState = oldAddon.blocklistState;
     }
     let oldState = this.blocklistState;
 
-    let entry = await this.findBlocklistEntry();
+    let entry = this.findBlocklistEntry();
     let newState = entry ? entry.state : Blocklist.STATE_NOT_BLOCKED;
 
     this.blocklistState = newState;
     this.blocklistURL = entry && entry.url;
 
     let userDisabled, softDisabled;
     // After a blocklist update, the blocklist service manually applies
     // new soft blocks after displaying a UI, in which cases we need to
@@ -4957,17 +4952,17 @@ AddonWrapper.prototype = {
 
     let activeAddon = XPIProvider.activeAddons.get(addon.id);
     if (activeAddon)
       return activeAddon.startupPromise || null;
     return null;
   },
 
   updateBlocklistState(applySoftBlock = true) {
-    return addonFor(this).updateBlocklistState({applySoftBlock});
+    addonFor(this).updateBlocklistState({applySoftBlock});
   },
 
   get userDisabled() {
     let addon = addonFor(this);
     return addon.softDisabled || addon.userDisabled;
   },
   set userDisabled(val) {
     let addon = addonFor(this);
--- a/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
+++ b/toolkit/mozapps/extensions/internal/XPIProviderUtils.js
@@ -1229,17 +1229,19 @@ this.XPIDatabaseReconcile = {
    */
   updateMetadata(aInstallLocation, aOldAddon, aAddonState, aNewAddon) {
     logger.debug("Add-on " + aOldAddon.id + " modified in " + aInstallLocation.name);
 
     try {
       // If there isn't an updated install manifest for this add-on then load it.
       if (!aNewAddon) {
         let file = new nsIFile(aAddonState.path);
-        aNewAddon = syncLoadManifestFromFile(file, aInstallLocation, aOldAddon);
+        aNewAddon = syncLoadManifestFromFile(file, aInstallLocation);
+
+        aNewAddon.updateBlocklistState({oldAddon: aOldAddon});
       }
 
       // The ID in the manifest that was loaded must match the ID of the old
       // add-on.
       if (aNewAddon.id != aOldAddon.id)
         throw new Error("Incorrect id in install manifest for existing add-on " + aOldAddon.id);
     } catch (e) {
       logger.warn("updateMetadata: Add-on " + aOldAddon.id + " is invalid", e);
@@ -1288,35 +1290,41 @@ this.XPIDatabaseReconcile = {
    *
    * @param  aInstallLocation
    *         The install location containing the add-on
    * @param  aOldAddon
    *         The AddonInternal as it appeared the last time the application
    *         ran
    * @param  aAddonState
    *         The new state of the add-on
+   * @param  aOldAppVersion
+   *         The version of the application last run with this profile or null
+   *         if it is a new profile or the version is unknown
+   * @param  aOldPlatformVersion
+   *         The version of the platform last run with this profile or null
+   *         if it is a new profile or the version is unknown
    * @param  aReloadMetadata
    *         A boolean which indicates whether metadata should be reloaded from
    *         the addon manifests. Default to false.
    * @return the new addon.
    */
-  updateCompatibility(aInstallLocation, aOldAddon, aAddonState, aReloadMetadata) {
+  updateCompatibility(aInstallLocation, aOldAddon, aAddonState, aOldAppVersion,
+                      aOldPlatformVersion, aReloadMetadata) {
     logger.debug("Updating compatibility for add-on " + aOldAddon.id + " in " + aInstallLocation.name);
 
     let checkSigning = aOldAddon.signedState === undefined && ADDON_SIGNING &&
                        SIGNED_TYPES.has(aOldAddon.type);
 
     let manifest = null;
     if (checkSigning || aReloadMetadata) {
       try {
         let file = new nsIFile(aAddonState.path);
         manifest = syncLoadManifestFromFile(file, aInstallLocation);
       } catch (err) {
         // If we can no longer read the manifest, it is no longer compatible.
-        aOldAddon.brokenManifest = true;
         aOldAddon.appDisabled = true;
         return aOldAddon;
       }
     }
 
     // If updating from a version of the app that didn't support signedState
     // then update that property now
     if (checkSigning) {
@@ -1332,16 +1340,17 @@ this.XPIDatabaseReconcile = {
       let remove = ["syncGUID", "foreignInstall", "visible", "active",
                     "userDisabled", "applyBackgroundUpdates", "sourceURI",
                     "releaseNotesURI", "targetApplications"];
 
       let props = PROP_JSON_FIELDS.filter(a => !remove.includes(a));
       copyProperties(manifest, props, aOldAddon);
     }
 
+    aOldAddon.updateBlocklistState({updateDatabase: false});
     aOldAddon.appDisabled = !isUsableAddon(aOldAddon);
 
     return aOldAddon;
   },
 
   /**
    * Compares the add-ons that are currently installed to those that were
    * known to be installed when the application last ran and applies any
@@ -1394,20 +1403,16 @@ this.XPIDatabaseReconcile = {
       let locationAddonMap = previousAddons.get(a.location);
       if (!locationAddonMap) {
         locationAddonMap = new Map();
         previousAddons.set(a.location, locationAddonMap);
       }
       locationAddonMap.set(a.id, a);
     }
 
-    // Keep track of add-ons whose blocklist status may have changed. We'll check this
-    // after everything else.
-    let addonsToCheckAgainstBlocklist = [];
-
     // Build the list of current add-ons into similar maps. When add-ons are still
     // present we re-use the add-on objects from the database and update their
     // details directly
     let currentAddons = new Map();
     for (let installLocation of XPIProvider.installLocations) {
       let locationAddonMap = new Map();
       currentAddons.set(installLocation.name, locationAddonMap);
 
@@ -1452,20 +1457,18 @@ this.XPIDatabaseReconcile = {
               newAddon = this.updateMetadata(installLocation, oldAddon, xpiState, newAddon);
             } else if (oldPath != xpiState.path) {
               newAddon = this.updatePath(installLocation, oldAddon, xpiState);
             } else if (aUpdateCompatibility || aSchemaChange) {
               // Check compatility when the application version and/or schema
               // version has changed. A schema change also reloads metadata from
               // the manifests.
               newAddon = this.updateCompatibility(installLocation, oldAddon, xpiState,
+                                                  aOldAppVersion, aOldPlatformVersion,
                                                   aSchemaChange);
-              // We need to do a blocklist check later, but the add-on may have changed by then.
-              // Avoid storing the current copy and just get one when we need one instead.
-              addonsToCheckAgainstBlocklist.push(newAddon.id);
             } else {
               // No change
               newAddon = oldAddon;
             }
 
             if (newAddon)
               locationAddonMap.set(newAddon.id, newAddon);
           } else {
@@ -1660,31 +1663,11 @@ this.XPIDatabaseReconcile = {
       }
     }
     XPIStates.save();
 
     // Clear out any cached migration data.
     XPIDatabase.migrateData = null;
     XPIDatabase.saveChanges();
 
-    // Do some blocklist checks. These will happen after we've just saved everything,
-    // because they're async and depend on the blocklist loading. When we're done, save
-    // the data if any of the add-ons' blocklist state has changed.
-    AddonManager.shutdown.addBlocker(
-      "Update add-on blocklist state into add-on DB",
-      (async () => {
-        // Avoid querying the AddonManager immediately to give startup a chance
-        // to complete.
-        await Promise.resolve();
-        let addons = await AddonManager.getAddonsByIDs(addonsToCheckAgainstBlocklist);
-        await Promise.all(addons.map(addon => {
-          if (addon) {
-            return addon.updateBlocklistState({updateDatabase: false});
-          }
-          return null;
-        }));
-        XPIDatabase.saveChanges();
-      })().catch(Cu.reportError)
-    );
-
     return true;
   },
 };
--- a/toolkit/mozapps/extensions/nsBlocklistService.js
+++ b/toolkit/mozapps/extensions/nsBlocklistService.js
@@ -339,18 +339,19 @@ Blocklist.prototype = {
                   Ci.nsIBlocklistService.STATE_BLOCKED : Ci.nsIBlocklistService.STATE_SOFTBLOCKED),
           url: blItem.blockID && this._createBlocklistURL(blItem.blockID),
         };
       }
     }
     return null;
   },
 
-  async getAddonBlocklistEntry(addon, appVersion, toolkitVersion) {
-    await this.loadBlocklistAsync();
+  getAddonBlocklistEntry(addon, appVersion, toolkitVersion) {
+    if (!this.isLoaded)
+      this._loadBlocklist();
     return this._getAddonBlocklistEntry(addon, this._addonEntries,
                                         appVersion, toolkitVersion);
   },
 
   /**
    * Private version of getAddonBlocklistState that allows the caller to pass in
    * the add-on blocklist entries to compare against.
    *
@@ -760,30 +761,19 @@ Blocklist.prototype = {
     return this._addonEntries != null && this._gfxEntries != null && this._pluginEntries != null;
   },
 
   /* Used for testing */
   _clear() {
     this._addonEntries = null;
     this._gfxEntries = null;
     this._pluginEntries = null;
-    delete this._preloadPromise;
   },
 
   async loadBlocklistAsync() {
-    if (this.isLoaded) {
-      return;
-    }
-    if (!this._preloadPromise) {
-      this._preloadPromise = this._loadBlocklistAsyncInternal();
-    }
-    await this._preloadPromise;
-  },
-
-  async _loadBlocklistAsyncInternal() {
     let profPath = OS.Path.join(OS.Constants.Path.profileDir, FILE_BLOCKLIST);
     try {
       await this._preloadBlocklistFile(profPath);
       return;
     } catch (e) {
       LOG("Blocklist::loadBlocklistAsync: Failed to load XML file " + e);
     }
 
@@ -794,17 +784,18 @@ Blocklist.prototype = {
     } catch (e) {
       LOG("Blocklist::loadBlocklistAsync: Failed to load XML file " + e);
     }
 
     LOG("Blocklist::loadBlocklistAsync: no XML File found");
   },
 
   async _preloadBlocklistFile(path) {
-    if (this.isLoaded) {
+    if (this._addonEntries) {
+      // The file has been already loaded.
       return;
     }
 
     if (!gBlocklistEnabled) {
       LOG("Blocklist::_preloadBlocklistFile: blocklist is disabled");
       return;
     }
 
@@ -1221,196 +1212,197 @@ Blocklist.prototype = {
     Services.obs.notifyObservers(null, "blocklist-data-gfxItems", payload);
   },
 
   _notifyObserversBlocklistUpdated() {
     Services.obs.notifyObservers(this, "blocklist-updated");
     Services.ppmm.broadcastAsyncMessage("Blocklist:blocklistInvalidated", {});
   },
 
-  async _blocklistUpdated(oldAddonEntries, oldPluginEntries) {
+  _blocklistUpdated(oldAddonEntries, oldPluginEntries) {
     var addonList = [];
 
     // A helper function that reverts the prefs passed to default values.
     function resetPrefs(prefs) {
       for (let pref of prefs)
         Services.prefs.clearUserPref(pref);
     }
     const types = ["extension", "theme", "locale", "dictionary", "service"];
-    let addons = await AddonManager.getAddonsByTypes(types);
-    for (let addon of addons) {
-      let oldState = addon.blocklistState;
-      if (addon.updateBlocklistState) {
-        await addon.updateBlocklistState(false);
-      } else if (oldAddonEntries) {
-        oldState = this._getAddonBlocklistState(addon, oldAddonEntries);
-      } else {
-        oldState = Ci.nsIBlocklistService.STATE_NOTBLOCKED;
-      }
-      let state = addon.blocklistState;
+    AddonManager.getAddonsByTypes(types, addons => {
+      for (let addon of addons) {
+        let oldState = addon.blocklistState;
+        if (addon.updateBlocklistState) {
+          addon.updateBlocklistState(false);
+        } else if (oldAddonEntries) {
+          oldState = this._getAddonBlocklistState(addon, oldAddonEntries);
+        } else {
+          oldState = Ci.nsIBlocklistService.STATE_NOTBLOCKED;
+        }
+        let state = addon.blocklistState;
 
-      LOG("Blocklist state for " + addon.id + " changed from " +
-          oldState + " to " + state);
+        LOG("Blocklist state for " + addon.id + " changed from " +
+            oldState + " to " + state);
+
+        // We don't want to re-warn about add-ons
+        if (state == oldState)
+          continue;
 
-      // We don't want to re-warn about add-ons
-      if (state == oldState)
-        continue;
+        if (state === Ci.nsIBlocklistService.STATE_BLOCKED) {
+          // It's a hard block. We must reset certain preferences.
+          let prefs = this._getAddonPrefs(addon);
+          resetPrefs(prefs);
+        }
 
-      if (state === Ci.nsIBlocklistService.STATE_BLOCKED) {
-        // It's a hard block. We must reset certain preferences.
-        let prefs = this._getAddonPrefs(addon);
-        resetPrefs(prefs);
-      }
+        // Ensure that softDisabled is false if the add-on is not soft blocked
+        if (state != Ci.nsIBlocklistService.STATE_SOFTBLOCKED)
+          addon.softDisabled = false;
 
-      // Ensure that softDisabled is false if the add-on is not soft blocked
-      if (state != Ci.nsIBlocklistService.STATE_SOFTBLOCKED)
-        addon.softDisabled = false;
+        // Don't warn about add-ons becoming unblocked.
+        if (state == Ci.nsIBlocklistService.STATE_NOT_BLOCKED)
+          continue;
 
-      // Don't warn about add-ons becoming unblocked.
-      if (state == Ci.nsIBlocklistService.STATE_NOT_BLOCKED)
-        continue;
+        // If an add-on has dropped from hard to soft blocked just mark it as
+        // soft disabled and don't warn about it.
+        if (state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED &&
+            oldState == Ci.nsIBlocklistService.STATE_BLOCKED) {
+          addon.softDisabled = true;
+          continue;
+        }
 
-      // If an add-on has dropped from hard to soft blocked just mark it as
-      // soft disabled and don't warn about it.
-      if (state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED &&
-          oldState == Ci.nsIBlocklistService.STATE_BLOCKED) {
-        addon.softDisabled = true;
-        continue;
-      }
+        // If the add-on is already disabled for some reason then don't warn
+        // about it
+        if (!addon.isActive) {
+          // But mark it as softblocked if necessary. Note that we avoid setting
+          // softDisabled at the same time as userDisabled to make it clear
+          // which was the original cause of the add-on becoming disabled in a
+          // way that the user can change.
+          if (state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED && !addon.userDisabled)
+            addon.softDisabled = true;
+          continue;
+        }
 
-      // If the add-on is already disabled for some reason then don't warn
-      // about it
-      if (!addon.isActive) {
-        // But mark it as softblocked if necessary. Note that we avoid setting
-        // softDisabled at the same time as userDisabled to make it clear
-        // which was the original cause of the add-on becoming disabled in a
-        // way that the user can change.
-        if (state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED && !addon.userDisabled)
-          addon.softDisabled = true;
-        continue;
+        let entry = this._getAddonBlocklistEntry(addon, this._addonEntries);
+        addonList.push({
+          name: addon.name,
+          version: addon.version,
+          icon: addon.iconURL,
+          disable: false,
+          blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED,
+          item: addon,
+          url: entry && entry.url,
+        });
       }
 
-      let entry = this._getAddonBlocklistEntry(addon, this._addonEntries);
-      addonList.push({
-        name: addon.name,
-        version: addon.version,
-        icon: addon.iconURL,
-        disable: false,
-        blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED,
-        item: addon,
-        url: entry && entry.url,
-      });
-    }
-
-    AddonManagerPrivate.updateAddonAppDisabledStates();
+      AddonManagerPrivate.updateAddonAppDisabledStates();
 
-    var phs = Cc["@mozilla.org/plugin/host;1"].
-              getService(Ci.nsIPluginHost);
-    var plugins = phs.getPluginTags();
-
-    for (let plugin of plugins) {
-      let oldState = -1;
-      if (oldPluginEntries)
-        oldState = this._getPluginBlocklistState(plugin, oldPluginEntries);
-      let state = this.getPluginBlocklistState(plugin);
-      LOG("Blocklist state for " + plugin.name + " changed from " +
-          oldState + " to " + state);
-      // We don't want to re-warn about items
-      if (state == oldState)
-        continue;
+      var phs = Cc["@mozilla.org/plugin/host;1"].
+                getService(Ci.nsIPluginHost);
+      var plugins = phs.getPluginTags();
 
-      if (oldState == Ci.nsIBlocklistService.STATE_BLOCKED) {
-        if (state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED)
-          plugin.enabledState = Ci.nsIPluginTag.STATE_DISABLED;
-      } else if (!plugin.disabled && state != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
-        if (state != Ci.nsIBlocklistService.STATE_OUTDATED &&
-            state != Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE &&
-            state != Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE) {
-          addonList.push({
-            name: plugin.name,
-            version: plugin.version,
-            icon: "chrome://mozapps/skin/plugins/pluginGeneric.svg",
-            disable: false,
-            blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED,
-            item: plugin,
-            url: this.getPluginBlocklistURL(plugin),
-          });
-        }
-      }
-    }
-
-    if (addonList.length == 0) {
-      this._notifyObserversBlocklistUpdated();
-      return;
-    }
-
-    if ("@mozilla.org/addons/blocklist-prompt;1" in Cc) {
-      try {
-        let blockedPrompter = Cc["@mozilla.org/addons/blocklist-prompt;1"]
-                               .getService(Ci.nsIBlocklistPrompt);
-        blockedPrompter.prompt(addonList);
-      } catch (e) {
-        LOG(e);
-      }
-      this._notifyObserversBlocklistUpdated();
-      return;
-    }
-
-    var args = {
-      restart: false,
-      list: addonList
-    };
-    // This lets the dialog get the raw js object
-    args.wrappedJSObject = args;
-
-    /*
-      Some tests run without UI, so the async code listens to a message
-      that can be sent programatically
-    */
-    let applyBlocklistChanges = () => {
-      for (let addon of addonList) {
-        if (!addon.disable)
+      for (let plugin of plugins) {
+        let oldState = -1;
+        if (oldPluginEntries)
+          oldState = this._getPluginBlocklistState(plugin, oldPluginEntries);
+        let state = this.getPluginBlocklistState(plugin);
+        LOG("Blocklist state for " + plugin.name + " changed from " +
+            oldState + " to " + state);
+        // We don't want to re-warn about items
+        if (state == oldState)
           continue;
 
-        if (addon.item instanceof Ci.nsIPluginTag)
-          addon.item.enabledState = Ci.nsIPluginTag.STATE_DISABLED;
-        else {
-          // This add-on is softblocked.
-          addon.item.softDisabled = true;
-          // We must revert certain prefs.
-          let prefs = this._getAddonPrefs(addon.item);
-          resetPrefs(prefs);
+        if (oldState == Ci.nsIBlocklistService.STATE_BLOCKED) {
+          if (state == Ci.nsIBlocklistService.STATE_SOFTBLOCKED)
+            plugin.enabledState = Ci.nsIPluginTag.STATE_DISABLED;
+        } else if (!plugin.disabled && state != Ci.nsIBlocklistService.STATE_NOT_BLOCKED) {
+          if (state != Ci.nsIBlocklistService.STATE_OUTDATED &&
+              state != Ci.nsIBlocklistService.STATE_VULNERABLE_UPDATE_AVAILABLE &&
+              state != Ci.nsIBlocklistService.STATE_VULNERABLE_NO_UPDATE) {
+            addonList.push({
+              name: plugin.name,
+              version: plugin.version,
+              icon: "chrome://mozapps/skin/plugins/pluginGeneric.svg",
+              disable: false,
+              blocked: state == Ci.nsIBlocklistService.STATE_BLOCKED,
+              item: plugin,
+              url: this.getPluginBlocklistURL(plugin),
+            });
+          }
         }
       }
 
-      if (args.restart)
-        restartApp();
+      if (addonList.length == 0) {
+        this._notifyObserversBlocklistUpdated();
+        return;
+      }
 
-      this._notifyObserversBlocklistUpdated();
-      Services.obs.removeObserver(applyBlocklistChanges, "addon-blocklist-closed");
-    };
+      if ("@mozilla.org/addons/blocklist-prompt;1" in Cc) {
+        try {
+          let blockedPrompter = Cc["@mozilla.org/addons/blocklist-prompt;1"]
+                                 .getService(Ci.nsIBlocklistPrompt);
+          blockedPrompter.prompt(addonList);
+        } catch (e) {
+          LOG(e);
+        }
+        this._notifyObserversBlocklistUpdated();
+        return;
+      }
 
-    Services.obs.addObserver(applyBlocklistChanges, "addon-blocklist-closed");
+      var args = {
+        restart: false,
+        list: addonList
+      };
+      // This lets the dialog get the raw js object
+      args.wrappedJSObject = args;
+
+      /*
+        Some tests run without UI, so the async code listens to a message
+        that can be sent programatically
+      */
+      let applyBlocklistChanges = () => {
+        for (let addon of addonList) {
+          if (!addon.disable)
+            continue;
 
-    if (Services.prefs.getBoolPref(PREF_BLOCKLIST_SUPPRESSUI, false)) {
-      applyBlocklistChanges();
-      return;
-    }
+          if (addon.item instanceof Ci.nsIPluginTag)
+            addon.item.enabledState = Ci.nsIPluginTag.STATE_DISABLED;
+          else {
+            // This add-on is softblocked.
+            addon.item.softDisabled = true;
+            // We must revert certain prefs.
+            let prefs = this._getAddonPrefs(addon.item);
+            resetPrefs(prefs);
+          }
+        }
 
-    function blocklistUnloadHandler(event) {
-      if (event.target.location == URI_BLOCKLIST_DIALOG) {
+        if (args.restart)
+          restartApp();
+
+        this._notifyObserversBlocklistUpdated();
+        Services.obs.removeObserver(applyBlocklistChanges, "addon-blocklist-closed");
+      };
+
+      Services.obs.addObserver(applyBlocklistChanges, "addon-blocklist-closed");
+
+      if (Services.prefs.getBoolPref(PREF_BLOCKLIST_SUPPRESSUI, false)) {
         applyBlocklistChanges();
-        blocklistWindow.removeEventListener("unload", blocklistUnloadHandler);
+        return;
       }
-    }
 
-    let blocklistWindow = Services.ww.openWindow(null, URI_BLOCKLIST_DIALOG, "",
-                            "chrome,centerscreen,dialog,titlebar", args);
-    if (blocklistWindow)
-      blocklistWindow.addEventListener("unload", blocklistUnloadHandler);
+      function blocklistUnloadHandler(event) {
+        if (event.target.location == URI_BLOCKLIST_DIALOG) {
+          applyBlocklistChanges();
+          blocklistWindow.removeEventListener("unload", blocklistUnloadHandler);
+        }
+      }
+
+      let blocklistWindow = Services.ww.openWindow(null, URI_BLOCKLIST_DIALOG, "",
+                              "chrome,centerscreen,dialog,titlebar", args);
+      if (blocklistWindow)
+        blocklistWindow.addEventListener("unload", blocklistUnloadHandler);
+    });
   },
 
   classID: Components.ID("{66354bc9-7ed1-4692-ae1d-8da97d6b205e}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                          Ci.nsIBlocklistService,
                                          Ci.nsITimerCallback]),
 };
 
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_severities.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklist_severities.js
@@ -9,18 +9,18 @@ ChromeUtils.import("resource://testing-c
 
 var gTestserver = AddonTestUtils.createHttpServer({hosts: ["example.com"]});
 gTestserver.registerDirectory("/data/", do_get_file("data"));
 
 // Workaround for Bug 658720 - URL formatter can leak during xpcshell tests
 const PREF_BLOCKLIST_ITEM_URL = "extensions.blocklist.itemURL";
 Services.prefs.setCharPref(PREF_BLOCKLIST_ITEM_URL, "http://example.com/blocklist/%blockID%");
 
-async function getAddonBlocklistURL(addon) {
-  let entry = await Services.blocklist.getAddonBlocklistEntry(addon);
+function getAddonBlocklistURL(addon) {
+  let entry = Services.blocklist.getAddonBlocklistEntry(addon);
   return entry && entry.url;
 }
 
 var ADDONS = [{
   // Tests how the blocklist affects a disabled add-on
   id: "test_bug455906_1@tests.mozilla.org",
   name: "Bug 455906 Addon Test 1",
   version: "5",
@@ -361,21 +361,21 @@ add_task(async function test_pt3() {
   equal(check_plugin_state(PLUGINS[2]), "false,true");
   equal(check_plugin_state(PLUGINS[3]), "true,true");
   equal(check_plugin_state(PLUGINS[4]), "false,true");
 
   // Should have gained the blocklist state but no longer be soft disabled
   checkAddonState(addons[3], {userDisabled: false, softDisabled: false, appDisabled: true});
 
   // Check blockIDs are correct
-  equal(await getAddonBlocklistURL(addons[0]), create_blocklistURL(addons[0].id));
-  equal(await getAddonBlocklistURL(addons[1]), create_blocklistURL(addons[1].id));
-  equal(await getAddonBlocklistURL(addons[2]), create_blocklistURL(addons[2].id));
-  equal(await getAddonBlocklistURL(addons[3]), create_blocklistURL(addons[3].id));
-  equal(await getAddonBlocklistURL(addons[4]), create_blocklistURL(addons[4].id));
+  equal(getAddonBlocklistURL(addons[0]), create_blocklistURL(addons[0].id));
+  equal(getAddonBlocklistURL(addons[1]), create_blocklistURL(addons[1].id));
+  equal(getAddonBlocklistURL(addons[2]), create_blocklistURL(addons[2].id));
+  equal(getAddonBlocklistURL(addons[3]), create_blocklistURL(addons[3].id));
+  equal(getAddonBlocklistURL(addons[4]), create_blocklistURL(addons[4].id));
 
   // All plugins have the same blockID on the test
   equal(Services.blocklist.getPluginBlocklistURL(PLUGINS[0]), create_blocklistURL("test_bug455906_plugin"));
   equal(Services.blocklist.getPluginBlocklistURL(PLUGINS[1]), create_blocklistURL("test_bug455906_plugin"));
   equal(Services.blocklist.getPluginBlocklistURL(PLUGINS[2]), create_blocklistURL("test_bug455906_plugin"));
   equal(Services.blocklist.getPluginBlocklistURL(PLUGINS[3]), create_blocklistURL("test_bug455906_plugin"));
   equal(Services.blocklist.getPluginBlocklistURL(PLUGINS[4]), create_blocklistURL("test_bug455906_plugin"));
 
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js
@@ -799,17 +799,17 @@ add_task(async function run_app_update_s
   check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED);
 });
 
 add_task(async function update_schema_2() {
   await promiseShutdownManager();
 
   await changeXPIDBVersion(100);
   gAppInfo.version = "2";
-  await promiseStartupManager(true);
+  startupManager(true);
 
   let [s1, s2, s3, s4, h, r] = await promiseAddonsByIDs(ADDON_IDS);
 
   check_addon(s1, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
   check_addon(s2, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
   check_addon(s3, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
   check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
   check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED);
@@ -823,17 +823,17 @@ add_task(async function update_schema_2(
 });
 
 add_task(async function update_schema_3() {
   await promiseRestartManager();
 
   await promiseShutdownManager();
   await changeXPIDBVersion(100);
   gAppInfo.version = "2.5";
-  await promiseStartupManager(true);
+  startupManager(true);
 
   let [s1, s2, s3, s4, h, r] = await promiseAddonsByIDs(ADDON_IDS);
 
   check_addon(s1, "1.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
   check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
   check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
   check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
   check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED);
@@ -856,17 +856,17 @@ add_task(async function update_schema_4(
   check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED);
 });
 
 add_task(async function update_schema_5() {
   await promiseShutdownManager();
 
   await changeXPIDBVersion(100);
   gAppInfo.version = "1";
-  await promiseStartupManager(true);
+  startupManager(true);
 
   let [s1, s2, s3, s4, h, r] = await promiseAddonsByIDs(ADDON_IDS);
 
   check_addon(s1, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED);
   check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED);
   check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED);
   check_addon(s4, "1.0", true, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED);
   check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED);
@@ -1057,17 +1057,17 @@ add_task(async function run_addon_change
 
   getFileForAddon(profileDir, softblock1_1.id).remove(true);
   getFileForAddon(profileDir, softblock2_1.id).remove(true);
   getFileForAddon(profileDir, softblock3_1.id).remove(true);
   getFileForAddon(profileDir, softblock4_1.id).remove(true);
   getFileForAddon(profileDir, hardblock_1.id).remove(true);
   getFileForAddon(profileDir, regexpblock_1.id).remove(true);
 
-  await promiseStartupManager(false);
+  startupManager(false);
   await promiseShutdownManager();
 
   writeInstallRDFForExtension(softblock1_2, profileDir);
   writeInstallRDFForExtension(softblock2_2, profileDir);
   writeInstallRDFForExtension(softblock3_2, profileDir);
   writeInstallRDFForExtension(softblock4_2, profileDir);
   writeInstallRDFForExtension(hardblock_2, profileDir);
   writeInstallRDFForExtension(regexpblock_2, profileDir);
@@ -1183,17 +1183,17 @@ add_task(async function run_background_u
 
   getFileForAddon(profileDir, softblock1_1.id).remove(true);
   getFileForAddon(profileDir, softblock2_1.id).remove(true);
   getFileForAddon(profileDir, softblock3_1.id).remove(true);
   getFileForAddon(profileDir, softblock4_1.id).remove(true);
   getFileForAddon(profileDir, hardblock_1.id).remove(true);
   getFileForAddon(profileDir, regexpblock_1.id).remove(true);
 
-  await promiseStartupManager(false);
+  startupManager(false);
   await promiseShutdownManager();
 
   writeInstallRDFForExtension(softblock1_3, profileDir);
   writeInstallRDFForExtension(softblock2_3, profileDir);
   writeInstallRDFForExtension(softblock3_3, profileDir);
   writeInstallRDFForExtension(softblock4_3, profileDir);
   writeInstallRDFForExtension(hardblock_3, profileDir);
   writeInstallRDFForExtension(regexpblock_3, profileDir);
@@ -1289,17 +1289,17 @@ add_task(async function run_manual_updat
 
   getFileForAddon(profileDir, softblock1_1.id).remove(true);
   getFileForAddon(profileDir, softblock2_1.id).remove(true);
   getFileForAddon(profileDir, softblock3_1.id).remove(true);
   getFileForAddon(profileDir, softblock4_1.id).remove(true);
   getFileForAddon(profileDir, hardblock_1.id).remove(true);
   getFileForAddon(profileDir, regexpblock_1.id).remove(true);
 
-  await promiseStartupManager(false);
+  startupManager(false);
   await promiseShutdownManager();
 
   writeInstallRDFForExtension(softblock1_1, profileDir);
   writeInstallRDFForExtension(softblock2_1, profileDir);
   writeInstallRDFForExtension(softblock3_1, profileDir);
   writeInstallRDFForExtension(softblock4_1, profileDir);
   writeInstallRDFForExtension(hardblock_1, profileDir);
   writeInstallRDFForExtension(regexpblock_1, profileDir);
--- a/toolkit/mozapps/extensions/test/xpcshell/test_upgrade_incompatible.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade_incompatible.js
@@ -3,17 +3,17 @@
 // unparseable after an application update, the extension becomes
 // disabled.  (See bug 1439600 for a concrete example of a situation where
 // this happened).
 add_task(async function test_upgrade_incompatible() {
   const ID = "incompatible-upgrade@tests.mozilla.org";
 
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
 
-  await promiseStartupManager(false);
+  await promiseStartupManager();
 
   let file = createTempWebExtensionFile({
     manifest: {
       applications: {gecko: {id: ID}},
     },
   });
 
   await Promise.all([promiseInstallFile(file), promiseWebExtensionStartup()]);
@@ -46,31 +46,10 @@ add_task(async function test_upgrade_inc
   Services.prefs.setIntPref("extensions.databaseSchema", 0);
   await promiseStartupManager(true);
 
   addon = await promiseAddonByID(ID);
   notEqual(addon, null);
   equal(addon.appDisabled, true);
 
   await promiseShutdownManager();
-
-  file = createTempWebExtensionFile({
-    manifest: {
-      applications: {gecko: {id: ID}},
-    },
-  });
-
-  // swap the old extension back in and check that we don't persist the disabled state forever.
-  await OS.File.move(file.path, path);
-  await promiseSetExtensionModifiedTime(path, timestamp);
-  Services.obs.notifyObservers(new FileUtils.File(path), "flush-cache-entry");
-
-  // Restart.  With the change to the DB schema we recompute compatibility.
-  Services.prefs.setIntPref("extensions.databaseSchema", 0);
-  await promiseStartupManager(true);
-
-  addon = await promiseAddonByID(ID);
-  notEqual(addon, null);
-  equal(addon.appDisabled, false);
-
-  await promiseShutdownManager();
 });
 
--- a/xpcom/system/nsIBlocklistService.idl
+++ b/xpcom/system/nsIBlocklistService.idl
@@ -59,20 +59,19 @@ interface nsIBlocklistService : nsISuppo
    *          is used.
    * @returns The STATE constant.
    */
   unsigned long getPluginBlocklistState(in nsIPluginTag plugin,
                                         [optional] in AString appVersion,
                                         [optional] in AString toolkitVersion);
 
   /**
-   * Returns a promise that resolves to the blocklist entry.
-   * The blocklist entry is an object with `state` and `url`
+   * Returns the blocklist entry, as an object with `state` and `url`
    * properties, if a blocklist entry for the add-on exists, or null
-   * otherwise.
+   * othereise.
 
    * @param   addon
    *          The addon object to match.
    * @param   appVersion
    *          The version of the application we are checking in the blocklist.
    *          If this parameter is null, the version of the running application
    *          is used.
    * @param   toolkitVersion