Bug 853388: Keep trying to save JSON even if read or save fails; r=unfocused
☠☠ backed out by 960ecd36a714 ☠ ☠
authorIrving Reid <irving@mozilla.com>
Thu, 08 Aug 2013 16:08:42 -0400
changeset 149811 607b35c777f079c2b097aed34aa0bd528afadece
parent 149810 40c48d65e38287193f978193268b10cbe9a051f1
child 149812 a0670c5cac399ccaf65b9f13114ee29a4672e3f2
push idunknown
push userunknown
push dateunknown
reviewersunfocused
bugs853388
milestone26.0a1
Bug 853388: Keep trying to save JSON even if read or save fails; r=unfocused
toolkit/mozapps/extensions/DeferredSave.jsm
toolkit/mozapps/extensions/XPIProvider.jsm
toolkit/mozapps/extensions/XPIProviderUtils.js
toolkit/mozapps/extensions/test/xpcshell/head_addons.js
toolkit/mozapps/extensions/test/xpcshell/test_ChromeManifestParser.js
toolkit/mozapps/extensions/test/xpcshell/test_DeferredSave.js
toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js
toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js
toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js
toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js
toolkit/mozapps/extensions/test/xpcshell/test_bug371495.js
toolkit/mozapps/extensions/test/xpcshell/test_bug384052.js
toolkit/mozapps/extensions/test/xpcshell/test_bug397778.js
toolkit/mozapps/extensions/test/xpcshell/test_bug425657.js
toolkit/mozapps/extensions/test/xpcshell/test_bug455906.js
toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js
toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3_strictcompat.js
toolkit/mozapps/extensions/test/xpcshell/test_bug470377_4.js
toolkit/mozapps/extensions/test/xpcshell/test_bug521905.js
toolkit/mozapps/extensions/test/xpcshell/test_bug526598.js
toolkit/mozapps/extensions/test/xpcshell/test_bug541420.js
toolkit/mozapps/extensions/test/xpcshell/test_bug542391.js
toolkit/mozapps/extensions/test/xpcshell/test_bug559800.js
toolkit/mozapps/extensions/test/xpcshell/test_bug563256.js
toolkit/mozapps/extensions/test/xpcshell/test_bug564030.js
toolkit/mozapps/extensions/test/xpcshell/test_bug566626.js
toolkit/mozapps/extensions/test/xpcshell/test_bug567184.js
toolkit/mozapps/extensions/test/xpcshell/test_bug569138.js
toolkit/mozapps/extensions/test/xpcshell/test_bug576735.js
toolkit/mozapps/extensions/test/xpcshell/test_bug587088.js
toolkit/mozapps/extensions/test/xpcshell/test_bug595573.js
toolkit/mozapps/extensions/test/xpcshell/test_bug596607.js
toolkit/mozapps/extensions/test/xpcshell/test_bug616841.js
toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js
toolkit/mozapps/extensions/test/xpcshell/test_bug659772.js
toolkit/mozapps/extensions/test/xpcshell/test_bug675371.js
toolkit/mozapps/extensions/test/xpcshell/test_bug740612.js
toolkit/mozapps/extensions/test/xpcshell/test_bug753900.js
toolkit/mozapps/extensions/test/xpcshell/test_bug757663.js
toolkit/mozapps/extensions/test/xpcshell/test_cacheflush.js
toolkit/mozapps/extensions/test/xpcshell/test_checkcompatibility.js
toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js
toolkit/mozapps/extensions/test/xpcshell/test_disable.js
toolkit/mozapps/extensions/test/xpcshell/test_distribution.js
toolkit/mozapps/extensions/test/xpcshell/test_dss.js
toolkit/mozapps/extensions/test/xpcshell/test_duplicateplugins.js
toolkit/mozapps/extensions/test/xpcshell/test_error.js
toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js
toolkit/mozapps/extensions/test/xpcshell/test_fuel.js
toolkit/mozapps/extensions/test/xpcshell/test_general.js
toolkit/mozapps/extensions/test/xpcshell/test_getresource.js
toolkit/mozapps/extensions/test/xpcshell/test_hasbinarycomponents.js
toolkit/mozapps/extensions/test/xpcshell/test_hotfix.js
toolkit/mozapps/extensions/test/xpcshell/test_install.js
toolkit/mozapps/extensions/test/xpcshell/test_install_icons.js
toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js
toolkit/mozapps/extensions/test/xpcshell/test_langpack.js
toolkit/mozapps/extensions/test/xpcshell/test_locale.js
toolkit/mozapps/extensions/test/xpcshell/test_locked.js
toolkit/mozapps/extensions/test/xpcshell/test_locked2.js
toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js
toolkit/mozapps/extensions/test/xpcshell/test_manifest.js
toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js
toolkit/mozapps/extensions/test/xpcshell/test_migrate1.js
toolkit/mozapps/extensions/test/xpcshell/test_migrate2.js
toolkit/mozapps/extensions/test/xpcshell/test_migrate3.js
toolkit/mozapps/extensions/test/xpcshell/test_migrate5.js
toolkit/mozapps/extensions/test/xpcshell/test_onPropertyChanged_appDisabled.js
toolkit/mozapps/extensions/test/xpcshell/test_pluginchange.js
toolkit/mozapps/extensions/test/xpcshell/test_plugins.js
toolkit/mozapps/extensions/test/xpcshell/test_registry.js
toolkit/mozapps/extensions/test/xpcshell/test_safemode.js
toolkit/mozapps/extensions/test/xpcshell/test_startup.js
toolkit/mozapps/extensions/test/xpcshell/test_syncGUID.js
toolkit/mozapps/extensions/test/xpcshell/test_targetPlatforms.js
toolkit/mozapps/extensions/test/xpcshell/test_theme.js
toolkit/mozapps/extensions/test/xpcshell/test_uninstall.js
toolkit/mozapps/extensions/test/xpcshell/test_update.js
toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js
toolkit/mozapps/extensions/test/xpcshell/test_updateid.js
toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js
toolkit/mozapps/extensions/test/xpcshell/test_upgrade_strictcompat.js
--- a/toolkit/mozapps/extensions/DeferredSave.jsm
+++ b/toolkit/mozapps/extensions/DeferredSave.jsm
@@ -68,32 +68,36 @@ function DeferredSave(aPath, aDataProvid
   this._path = aPath;
   this._dataProvider = aDataProvider;
 
   this._timer = null;
 
   // Some counters for telemetry
   // The total number of times the file was written
   this.totalSaves = 0;
+
   // The number of times the data became dirty while
   // another save was in progress
   this.overlappedSaves = 0;
 
+  // Error returned by the most recent write (if any)
+  this._lastError = null;
+
   if (aDelay && (aDelay > 0))
     this._delay = aDelay;
   else
     this._delay = DEFAULT_SAVE_DELAY_MS;
 }
 
 DeferredSave.prototype = {
   get dirty() {
     return this._pending || this.writeInProgress;
   },
 
-  get error() {
+  get lastError() {
     return this._lastError;
   },
 
   // Start the pending timer if data is dirty
   _startTimer: function() {
     if (!this._pending) {
       return;
     }
--- a/toolkit/mozapps/extensions/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/XPIProvider.jsm
@@ -1879,19 +1879,19 @@ var XPIProvider = {
 
     // This is needed to allow xpcshell tests to simulate a restart
     this.extensionsActive = false;
 
     // Remove URI mappings again
     delete this._uriMappings;
 
     if (gLazyObjectsLoaded) {
-      XPIDatabase.shutdown(function shutdownCallback() {
+      XPIDatabase.shutdown(function shutdownCallback(saveError) {
         LOG("Notifying XPI shutdown observers");
-        Services.obs.notifyObservers(null, "xpi-provider-shutdown", null);
+        Services.obs.notifyObservers(null, "xpi-provider-shutdown", saveError);
       });
     }
     else {
       LOG("Notifying XPI shutdown observers");
       Services.obs.notifyObservers(null, "xpi-provider-shutdown", null);
     }
   },
 
@@ -2589,19 +2589,18 @@ var XPIProvider = {
      * @return a boolean indicating if flushing caches is required to complete
      *         changing this add-on
      */
     function updateDescriptor(aInstallLocation, aOldAddon, aAddonState) {
       LOG("Add-on " + aOldAddon.id + " moved to " + aAddonState.descriptor);
 
       aOldAddon.descriptor = aAddonState.descriptor;
       aOldAddon.visible = !(aOldAddon.id in visibleAddons);
-
-      // Update the database
-      XPIDatabase.setAddonDescriptor(aOldAddon, aAddonState.descriptor);
+      XPIDatabase.saveChanges();
+
       if (aOldAddon.visible) {
         visibleAddons[aOldAddon.id] = aOldAddon;
 
         if (aOldAddon.bootstrap && aOldAddon.active) {
           let bootstrap = oldBootstrappedAddons[aOldAddon.id];
           bootstrap.descriptor = aAddonState.descriptor;
           XPIProvider.bootstrappedAddons[aOldAddon.id] = bootstrap;
         }
@@ -3183,18 +3182,16 @@ var XPIProvider = {
       // If the state has changed then we must update the database
       let cache = Prefs.getCharPref(PREF_INSTALL_CACHE, null);
       updateDatabase = cache != JSON.stringify(state);
     }
 
     // If the database doesn't exist and there are add-ons installed then we
     // must update the database however if there are no add-ons then there is
     // no need to update the database.
-    // Avoid using XPIDatabase.dbFileExists, as that code is lazy-loaded,
-    // and we want to avoid loading it until absolutely necessary.
     let dbFile = FileUtils.getFile(KEY_PROFILEDIR, [FILE_DATABASE], true);
     if (!dbFile.exists())
       updateDatabase = state.length > 0;
 
     if (!updateDatabase) {
       let bootstrapDescriptors = [this.bootstrappedAddons[b].descriptor
                                   for (b in this.bootstrappedAddons)];
 
--- a/toolkit/mozapps/extensions/XPIProviderUtils.js
+++ b/toolkit/mozapps/extensions/XPIProviderUtils.js
@@ -344,17 +344,16 @@ function DBAddonInternal(aLoaded) {
     this._sourceBundle = this._installLocation.getLocationForID(this.id);
   }
   catch (e) {
     // An exception will be thrown if the add-on appears in the database but
     // not on disk. In general this should only happen during startup as
     // this change is being detected.
   }
 
-  // XXX Can we redesign pendingUpgrade?
   XPCOMUtils.defineLazyGetter(this, "pendingUpgrade",
     function DBA_pendingUpgradeGetter() {
       for (let install of XPIProvider.installs) {
         if (install.state == AddonManager.STATE_INSTALLED &&
             !(install.addon.inDatabase) &&
             install.addon.id == this.id &&
             install.installLocation == this._installLocation) {
           delete this.pendingUpgrade;
@@ -421,93 +420,88 @@ this.XPIDatabase = {
   // true if the database connection has been opened
   initialized: false,
   // The database file
   jsonFile: FileUtils.getFile(KEY_PROFILEDIR, [FILE_JSON_DB], true),
   // Migration data loaded from an old version of the database.
   migrateData: null,
   // Active add-on directories loaded from extensions.ini and prefs at startup.
   activeBundles: null,
-  // Special handling for when the database is locked at first load
-  lockedDatabase: false,
+
+  // Saved error object if we fail to read an existing database
+  _loadError: null,
 
-  // XXX may be able to refactor this away
-  get dbfileExists() {
-    delete this.dbfileExists;
-    return this.dbfileExists = this.jsonFile.exists();
-  },
-  set dbfileExists(aValue) {
-    delete this.dbfileExists;
-    return this.dbfileExists = aValue;
+  // Error reported by our most recent attempt to read or write the database, if any
+  get lastError() {
+    if (this._loadError)
+      return this._loadError;
+    if (this._deferredSave)
+      return this._deferredSave.lastError;
+    return null;
   },
 
   /**
    * Mark the current stored data dirty, and schedule a flush to disk
    */
   saveChanges: function() {
     if (!this.initialized) {
       throw new Error("Attempt to use XPI database when it is not initialized");
     }
 
-    // handle the "in memory only" case
-    if (this.lockedDatabase) {
-      return;
-    }
-
     if (!this._deferredSave) {
       this._deferredSave = new DeferredSave(this.jsonFile.path,
                                             () => JSON.stringify(this),
                                             ASYNC_SAVE_DELAY_MS);
     }
 
     let promise = this._deferredSave.saveChanges();
     if (!this._schemaVersionSet) {
       this._schemaVersionSet = true;
       promise.then(
         count => {
           // Update the XPIDB schema version preference the first time we successfully
           // save the database.
           LOG("XPI Database saved, setting schema version preference to " + DB_SCHEMA);
           Services.prefs.setIntPref(PREF_DB_SCHEMA, DB_SCHEMA);
+          // Reading the DB worked once, so we don't need the load error
+          this._loadError = null;
         },
         error => {
           // Need to try setting the schema version again later
           this._schemaVersionSet = false;
           WARN("Failed to save XPI database", error);
+          // this._deferredSave.lastError has the most recent error so we don't
+          // need this any more
+          this._loadError = null;
         });
     }
   },
 
   flush: function() {
     // handle the "in memory only" and "saveChanges never called" cases
     if (!this._deferredSave) {
-      let done = Promise.defer();
-      done.resolve(0);
-      return done.promise;
+      return Promise.resolve(0);
     }
 
     return this._deferredSave.flush();
   },
 
   /**
-   * Converts the current internal state of the XPI addon database to JSON
+   * Converts the current internal state of the XPI addon database to
+   * a JSON.stringify()-ready structure
    */
   toJSON: function() {
     if (!this.addonDB) {
       // We never loaded the database?
       throw new Error("Attempt to save database without loading it first");
     }
 
-    let addons = [];
-    for (let [, addon] of this.addonDB) {
-      addons.push(addon);
-    }
     let toSave = {
       schemaVersion: DB_SCHEMA,
-      addons: addons
+      addons: [...this.addonDB.values()]
     };
     return toSave;
   },
 
   /**
    * Pull upgrade information from an existing SQLITE database
    *
    * @return false if there is no SQLITE database
@@ -620,27 +614,26 @@ this.XPIDatabase = {
         ERROR("bad JSON file contents");
         this.rebuildDatabase(aRebuildOnError);
         return;
       }
       if (inputAddons.schemaVersion != DB_SCHEMA) {
         // Handle mismatched JSON schema version. For now, we assume
         // compatibility for JSON data, though we throw away any fields we
         // don't know about
-        // XXX preserve unknown fields during save/restore
         LOG("JSON schema mismatch: expected " + DB_SCHEMA +
             ", actual " + inputAddons.schemaVersion);
       }
       // If we got here, we probably have good data
       // Make AddonInternal instances from the loaded data and save them
       let addonDB = new Map();
-      inputAddons.addons.forEach(function(loadedAddon) {
+      for (let loadedAddon of inputAddons.addons) {
         let newAddon = new DBAddonInternal(loadedAddon);
         addonDB.set(newAddon._key, newAddon);
-      });
+      };
       this.addonDB = addonDB;
       LOG("Successfully read XPI database");
       this.initialized = true;
     }
     catch(e) {
       // If we catch and log a SyntaxError from the JSON
       // parser, the xpcshell test harness fails the test for us: bug 870828
       if (e.name == "SyntaxError") {
@@ -672,25 +665,24 @@ this.XPIDatabase = {
       this.migrateData = this.getMigrateDataFromRDF();
     }
 
     this.rebuildDatabase(aRebuildOnError);
   },
 
   /**
    * Reconstruct when the DB file exists but is unreadable
-   * (for example because read permission is denied
+   * (for example because read permission is denied)
    */
   rebuildUnreadableDB: function(aError, aRebuildOnError) {
     WARN("Extensions database " + this.jsonFile.path +
         " exists but is not readable; rebuilding in memory", aError);
-    // XXX open question - if we can overwrite at save time, should we, or should we
-    // leave the locked database in case we can recover from it next time we start up?
-    // The old code made one attempt to remove the locked file before it rebuilt in memory
-    this.lockedDatabase = true;
+    // Remember the error message until we try and write at least once, so
+    // we know at shutdown time that there was a problem
+    this._loadError = aError;
     // XXX TELEMETRY report when this happens?
     this.rebuildDatabase(aRebuildOnError);
   },
 
   /**
    * Open and read the XPI database asynchronously, upgrading if
    * necessary. If any DB load operation fails, we need to
    * synchronously rebuild the DB from the installed extensions.
@@ -968,44 +960,46 @@ this.XPIDatabase = {
   },
 
   /**
    * Shuts down the database connection and releases all cached objects.
    */
   shutdown: function XPIDB_shutdown(aCallback) {
     LOG("shutdown");
     if (this.initialized) {
-      // If we are running with an in-memory database then force a new
-      // extensions.ini to be written to disk on the next startup
-      if (this.lockedDatabase)
-        Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS, true);
+      // If our last database I/O had an error, try one last time to save.
+      if (this.lastError)
+        this.saveChanges();
 
       this.initialized = false;
-      let result = null;
 
       // Make sure any pending writes of the DB are complete, and we
       // finish cleaning up, and then call back
       this.flush()
         .then(null, error => {
           ERROR("Flush of XPI database failed", error);
-          Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS, true);
-          result = error;
           return 0;
         })
         .then(count => {
+          // If our last attempt to read or write the DB failed, force a new
+          // extensions.ini to be written to disk on the next startup
+          let lastSaveFailed = this.lastError;
+          if (lastSaveFailed)
+            Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS, true);
+
           // Clear out the cached addons data loaded from JSON
           delete this.addonDB;
           delete this._dbPromise;
           // same for the deferred save
           delete this._deferredSave;
           // re-enable the schema version setter
           delete this._schemaVersionSet;
 
           if (aCallback)
-            aCallback(result);
+            aCallback(lastSaveFailed);
         });
     }
     else {
       if (aCallback)
         aCallback(null);
     }
   },
 
@@ -1337,48 +1331,32 @@ this.XPIDatabase = {
       throw new Error("Addon sync GUID conflict for addon " + aAddon._key +
           ": " + otherAddon._key + " already has GUID " + aGUID);
     }
     aAddon.syncGUID = aGUID;
     this.saveChanges();
   },
 
   /**
-   * Synchronously sets the file descriptor for an add-on.
-   * XXX IRVING could replace this with setAddonProperties
-   *
-   * @param  aAddon
-   *         The DBAddonInternal being updated
-   * @param  aDescriptor
-   *         File path of the installed addon
-   */
-  setAddonDescriptor: function XPIDB_setAddonDescriptor(aAddon, aDescriptor) {
-    aAddon.descriptor = aDescriptor;
-    this.saveChanges();
-  },
-
-  /**
    * Synchronously updates an add-on's active flag in the database.
    *
    * @param  aAddon
    *         The DBAddonInternal to update
    */
   updateAddonActive: function XPIDB_updateAddonActive(aAddon, aActive) {
     LOG("Updating active state for add-on " + aAddon.id + " to " + aActive);
 
     aAddon.active = aActive;
     this.saveChanges();
   },
 
   /**
    * Synchronously calculates and updates all the active flags in the database.
    */
   updateActiveAddons: function XPIDB_updateActiveAddons() {
-    // XXX IRVING this may get called during XPI-utils shutdown
-    // XXX need to make sure PREF_PENDING_OPERATIONS handling is clean
     LOG("Updating add-on states");
     for (let [, addon] of this.addonDB) {
       let newActive = (addon.visible && !addon.userDisabled &&
                       !addon.softDisabled && !addon.appDisabled &&
                       !addon.pendingUninstall);
       if (newActive != addon.active) {
         addon.active = newActive;
         this.saveChanges();
--- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
@@ -339,16 +339,20 @@ function do_check_compatibilityoverride(
 }
 
 function do_check_icons(aActual, aExpected) {
   for (var size in aExpected) {
     do_check_eq(remove_port(aActual[size]), remove_port(aExpected[size]));
   }
 }
 
+// Record the error (if any) from trying to save the XPI
+// database at shutdown time
+let gXPISaveError = null;
+
 /**
  * Starts up the add-on manager as if it was started by the application.
  *
  * @param  aAppChanged
  *         An optional boolean parameter to simulate the case where the
  *         application has changed version since the last run. If not passed it
  *         defaults to true
  */
@@ -391,56 +395,51 @@ function restartManager(aNewVersion) {
     startupManager(false);
   }
 }
 
 function shutdownManager() {
   if (!gInternalManager)
     return;
 
-  let obs = AM_Cc["@mozilla.org/observer-service;1"].
-            getService(AM_Ci.nsIObserverService);
-
   let xpiShutdown = false;
-  obs.addObserver({
+  Services.obs.addObserver({
     observe: function(aSubject, aTopic, aData) {
       xpiShutdown = true;
-      obs.removeObserver(this, "xpi-provider-shutdown");
+      gXPISaveError = aData;
+      Services.obs.removeObserver(this, "xpi-provider-shutdown");
     }
   }, "xpi-provider-shutdown", false);
 
   let repositoryShutdown = false;
-  obs.addObserver({
+  Services.obs.addObserver({
     observe: function(aSubject, aTopic, aData) {
       repositoryShutdown = true;
-      obs.removeObserver(this, "addon-repository-shutdown");
+      Services.obs.removeObserver(this, "addon-repository-shutdown");
     }
   }, "addon-repository-shutdown", false);
 
-  obs.notifyObservers(null, "quit-application-granted", null);
+  Services.obs.notifyObservers(null, "quit-application-granted", null);
   let scope = Components.utils.import("resource://gre/modules/AddonManager.jsm");
   scope.AddonManagerInternal.shutdown();
   gInternalManager = null;
 
   AddonRepository.shutdown();
 
   // Load the add-ons list as it was after application shutdown
   loadAddonsList();
 
   // Clear any crash report annotations
   gAppInfo.annotations = {};
 
-  let thr = AM_Cc["@mozilla.org/thread-manager;1"].
-            getService(AM_Ci.nsIThreadManager).
-            mainThread;
+  let thr = Services.tm.mainThread;
 
   // Wait until we observe the shutdown notifications
   while (!repositoryShutdown || !xpiShutdown) {
-    if (thr.hasPendingEvents())
-      thr.processNextEvent(false);
+    thr.processNextEvent(true);
   }
 
   // Force the XPIProvider provider to reload to better
   // simulate real-world usage.
   scope = Components.utils.import("resource://gre/modules/XPIProvider.jsm");
   AddonManagerPrivate.unregisterProvider(scope.XPIProvider);
   Components.utils.unload("resource://gre/modules/XPIProvider.jsm");
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_ChromeManifestParser.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_ChromeManifestParser.js
@@ -98,11 +98,11 @@ function run_test_1() {
     manifest = ChromeManifestParser.parseSync(manifestURI);
 
     do_check_true(Array.isArray(manifest));
     do_check_eq(manifest.length, expected.length);
     for (let i = 0; i < manifest.length; i++) {
       do_check_eq(JSON.stringify(manifest[i]), JSON.stringify(expected[i]));
     }
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_DeferredSave.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_DeferredSave.js
@@ -32,18 +32,18 @@ function DeferredSaveTester(aDelay, aDat
       return tester.saver.saveChanges();
     },
 
     flush: (aWriteHandler) => {
       tester.writeHandler = aWriteHandler || writer;
       return tester.saver.flush();
     },
 
-    get error() {
-      return tester.saver.error;
+    get lastError() {
+      return tester.saver.lastError;
     }
   };
 
   // Default write handler for most cases where the test case doesn't need
   // to do anything while the write is in progress; just completes the write
   // on the next event loop
   function writer(aTester) {
     do_print("default write callback");
@@ -149,21 +149,21 @@ add_task(function test_error_immediate()
   function writeFail(aTester) {
     aTester.waDeferred.reject(testError);
   }
 
   yield tester.save("test_error_immediate", writeFail).then(
     count => do_throw("Did not get expected error"),
     error => do_check_eq(testError.message, error.message)
     );
-  do_check_eq(testError, tester.error);
+  do_check_eq(testError, tester.lastError);
 
   // This write should succeed and clear the error
   yield tester.save("test_error_immediate succeeds");
-  do_check_eq(null, tester.error);
+  do_check_eq(null, tester.lastError);
   // The failed save attempt counts in our total
   do_check_eq(2, tester.saver.totalSaves);
 });
 
 // Save one set of changes, then while the write is in progress, modify the
 // data two more times. Test that we re-write the dirty data exactly once
 // after the first write succeeds
 add_task(function dirty_while_writing() {
--- a/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_blocklistchange.js
@@ -330,22 +330,22 @@ const ADDON_IDS = ["softblock1@tests.moz
                    "softblock4@tests.mozilla.org",
                    "softblock5@tests.mozilla.org",
                    "hardblock@tests.mozilla.org",
                    "regexpblock@tests.mozilla.org"];
 
 // Don't need the full interface, attempts to call other methods will just
 // throw which is just fine
 var WindowWatcher = {
-  openWindow: function(parent, url, name, features, arguments) {
+  openWindow: function(parent, url, name, features, openArgs) {
     // Should be called to list the newly blocklisted items
     do_check_eq(url, URI_EXTENSION_BLOCKLIST_DIALOG);
 
     // Simulate auto-disabling any softblocks
-    var list = arguments.wrappedJSObject.list;
+    var list = openArgs.wrappedJSObject.list;
     list.forEach(function(aItem) {
       if (!aItem.blocked)
         aItem.disable = true;
     });
 
     //run the code after the blocklist is closed
     Services.obs.notifyObservers(null, "addon-blocklist-closed", null);
 
@@ -1324,17 +1324,17 @@ add_test(function run_manual_update_2_te
   writeInstallRDFForExtension(softblock3_1, profileDir);
   writeInstallRDFForExtension(softblock4_1, profileDir);
   writeInstallRDFForExtension(softblock5_1, profileDir);
   writeInstallRDFForExtension(hardblock_1, profileDir);
   writeInstallRDFForExtension(regexpblock_1, profileDir);
 
   startupManager(false);
 
-  AddonManager.getAddonsByIDs(ADDON_IDS, function([s1, s2, s3, s4, s5, h, r]) {
+  AddonManager.getAddonsByIDs(ADDON_IDS, callback_soon(function([s1, s2, s3, s4, s5, h, r]) {
 
     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(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED);
     check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED);
 
     s2.userDisabled = false;
@@ -1342,17 +1342,18 @@ add_test(function run_manual_update_2_te
     check_addon(s2, "1.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
     s3.userDisabled = false;
     check_addon(s3, "1.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
     restartManager();
 
     manual_update("2", function manual_update_2_2() {
       restartManager();
 
-      AddonManager.getAddonsByIDs(ADDON_IDS, function([s1, s2, s3, s4, s5, h, r]) {
+      AddonManager.getAddonsByIDs(ADDON_IDS,
+       callback_soon(function([s1, s2, s3, s4, s5, h, r]) {
 
         check_addon(s1, "2.0", true, true, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
         check_addon(s2, "2.0", true, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
         check_addon(s3, "2.0", false, false, Ci.nsIBlocklistService.STATE_SOFTBLOCKED);
         // Can't manually update to a hardblocked add-on
         check_addon(h, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED);
         check_addon(r, "1.0", false, false, Ci.nsIBlocklistService.STATE_BLOCKED);
 
@@ -1370,19 +1371,19 @@ add_test(function run_manual_update_2_te
             check_addon(r, "3.0", false, false, Ci.nsIBlocklistService.STATE_NOT_BLOCKED);
 
             s1.userDisabled = false;
             s2.userDisabled = false;
             s4.userDisabled = true;
             run_next_test();
           });
         });
-      });
+      }));
     });
-  });
+  }));
 });
 
 // Uses the API to install blocked add-ons from the local filesystem
 add_test(function run_local_install_test() {
   do_print("Test: " + arguments.callee.name + "\n");
   shutdownManager();
 
   getFileForAddon(profileDir, softblock1_1.id).remove(true);
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bootstrap.js
@@ -450,27 +450,27 @@ function run_test_7() {
 function check_test_7() {
   ensure_test_completed();
   do_check_eq(getInstalledVersion(), 0);
   do_check_eq(getActiveVersion(), 0);
   do_check_eq(getShutdownReason(), ADDON_UNINSTALL);
   do_check_eq(getShutdownNewVersion(), 0);
   do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "2.0");
 
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
     do_check_eq(b1, null);
 
     restartManager();
 
     AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(newb1) {
       do_check_eq(newb1, null);
 
       do_check_bootstrappedPref(run_test_8);
     });
-  });
+  }));
 }
 
 // Test that a bootstrapped extension dropped into the profile loads properly
 // on startup and doesn't cause an EM restart
 function run_test_8() {
   shutdownManager();
 
   manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir,
@@ -666,20 +666,23 @@ function run_test_12() {
     do_check_true(b1.isActive);
     do_check_eq(getInstalledVersion(), 1);
     do_check_eq(getActiveVersion(), 1);
     do_check_eq(getStartupReason(), ADDON_INSTALL);
     do_check_eq(getStartupOldVersion(), 0);
     do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
 
     b1.uninstall();
-    restartManager();
+    do_execute_soon(test_12_restart);
+  });
+}
 
-    do_check_bootstrappedPref(run_test_13);
-  });
+function test_12_restart() {
+  restartManager();
+  do_check_bootstrappedPref(run_test_13);
 }
 
 
 // Tests that installing a bootstrapped extension with an invalid application
 // entry doesn't call it's startup method
 function run_test_13() {
   prepare_test({ }, [
     "onNewInstall"
@@ -698,17 +701,17 @@ function run_test_13() {
     prepare_test({
       "bootstrap1@tests.mozilla.org": [
         ["onInstalling", false],
         "onInstalled"
       ]
     }, [
       "onInstallStarted",
       "onInstallEnded",
-    ], function() {do_execute_soon(check_test_13)});
+    ], callback_soon(check_test_13));
     install.install();
   });
 }
 
 function check_test_13() {
   AddonManager.getAllInstalls(function(installs) {
     // There should be no active installs now since the install completed and
     // doesn't require a restart.
@@ -719,33 +722,37 @@ function check_test_13() {
       do_check_eq(b1.version, "3.0");
       do_check_true(b1.appDisabled);
       do_check_false(b1.userDisabled);
       do_check_false(b1.isActive);
       do_check_eq(getInstalledVersion(), 3);  // We call install even for disabled add-ons
       do_check_eq(getActiveVersion(), 0);     // Should not have called startup though
       do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0");
 
-      restartManager();
+      do_execute_soon(test_13_restart);
+    });
+  });
+}
+
+function test_13_restart() {
+  restartManager();
 
-      AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
-        do_check_neq(b1, null);
-        do_check_eq(b1.version, "3.0");
-        do_check_true(b1.appDisabled);
-        do_check_false(b1.userDisabled);
-        do_check_false(b1.isActive);
-        do_check_eq(getInstalledVersion(), 3);  // We call install even for disabled add-ons
-        do_check_eq(getActiveVersion(), 0);     // Should not have called startup though
-        do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0");
+  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+    do_check_neq(b1, null);
+    do_check_eq(b1.version, "3.0");
+    do_check_true(b1.appDisabled);
+    do_check_false(b1.userDisabled);
+    do_check_false(b1.isActive);
+    do_check_eq(getInstalledVersion(), 3);  // We call install even for disabled add-ons
+    do_check_eq(getActiveVersion(), 0);     // Should not have called startup though
+    do_check_not_in_crash_annotation("bootstrap1@tests.mozilla.org", "3.0");
 
-        do_check_bootstrappedPref(function() {
-          b1.uninstall();
-          do_execute_soon(run_test_14);
-        });
-      });
+    do_check_bootstrappedPref(function() {
+      b1.uninstall();
+      do_execute_soon(run_test_14);
     });
   });
 }
 
 // Tests that a bootstrapped extension with an invalid target application entry
 // does not get loaded when detected during startup
 function run_test_14() {
   restartManager();
@@ -807,17 +814,17 @@ function run_test_15() {
         prepare_test({
           "bootstrap1@tests.mozilla.org": [
             ["onInstalling", false],
             "onInstalled"
           ]
         }, [
           "onInstallStarted",
           "onInstallEnded",
-        ], function() {do_execute_soon(check_test_15)});
+        ], callback_soon(check_test_15));
         install.install();
       });
     });
   });
   installAllFiles([do_get_addon("test_bootstrap1_1")], function test_15_addon_installed() { });
 }
 
 function check_test_15() {
@@ -849,17 +856,17 @@ function check_test_15() {
     });
   });
 }
 
 // Tests that bootstrapped extensions don't get loaded when in safe mode
 function run_test_16() {
   resetPrefs();
   waitForPref("bootstraptest.startup_reason", function test_16_after_startup() {
-    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
       // Should have installed and started
       do_check_eq(getInstalledVersion(), 1);
       do_check_eq(getActiveVersion(), 1);
       do_check_true(b1.isActive);
       do_check_eq(b1.iconURL, "chrome://foo/skin/icon.png");
       do_check_eq(b1.aboutURL, "chrome://foo/content/about.xul");
       do_check_eq(b1.optionsURL, "chrome://foo/content/options.xul");
 
@@ -867,17 +874,17 @@ function run_test_16() {
 
       // Should have stopped
       do_check_eq(getInstalledVersion(), 1);
       do_check_eq(getActiveVersion(), 0);
 
       gAppInfo.inSafeMode = true;
       startupManager(false);
 
-      AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+      AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
         // Should still be stopped
         do_check_eq(getInstalledVersion(), 1);
         do_check_eq(getActiveVersion(), 0);
         do_check_false(b1.isActive);
         do_check_eq(b1.iconURL, null);
         do_check_eq(b1.aboutURL, null);
         do_check_eq(b1.optionsURL, null);
 
@@ -887,20 +894,20 @@ function run_test_16() {
 
         // Should have started
         do_check_eq(getInstalledVersion(), 1);
         do_check_eq(getActiveVersion(), 1);
 
         AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
           b1.uninstall();
 
-          run_test_17();
+          do_execute_soon(run_test_17);
         });
-      });
-    });
+      }));
+    }));
   });
   installAllFiles([do_get_addon("test_bootstrap1_1")], function() { });
 }
 
 // Check that a bootstrapped extension in a non-profile location is loaded
 function run_test_17() {
   shutdownManager();
 
@@ -1017,17 +1024,17 @@ function run_test_20() {
     do_check_eq(getInstallReason(), ADDON_UPGRADE);
     do_check_eq(getStartupReason(), APP_STARTUP);
 
     do_check_eq(getShutdownNewVersion(), 0);
     do_check_eq(getUninstallNewVersion(), 2);
     do_check_eq(getInstallOldVersion(), 1);
     do_check_eq(getStartupOldVersion(), 0);
 
-    run_test_21();
+    do_execute_soon(run_test_21);
   });
 }
 
 // Check that a detected removal reveals the non-profile one
 function run_test_21() {
   resetPrefs();
   shutdownManager();
 
@@ -1074,17 +1081,17 @@ function run_test_22() {
   let file = manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir,
                              "bootstrap1@tests.mozilla.org");
 
   // Make it look old so changes are detected
   setExtensionModifiedTime(file, file.lastModifiedTime - 5000);
 
   startupManager();
 
-  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
     // Should have installed and started
     do_check_eq(getInstalledVersion(), 1);
     do_check_eq(getActiveVersion(), 1);
     do_check_neq(b1, null);
     do_check_eq(b1.version, "1.0");
     do_check_true(b1.isActive);
 
     resetPrefs();
@@ -1118,17 +1125,17 @@ function run_test_22() {
       do_check_eq(getStartupOldVersion(), 0);
 
       do_check_bootstrappedPref(function() {
         b1.uninstall();
 
         run_test_23();
       });
     });
-  });
+  }));
 }
 
 
 // Tests that installing from a URL doesn't require a restart
 function run_test_23() {
   prepare_test({ }, [
     "onNewInstall"
   ]);
@@ -1192,27 +1199,27 @@ function check_test_23() {
       do_check_true(b1.hasResource("install.rdf"));
       do_check_true(b1.hasResource("bootstrap.js"));
       do_check_false(b1.hasResource("foo.bar"));
       do_check_in_crash_annotation("bootstrap1@tests.mozilla.org", "1.0");
 
       let dir = do_get_addon_root_uri(profileDir, "bootstrap1@tests.mozilla.org");
       do_check_eq(b1.getResourceURI("bootstrap.js").spec, dir + "bootstrap.js");
 
-      AddonManager.getAddonsWithOperationsByTypes(null, function(list) {
+      AddonManager.getAddonsWithOperationsByTypes(null, callback_soon(function(list) {
         do_check_eq(list.length, 0);
 
         restartManager();
-        AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+        AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
           b1.uninstall();
           restartManager();
 
           testserver.stop(run_test_24);
-        });
-      });
+        }));
+      }));
      });
     });
   });
 }
 
 // Tests that we recover from a broken preference
 function run_test_24() {
   resetPrefs();
@@ -1269,17 +1276,17 @@ function run_test_25() {
       do_check_eq(getInstalledVersion(), 1);
       do_check_eq(getActiveVersion(), 1);
 
       installAllFiles([do_get_addon("test_bootstrap1_4")], function() {
         // Needs a restart to complete this so the old version stays running
         do_check_eq(getInstalledVersion(), 1);
         do_check_eq(getActiveVersion(), 1);
 
-        AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+        AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
           do_check_neq(b1, null);
           do_check_eq(b1.version, "1.0");
           do_check_true(b1.isActive);
           do_check_true(hasFlag(b1.pendingOperations, AddonManager.PENDING_UPGRADE));
 
           restartManager();
 
           do_check_eq(getInstalledVersion(), 0);
@@ -1290,33 +1297,33 @@ function run_test_25() {
           AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
             do_check_neq(b1, null);
             do_check_eq(b1.version, "4.0");
             do_check_true(b1.isActive);
             do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
 
             do_check_bootstrappedPref(run_test_26);
           });
-        });
+        }));
       });
   });
   installAllFiles([do_get_addon("test_bootstrap1_1")], function test_25_installed() {
     do_print("test 25 install done");
   });
 }
 
 // Tests that updating from a normal add-on to a bootstrappable add-on calls
 // the install method
 function run_test_26() {
   installAllFiles([do_get_addon("test_bootstrap1_1")], function() {
     // Needs a restart to complete this
     do_check_eq(getInstalledVersion(), 0);
     do_check_eq(getActiveVersion(), 0);
 
-    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
       do_check_neq(b1, null);
       do_check_eq(b1.version, "4.0");
       do_check_true(b1.isActive);
       do_check_true(hasFlag(b1.pendingOperations, AddonManager.PENDING_UPGRADE));
 
       restartManager();
 
       do_check_eq(getInstalledVersion(), 1);
@@ -1327,17 +1334,17 @@ function run_test_26() {
       AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
         do_check_neq(b1, null);
         do_check_eq(b1.version, "1.0");
         do_check_true(b1.isActive);
         do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
 
         do_check_bootstrappedPref(run_test_27);
       });
-    });
+    }));
   });
 }
 
 // Tests that updating from a bootstrappable add-on to a normal add-on while
 // disabled calls the uninstall method
 function run_test_27() {
   AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
     do_check_neq(b1, null);
@@ -1350,17 +1357,17 @@ function run_test_27() {
 
     installAllFiles([do_get_addon("test_bootstrap1_4")], function() {
       // Updating disabled things happens immediately
       do_check_eq(getInstalledVersion(), 0);
       do_check_eq(getUninstallReason(), ADDON_UPGRADE);
       do_check_eq(getUninstallNewVersion(), 4);
       do_check_eq(getActiveVersion(), 0);
 
-      AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+      AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
         do_check_neq(b1, null);
         do_check_eq(b1.version, "4.0");
         do_check_false(b1.isActive);
         do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
 
         restartManager();
 
         do_check_eq(getInstalledVersion(), 0);
@@ -1369,33 +1376,33 @@ function run_test_27() {
         AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
           do_check_neq(b1, null);
           do_check_eq(b1.version, "4.0");
           do_check_false(b1.isActive);
           do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
 
           do_check_bootstrappedPref(run_test_28);
         });
-      });
+      }));
     });
   });
 }
 
 // Tests that updating from a normal add-on to a bootstrappable add-on when
 // disabled calls the install method but not the startup method
 function run_test_28() {
   installAllFiles([do_get_addon("test_bootstrap1_1")], function() {
    do_execute_soon(function bootstrap_disabled_downgrade_check() {
     // Doesn't need a restart to complete this
     do_check_eq(getInstalledVersion(), 1);
     do_check_eq(getInstallReason(), ADDON_DOWNGRADE);
     do_check_eq(getInstallOldVersion(), 4);
     do_check_eq(getActiveVersion(), 0);
 
-    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
+    AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", callback_soon(function(b1) {
       do_check_neq(b1, null);
       do_check_eq(b1.version, "1.0");
       do_check_false(b1.isActive);
       do_check_true(b1.userDisabled);
       do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
 
       restartManager();
 
@@ -1409,12 +1416,12 @@ function run_test_28() {
         do_check_eq(b1.version, "1.0");
         do_check_true(b1.isActive);
         do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
         do_check_eq(getInstalledVersion(), 1);
         do_check_eq(getActiveVersion(), 1);
 
         do_check_bootstrappedPref(do_test_finished);
       });
-    });
+    }));
    });
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug324121.js
@@ -133,17 +133,17 @@ function run_test() {
   testserver = new HttpServer();
   testserver.registerDirectory("/data/", dataDir);
   testserver.start(4444);
 
   startupManager();
 
   installAllFiles([do_get_addon(a.addon) for each (a in ADDONS)], function() {
     restartManager();
-    AddonManager.getAddonByID(ADDONS[0].id, function(addon) {
+    AddonManager.getAddonByID(ADDONS[0].id, callback_soon(function(addon) {
       do_check_true(!(!addon));
       addon.userDisabled = true;
       restartManager();
 
       AddonManager.getAddonsByTypes(["extension"], function(installedItems) {
         var items = [];
 
         for (let addon of ADDONS) {
@@ -163,16 +163,16 @@ function run_test() {
               updateListener.pendingCount++;
               installedItem.findUpdates(updateListener,
                                             AddonManager.UPDATE_WHEN_USER_REQUESTED,
                                             "3", "3");
             }
           }
         }
       });
-    });
+    }));
   });
 }
 
 function test_complete() {
   do_check_eq(gItemsNotChecked.length, 0);
   testserver.stop(do_test_finished);
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug335238.js
@@ -160,22 +160,22 @@ function run_test() {
 
   Services.prefs.setBoolPref(PREF_MATCH_OS_LOCALE, false);
   Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "en-US");
 
   startupManager();
   installAllFiles([do_get_addon(a.addon) for each (a in ADDONS)], function() {
 
     restartManager();
-    AddonManager.getAddonByID(ADDONS[1].id, function(addon) {
+    AddonManager.getAddonByID(ADDONS[1].id, callback_soon(function(addon) {
       do_check_true(!(!addon));
       addon.userDisabled = true;
       restartManager();
 
       AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(installedItems) {
         installedItems.forEach(function(item) {
           updateListener.pendingCount++;
           item.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED);
         });
       });
-    });
+    }));
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug371495.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug371495.js
@@ -23,13 +23,13 @@ function run_test()
       do_check_eq(addon.name, "Test theme");
       restartManager();
 
       AddonManager.getAddonByID(ID, function(addon) {
         do_check_neq(addon, null);
         do_check_eq(addon.optionsURL, null);
         do_check_eq(addon.aboutURL, null);
 
-        do_test_finished();
+        do_execute_soon(do_test_finished);
       });
     });
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug384052.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug384052.js
@@ -91,13 +91,13 @@ function run_test()
 
       onUpdateAvailable: function(addon, install) {
         do_throw("Should not have seen an available update");
       },
 
       onUpdateFinished: function(addon, error) {
         do_check_eq(error, AddonManager.UPDATE_STATUS_DOWNLOAD_ERROR);
         do_check_true(gSeenExpectedURL);
-        shutdownTest();
+        do_execute_soon(shutdownTest);
       }
     }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug397778.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug397778.js
@@ -22,96 +22,96 @@ function run_test()
   installAllFiles([do_get_addon(ADDON)], function() {
     restartManager();
 
     run_test_1();
   });
 }
 
 function run_test_1() {
-  AddonManager.getAddonByID(ID, function(addon) {
+  AddonManager.getAddonByID(ID, callback_soon(function(addon) {
     do_check_neq(addon, null);
     do_check_eq(addon.name, "fr Name");
     do_check_eq(addon.description, "fr Description");
 
     // Disable item
     addon.userDisabled = true;
     restartManager();
 
     AddonManager.getAddonByID(ID, function(newAddon) {
       do_check_neq(newAddon, null);
       do_check_eq(newAddon.name, "fr Name");
 
-      run_test_2();
+      do_execute_soon(run_test_2);
     });
-  });
+  }));
 }
 
 function run_test_2() {
   // Change locale. The more specific de-DE is the best match
   Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "de");
   restartManager();
 
   AddonManager.getAddonByID(ID, function(addon) {
     do_check_neq(addon, null);
     do_check_eq(addon.name, "de-DE Name");
     do_check_eq(addon.description, null);
 
-    run_test_3();
+    do_execute_soon(run_test_3);
   });
 }
 
 function run_test_3() {
   // Change locale. Locale case should have no effect
   Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "DE-de");
   restartManager();
 
   AddonManager.getAddonByID(ID, function(addon) {
     do_check_neq(addon, null);
     do_check_eq(addon.name, "de-DE Name");
     do_check_eq(addon.description, null);
 
-    run_test_4();
+    do_execute_soon(run_test_4);
   });
 }
 
 function run_test_4() {
   // Change locale. es-ES should closely match
   Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "es-AR");
   restartManager();
 
   AddonManager.getAddonByID(ID, function(addon) {
     do_check_neq(addon, null);
     do_check_eq(addon.name, "es-ES Name");
     do_check_eq(addon.description, "es-ES Description");
 
-    run_test_5();
+    do_execute_soon(run_test_5);
   });
 }
 
 function run_test_5() {
   // Change locale. Either zh-CN or zh-TW could match
   Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "zh");
   restartManager();
 
   AddonManager.getAddonByID(ID, function(addon) {
     do_check_neq(addon, null);
     if (addon.name != "zh-TW Name" && addon.name != "zh-CN Name")
       do_throw("zh matched to " + addon.name);
 
-    run_test_6();
+    do_execute_soon(run_test_6);
   });
 }
 
 function run_test_6() {
   // Unknown locale should try to match against en-US as well. Of en,en-GB
   // en should match as being less specific
   Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "nl-NL");
   restartManager();
 
   AddonManager.getAddonByID(ID, function(addon) {
     do_check_neq(addon, null);
     do_check_eq(addon.name, "en Name");
     do_check_eq(addon.description, "en Description");
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug425657.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug425657.js
@@ -16,12 +16,12 @@ function run_test()
   startupManager();
   installAllFiles([do_get_addon(ADDON)], function() {
     restartManager();
     AddonManager.getAddonByID(ID, function(addon) {
       do_check_neq(addon, null);
       do_check_eq(addon.name, "Deutsches W\u00f6rterbuch");
       do_check_eq(addon.name.length, 20);
 
-      do_test_finished();
+      do_execute_soon(do_test_finished);
     });
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug455906.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug455906.js
@@ -280,17 +280,17 @@ function check_initial_state(callback) {
     callback();
   });
 }
 
 // Tests the add-ons were installed and the initial blocklist applied as expected
 function check_test_pt1() {
   dump("Checking pt 1\n");
 
-  AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) {
+  AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], callback_soon(function(addons) {
     for (var i = 0; i < ADDONS.length; i++) {
       if (!addons[i])
         do_throw("Addon " + (i + 1) + " did not get installed correctly");
     }
   
     do_check_eq(check_addon_state(addons[0]), "false,false,false");
     do_check_eq(check_addon_state(addons[1]), "false,false,false");
     do_check_eq(check_addon_state(addons[2]), "false,false,false");
@@ -311,17 +311,17 @@ function check_test_pt1() {
     addons[4].userDisabled = false;
 
     restartManager();
     check_initial_state(function() {
       gNotificationCheck = check_notification_pt2;
       gTestCheck = check_test_pt2;
       load_blocklist("bug455906_warn.xml");
     });
-  });
+  }));
 }
 
 function check_notification_pt2(args) {
   dump("Checking notification pt 2\n");
   do_check_eq(args.list.length, 4);
 
   for (let addon of args.list) {
     if (addon.item instanceof Ci.nsIPluginTag) {
@@ -352,17 +352,17 @@ function check_notification_pt2(args) {
     }
   }
 }
 
 function check_test_pt2() {
   restartManager();
   dump("Checking results pt 2\n");
 
-  AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], function(addons) {
+  AddonManager.getAddonsByIDs([a.id for each (a in ADDONS)], callback_soon(function(addons) {
     // Should have disabled this add-on as requested
     do_check_eq(check_addon_state(addons[2]), "true,true,false");
     do_check_eq(check_plugin_state(PLUGINS[2]), "true,false");
 
     // The blocked add-on should have changed to soft disabled
     do_check_eq(check_addon_state(addons[5]), "true,true,false");
     do_check_eq(check_plugin_state(PLUGINS[5]), "true,false");
 
@@ -381,17 +381,17 @@ function check_test_pt2() {
     addons[2].userDisabled = false;
     addons[5].userDisabled = false;
     PLUGINS[2].enabledState = Ci.nsIPluginTag.STATE_ENABLED;
     PLUGINS[5].enabledState = Ci.nsIPluginTag.STATE_ENABLED;
     restartManager();
     gNotificationCheck = null;
     gTestCheck = run_test_pt3;
     load_blocklist("bug455906_start.xml");
-  });
+  }));
 }
 
 function run_test_pt3() {
   restartManager();
   check_initial_state(function() {
     gNotificationCheck = check_notification_pt3;
     gTestCheck = check_test_pt3;
     load_blocklist("bug455906_block.xml");
@@ -480,26 +480,26 @@ function check_test_pt3() {
     // Back to starting state
     gNotificationCheck = null;
     gTestCheck = run_test_pt4;
     load_blocklist("bug455906_start.xml");
   });
 }
 
 function run_test_pt4() {
-  AddonManager.getAddonByID(ADDONS[4].id, function(addon) {
+  AddonManager.getAddonByID(ADDONS[4].id, callback_soon(function(addon) {
     addon.userDisabled = false;
     PLUGINS[4].enabledState = Ci.nsIPluginTag.STATE_ENABLED;
     restartManager();
     check_initial_state(function() {
       gNotificationCheck = check_notification_pt4;
       gTestCheck = check_test_pt4;
       load_blocklist("bug455906_empty.xml");
     });
-  });
+  }));
 }
 
 function check_notification_pt4(args) {
   dump("Checking notification pt 4\n");
 
   // Should be just the dummy add-on to force this notification
   do_check_eq(args.list.length, 1);
   do_check_false(args.list[0].item instanceof Ci.nsIPluginTag);
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js
@@ -85,11 +85,11 @@ function run_test_2() {
     do_check_true(a2.isActive);
     do_check_neq(a3, null);
     do_check_true(a3.isActive);
     do_check_neq(a4, null);
     do_check_true(a4.isActive);
     do_check_neq(a5, null);
     do_check_true(a5.isActive);
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3_strictcompat.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3_strictcompat.js
@@ -84,11 +84,11 @@ function run_test_2() {
     do_check_true(a2.isActive);
     do_check_neq(a3, null);
     do_check_true(a3.isActive);
     do_check_neq(a4, null);
     do_check_true(a4.isActive);
     do_check_neq(a5, null);
     do_check_true(a5.isActive);
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_4.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_4.js
@@ -82,11 +82,11 @@ function run_test_2() {
     do_check_false(a2.isActive);
     do_check_neq(a3, null);
     do_check_false(a3.isActive);
     do_check_neq(a4, null);
     do_check_true(a4.isActive);
     do_check_neq(a5, null);
     do_check_true(a5.isActive);
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug521905.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug521905.js
@@ -49,11 +49,11 @@ function run_test_1() {
 function run_test_2() {
   Services.prefs.setBoolPref("extensions.checkCompatibility.2.0p", false);
 
   restartManager();
   AddonManager.getAddonByID(ID, function(addon) {
     do_check_neq(addon, null);
     do_check_false(addon.isActive);
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug526598.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug526598.js
@@ -11,17 +11,17 @@ function run_test() {
 
   installAllFiles([do_get_file("data/test_bug526598_1.xpi"),
                    do_get_file("data/test_bug526598_2.xpi")], function() {
 
     restartManager();
 
     AddonManager.getAddonsByIDs(["bug526598_1@tests.mozilla.org",
                                  "bug526598_2@tests.mozilla.org"],
-                                 function([a1, a2]) {
+                                 callback_soon(function([a1, a2]) {
 
       do_check_neq(a1, null);
       do_check_true(a1.hasResource("install.rdf"));
       let uri = a1.getResourceURI("install.rdf");
       do_check_true(uri instanceof AM_Ci.nsIFileURL);
       let file = uri.file;
       do_check_true(file.exists());
       do_check_true(file.isReadable());
@@ -42,13 +42,13 @@ function run_test() {
       restartManager();
 
       AddonManager.getAddonsByIDs(["bug526598_1@tests.mozilla.org",
                                    "bug526598_2@tests.mozilla.org"],
                                    function([newa1, newa2]) {
         do_check_eq(newa1, null);
         do_check_eq(newa2, null);
 
-        do_test_finished();
+        do_execute_soon(do_test_finished);
       });
-    });
+    }));
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug541420.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug541420.js
@@ -26,12 +26,12 @@ function run_test() {
 
       // We don't understand executable permissions on Windows since we don't
       // support NTFS permissions so we don't need to test there. OSX's isExecutable
       // only tests if the file is an application so it is better to just check the
       // raw permission bits
       if (!("nsIWindowsRegKey" in Components.interfaces))
         do_check_true((file.permissions & 0100) == 0100);
 
-      do_test_finished();
+      do_execute_soon(do_test_finished);
     });
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug542391.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug542391.js
@@ -327,34 +327,34 @@ function run_test() {
     check_startup_changes("installed", []);
     check_startup_changes("updated", []);
     check_startup_changes("uninstalled", ["addon1@tests.mozilla.org"]);
     check_startup_changes("disabled", []);
     check_startup_changes("enabled", []);
 
     AddonManager.getAddonsByIDs(["bug542391_2@tests.mozilla.org",
                                  "bug542391_4@tests.mozilla.org"],
-                                 function disable_and_restart([a2, a4]) {
+                                 callback_soon(function disable_and_restart([a2, a4]) {
       do_check_true(a2 != null && a4 != null);
       a2.userDisabled = true;
       a4.userDisabled = true;
       restartManager();
       check_startup_changes("installed", []);
       check_startup_changes("updated", []);
       check_startup_changes("uninstalled", []);
       check_startup_changes("disabled", []);
       check_startup_changes("enabled", []);
 
       AddonManager.getAddonsByIDs(["bug542391_1@tests.mozilla.org",
                                    "bug542391_2@tests.mozilla.org",
                                    "bug542391_3@tests.mozilla.org",
                                    "bug542391_4@tests.mozilla.org",
                                    "bug542391_5@tests.mozilla.org",
                                    "bug542391_6@tests.mozilla.org"],
-                                   function(addons) {
+                                   callback_soon(function(addons) {
         check_state_v1(addons);
 
         WindowWatcher.expected = true;
         restartManager("2");
         check_startup_changes("installed", []);
         check_startup_changes("updated", []);
         check_startup_changes("uninstalled", []);
         check_startup_changes("disabled", ["bug542391_1@tests.mozilla.org"]);
@@ -367,18 +367,18 @@ function run_test() {
                                      "bug542391_4@tests.mozilla.org",
                                      "bug542391_5@tests.mozilla.org",
                                      "bug542391_6@tests.mozilla.org"],
                                      function(addons) {
           check_state_v2(addons);
 
           do_execute_soon(run_test_1);
         });
-      });
-    });
+      }));
+    }));
   });
 }
 
 function end_test() {
   testserver.stop(do_test_finished);
 }
 
 // Upgrade to version 3 which will appDisable two more add-ons. Check that the
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug559800.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug559800.js
@@ -36,36 +36,36 @@ function run_test() {
   run_test_1();
 }
 
 function end_test() {
   gServer.stop(do_test_finished);
 }
 
 function run_test_1() {
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
     do_check_neq(a1, null);
     do_check_eq(a1.version, "1.0");
 
     shutdownManager();
 
     gExtensionsJSON.remove(true);
 
     do_execute_soon(check_test_1);
-  });
+  }));
 }
 
 function check_test_1() {
   startupManager(false);
 
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
     do_check_neq(a1, null);
     do_check_eq(a1.version, "1.0");
 
     // due to delayed write, the file may not exist until
     // after shutdown
     shutdownManager();
     do_check_true(gExtensionsJSON.exists());
     do_check_true(gExtensionsJSON.fileSize > 0);
 
     end_test();
-  });
+  }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug563256.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug563256.js
@@ -60,17 +60,17 @@ function run_test() {
     do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_DISABLE));
     do_check_true(hasFlag(a.permissions, AddonManager.PERM_CAN_ENABLE));
 
     run_test_1(d, a);
   });
 }
 
 function end_test() {
-  do_test_finished();
+  do_execute_soon(do_test_finished);
 }
 
 // Checks switching to a different theme and back again leaves everything the
 // same
 function run_test_1(d, a) {
   a.userDisabled = false;
 
   do_check_true(d.userDisabled);
@@ -191,17 +191,17 @@ function run_test_2() {
 
     do_execute_soon(check_test_2);
   });
 }
 
 function check_test_2() {
   restartManager();
   AddonManager.getAddonsByIDs(["default@tests.mozilla.org",
-                               "alternate@tests.mozilla.org"], function([d, a]) {
+                               "alternate@tests.mozilla.org"], callback_soon(function([d, a]) {
     do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "alternate/1.0");
 
     do_check_true(d.userDisabled);
     do_check_false(d.appDisabled);
     do_check_false(d.isActive);
     do_check_false(isThemeInAddonsList(profileDir, d.id));
     do_check_false(hasFlag(d.permissions, AddonManager.PERM_CAN_DISABLE));
     do_check_true(hasFlag(d.permissions, AddonManager.PERM_CAN_ENABLE));
@@ -250,10 +250,10 @@ function check_test_2() {
       do_check_false(a.appDisabled);
       do_check_false(a.isActive);
       do_check_false(isThemeInAddonsList(profileDir, a.id));
       do_check_false(hasFlag(a.permissions, AddonManager.PERM_CAN_DISABLE));
       do_check_true(hasFlag(a.permissions, AddonManager.PERM_CAN_ENABLE));
 
       end_test();
     });
-  });
+  }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug564030.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug564030.js
@@ -23,17 +23,17 @@ function run_test() {
     }]
   }, profileDir);
   // Attempt to make this look like it was added some time in the past so
   // the update makes the last modified time change.
   setExtensionModifiedTime(dest, dest.lastModifiedTime - 5000);
 
   startupManager();
 
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a) {
     do_check_neq(a, null);
     do_check_eq(a.version, "1.0");
     do_check_false(a.userDisabled);
     do_check_true(a.appDisabled);
     do_check_false(a.isActive);
     do_check_false(isExtensionInAddonsList(profileDir, a.id));
 
     writeInstallRDFForExtension({
@@ -52,12 +52,12 @@ function run_test() {
     AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a) {
       do_check_neq(a, null);
       do_check_eq(a.version, "2.0");
       do_check_false(a.userDisabled);
       do_check_false(a.appDisabled);
       do_check_true(a.isActive);
       do_check_true(isExtensionInAddonsList(profileDir, a.id));
 
-      do_test_finished();
+      do_execute_soon(do_test_finished);
     });
-  });
+  }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug566626.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug566626.js
@@ -101,12 +101,12 @@ function run_test_1() {
 // Verifies that a subsequent call gets the same add-on from the cache
 function run_test_2() {
   AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
     do_check_neq(a1, null);
     do_check_eq(a1.name, "Test 1");
 
     do_check_eq(a1, gAddon);
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug567184.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug567184.js
@@ -42,12 +42,12 @@ function check_test_1() {
     do_check_eq(installs.length, 0);
 
     AddonManager.getAddonByID("bug567184@tests.mozilla.org", function(b1) {
       do_check_neq(b1, null);
       do_check_true(b1.appDisabled);
       do_check_false(b1.userDisabled);
       do_check_false(b1.isActive);
 
-      do_test_finished();
+      do_execute_soon(do_test_finished);
     });
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug569138.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug569138.js
@@ -136,12 +136,12 @@ function run_test() {
     do_check_neq(a6, null);
     do_check_true(a6.appDisabled);
     do_check_false(a6.isActive);
 
     do_check_neq(a6, null);
     do_check_true(a6.appDisabled);
     do_check_false(a6.isActive);
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
 
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug576735.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug576735.js
@@ -33,17 +33,17 @@ profileDir.append("extensions");
 function run_test() {
   do_test_pending();
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "2");
 
   writeInstallRDFForExtension(addon1, profileDir);
 
   startupManager();
 
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
     a1.uninstall();
 
     shutdownManager();
 
     var dest = profileDir.clone();
     dest.append(do_get_expected_addon_name("addon1@tests.mozilla.org"));
     dest.remove(true);
 
@@ -55,12 +55,12 @@ function run_test() {
                                  "addon2@tests.mozilla.org"],
                                 function([a1, a2]) {
       // Addon1 should no longer be installed
       do_check_eq(a1, null);
 
       // Addon2 should have been detected
       do_check_neq(a2, null);
 
-      do_test_finished();
+      do_execute_soon(do_test_finished);
     });
-  });
+  }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug587088.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug587088.js
@@ -91,49 +91,49 @@ function run_test_1() {
       fstream.init(uri.QueryInterface(AM_Ci.nsIFileURL).file, -1, 0, 0);
 
       installAllFiles([do_get_addon("test_bug587088_2")], function() {
 
         check_addon_upgrading(a1);
 
         restartManager();
 
-        AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+        AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
           check_addon_upgrading(a1);
 
           restartManager();
 
-          AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+          AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
             check_addon_upgrading(a1);
 
             fstream.close();
 
             restartManager();
 
             AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
               check_addon(a1, "2.0");
 
               a1.uninstall();
               do_execute_soon(run_test_2);
             });
-          });
-        });
+          }));
+        }));
       });
     });
   });
 }
 
 // Test that a failed uninstall gets rolled back
 function run_test_2() {
   restartManager();
 
   installAllFiles([do_get_addon("test_bug587088_1")], function() {
     restartManager();
 
-    AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+    AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
       check_addon(a1, "1.0");
 
       // Lock either install.rdf for unpacked add-ons or the xpi for packed add-ons.
       let uri = a1.getResourceURI("install.rdf");
       if (uri.schemeIs("jar"))
         uri = a1.getResourceURI();
 
       let fstream = AM_Cc["@mozilla.org/network/file-input-stream;1"].
@@ -141,34 +141,34 @@ function run_test_2() {
       fstream.init(uri.QueryInterface(AM_Ci.nsIFileURL).file, -1, 0, 0);
 
       a1.uninstall();
 
       check_addon_uninstalling(a1);
 
       restartManager();
 
-      AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+      AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
         check_addon_uninstalling(a1, true);
 
         restartManager();
 
-        AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+        AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
           check_addon_uninstalling(a1, true);
 
           fstream.close();
 
           restartManager();
 
           AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
             do_check_eq(a1, null);
             var dir = profileDir.clone();
             dir.append(do_get_expected_addon_name("addon1@tests.mozilla.org"));
             do_check_false(dir.exists());
             do_check_false(isExtensionInAddonsList(profileDir, "addon1@tests.mozilla.org"));
 
-            do_test_finished();
+            do_execute_soon(do_test_finished);
           });
-        });
-      });
-    });
+        }));
+      }));
+    }));
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug595573.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug595573.js
@@ -30,11 +30,11 @@ function run_test_1() {
 
 function run_test_2() {
   restartManager();
 
   AddonManager.getAddonByID("{2f69dacd-03df-4150-a9f1-e8a7b2748829}", function(a1) {
     do_check_neq(a1, null);
     do_check_true(isExtensionInAddonsList(profileDir, a1.id));
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug596607.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug596607.js
@@ -130,11 +130,11 @@ function run_test_3() {
 
     do_check_neq(a2, null);
     do_check_true(a2.isActive);
     do_check_false(hasFlag(a2.permissions, AddonManager.PERM_CAN_UNINSTALL));
     do_check_eq(a2.scope, AddonManager.SCOPE_USER);
 
     do_check_eq(a3, null);
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug616841.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug616841.js
@@ -16,11 +16,11 @@ function run_test() {
   startupManager();
 
   do_test_pending();
 
   test_string_compare();
 
   AddonManager.getAddonByID("foo", function(aAddon) {
     test_string_compare();
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug655254.js
@@ -79,17 +79,17 @@ function run_test_1() {
     do_check_true(a2.isActive);
     do_check_false(isExtensionInAddonsList(userDir, a2.id));
     do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 1);
 
     a1.findUpdates({
       onUpdateFinished: function() {
         restartManager();
 
-        AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+        AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
           do_check_neq(a1, null);
           do_check_false(a1.appDisabled);
           do_check_true(a1.isActive);
           do_check_true(isExtensionInAddonsList(userDir, a1.id));
 
           shutdownManager();
 
           do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 0);
@@ -110,27 +110,27 @@ function run_test_1() {
             do_check_true(isExtensionInAddonsList(userDir, a1.id));
 
             do_check_neq(a2, null);
             do_check_false(a2.appDisabled);
             do_check_true(a2.isActive);
             do_check_false(isExtensionInAddonsList(userDir, a2.id));
             do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 1);
 
-            run_test_2();
+            do_execute_soon(run_test_2);
           });
-        });
+        }));
       }
     }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
   });
 }
 
 //Set up the profile
 function run_test_2() {
-  AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
+  AddonManager.getAddonByID("addon2@tests.mozilla.org", callback_soon(function(a2) {
    do_check_neq(a2, null);
    do_check_false(a2.appDisabled);
    do_check_true(a2.isActive);
    do_check_false(isExtensionInAddonsList(userDir, a2.id));
    do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 1);
 
    a2.userDisabled = true;
    do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 0);
@@ -155,10 +155,10 @@ function run_test_2() {
      do_check_neq(a2, null);
      do_check_true(a2.userDisabled);
      do_check_false(a2.isActive);
      do_check_false(isExtensionInAddonsList(userDir, a2.id));
      do_check_eq(Services.prefs.getIntPref("bootstraptest.active_version"), 0);
 
      end_test();
    });
-  });
+  }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug659772.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug659772.js
@@ -285,17 +285,17 @@ function run_test_2() {
 
       gAppInfo.version = "2";
       startupManager(true);
 
       AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                    "addon2@tests.mozilla.org",
                                    "addon3@tests.mozilla.org",
                                    "addon4@tests.mozilla.org"],
-                                  function([a1, a2, a3, a4]) {
+                                  callback_soon(function([a1, a2, a3, a4]) {
         do_check_neq(a1, null);
         do_check_eq(a1.version, "2.0");
         do_check_true(a1.appDisabled);
         do_check_false(a1.userDisabled);
         do_check_false(a1.isActive);
         do_check_false(isExtensionInAddonsList(profileDir, addon1.id));
 
         do_check_neq(a2, null);
@@ -329,12 +329,12 @@ function run_test_2() {
         a2.uninstall();
         a3.uninstall();
         a4.uninstall();
         restartManager();
 
         shutdownManager();
 
         do_test_finished();
-      });
+      }));
     };
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug675371.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug675371.js
@@ -19,19 +19,17 @@ function run_test() {
     prepare_test({
       "bug675371@tests.mozilla.org": [
         ["onInstalling", false],
         "onInstalled"
       ]
     }, [
       "onInstallStarted",
       "onInstallEnded",
-    ], function() {
-      do_execute_soon(check_test)
-    });
+    ], callback_soon(check_test));
     install.install();
   });
 }
 
 function check_test() {
   AddonManager.getAddonByID("bug675371@tests.mozilla.org", do_exception_wrap(function(addon) {
     do_check_neq(addon, null);
     do_check_true(addon.isActive);
@@ -83,11 +81,11 @@ function check_test() {
     target.active = false;
     try {
       Services.scriptloader.loadSubScript("chrome://bug675371/content/test.js", target);
       do_throw("Chrome file should not have been found");
     } catch (e) {
       do_check_false(target.active);
     }
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug740612.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug740612.js
@@ -30,11 +30,11 @@ function run_test() {
   AddonManager.getAddonsByIDs(["bug740612_1@tests.mozilla.org",
                                "bug740612_2@tests.mozilla.org"],
                                function([a1, a2]) {
     do_check_neq(a1, null);
     do_check_neq(a2, null);
     do_check_eq(getInstalledVersion(), "1.0");
     do_check_eq(getActiveVersion(), "1.0");
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug753900.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug753900.js
@@ -76,11 +76,11 @@ function run_test() {
     do_check_in_crash_annotation(addon1.id, addon1.version);
     do_check_neq(a2, null);
     do_check_in_crash_annotation(addon2.id, addon2.version);
     do_check_neq(a3, null);
     do_check_in_crash_annotation(addon3.id, addon3.version);
     do_check_neq(a4, null);
     do_check_in_crash_annotation(addon4.id, addon4.version);
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug757663.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug757663.js
@@ -102,11 +102,11 @@ function run_test_2() {
     listener2.sawEvent = false;
     do_check_true(listener3.sawEvent);
     listener3.sawEvent = false;
 
     AddonManager.removeInstallListener(listener1);
     AddonManager.removeInstallListener(listener2);
     AddonManager.removeInstallListener(listener3);
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_cacheflush.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_cacheflush.js
@@ -112,11 +112,11 @@ function run_test_4() {
     gExpectedFile = gProfD.clone();
     gExpectedFile.append("extensions");
     gExpectedFile.append("addon2@tests.mozilla.org.xpi");
 
     a2.uninstall();
     do_check_true(gCacheFlushed);
     gCacheFlushed = false;
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_checkcompatibility.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_checkcompatibility.js
@@ -186,11 +186,11 @@ function run_test_4() {
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                "addon2@tests.mozilla.org",
                                "addon3@tests.mozilla.org",
                                "addon4@tests.mozilla.org",
                                "addon5@tests.mozilla.org"],
                                function([a1, a2, a3, a4, a5]) {
     check_state(false, a1, a2, a3, a4, a5);
 
-    do_test_finished("checkcompatibility.js");
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_dictionary.js
@@ -144,17 +144,17 @@ function run_test_1() {
     }, [
       "onInstallStarted",
       "onInstallEnded",
     ], function() {
       do_check_true(addon.hasResource("install.rdf"));
       HunspellEngine.listener = function(aEvent) {
         HunspellEngine.listener = null;
         do_check_eq(aEvent, "addDirectory");
-        check_test_1();
+        do_execute_soon(check_test_1);
       };
     });
     install.install();
   });
 }
 
 function check_test_1() {
   AddonManager.getAllInstalls(function(installs) {
@@ -312,27 +312,28 @@ function run_test_7() {
   });
 }
 
 function check_test_7() {
   ensure_test_completed();
   do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic"));
   do_check_not_in_crash_annotation("ab-CD@dictionaries.addons.mozilla.org", "1.0");
 
-  AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) {
+  AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org",
+   callback_soon(function(b1) {
     do_check_eq(b1, null);
 
     restartManager();
 
     AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(newb1) {
       do_check_eq(newb1, null);
 
       do_execute_soon(run_test_8);
     });
-  });
+  }));
 }
 
 // Test that a bootstrapped extension dropped into the profile loads properly
 // on startup and doesn't cause an EM restart
 function run_test_8() {
   shutdownManager();
 
   let dir = profileDir.clone();
@@ -422,47 +423,49 @@ function run_test_12() {
 
 // Tests that bootstrapped extensions don't get loaded when in safe mode
 function run_test_16() {
   restartManager();
 
   installAllFiles([do_get_addon("test_dictionary")], function() {
     // spin the event loop to let the addon finish starting
    do_execute_soon(function check_installed_dictionary() {
-    AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) {
+    AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org",
+     callback_soon(function(b1) {
       // Should have installed and started
       do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic"));
 
       shutdownManager();
 
       // Should have stopped
       do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic"));
 
       gAppInfo.inSafeMode = true;
       startupManager(false);
 
-      AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) {
+      AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org",
+       callback_soon(function(b1) {
         // Should still be stopped
         do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic"));
         do_check_false(b1.isActive);
 
         shutdownManager();
         gAppInfo.inSafeMode = false;
         startupManager(false);
 
         // Should have started
         do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic"));
 
         AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) {
           b1.uninstall();
 
           do_execute_soon(run_test_17);
         });
-      });
-    });
+      }));
+    }));
    });
   });
 }
 
 // Check that a bootstrapped extension in a non-profile location is loaded
 function run_test_17() {
   shutdownManager();
 
@@ -478,32 +481,33 @@ function run_test_17() {
   dir.append("dictionaries");
   dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755);
   dir.append("ab-CD.dic");
   zip.extract("dictionaries/ab-CD.dic", dir);
   zip.close();
 
   startupManager();
 
-  AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) {
+  AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org",
+   callback_soon(function(b1) {
     // Should have installed and started
     do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic"));
     do_check_neq(b1, null);
     do_check_eq(b1.version, "1.0");
     do_check_true(b1.isActive);
 
     // From run_test_21
     dir = userExtDir.clone();
     dir.append("ab-CD@dictionaries.addons.mozilla.org");
     dir.remove(true);
 
     restartManager();
 
     run_test_23();
-  });
+  }));
 }
 
 // Tests that installing from a URL doesn't require a restart
 function run_test_23() {
   prepare_test({ }, [
     "onNewInstall"
   ]);
 
@@ -560,25 +564,25 @@ function check_test_23() {
       do_check_true(b1.isActive);
       do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic"));
       do_check_true(b1.hasResource("install.rdf"));
       do_check_false(b1.hasResource("bootstrap.js"));
       do_check_in_crash_annotation("ab-CD@dictionaries.addons.mozilla.org", "1.0");
 
       let dir = do_get_addon_root_uri(profileDir, "ab-CD@dictionaries.addons.mozilla.org");
 
-      AddonManager.getAddonsWithOperationsByTypes(null, function(list) {
+      AddonManager.getAddonsWithOperationsByTypes(null, callback_soon(function(list) {
         do_check_eq(list.length, 0);
 
         restartManager();
         AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) {
           b1.uninstall();
           do_execute_soon(run_test_25);
         });
-      });
+      }));
     });
   });
 }
 
 // Tests that updating from a bootstrappable add-on to a normal add-on calls
 // the uninstall method
 function run_test_25() {
   restartManager();
@@ -587,17 +591,18 @@ function run_test_25() {
     HunspellEngine.listener = null;
     do_check_eq(aEvent, "addDirectory");
     do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic"));
 
     installAllFiles([do_get_addon("test_dictionary_2")], function test_25_installed2() {
       // Needs a restart to complete this so the old version stays running
       do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic"));
 
-      AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) {
+      AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org",
+       callback_soon(function(b1) {
         do_check_neq(b1, null);
         do_check_eq(b1.version, "1.0");
         do_check_true(b1.isActive);
         do_check_true(hasFlag(b1.pendingOperations, AddonManager.PENDING_UPGRADE));
 
         restartManager();
 
         do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic"));
@@ -605,31 +610,32 @@ function run_test_25() {
         AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) {
           do_check_neq(b1, null);
           do_check_eq(b1.version, "2.0");
           do_check_true(b1.isActive);
           do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
 
           do_execute_soon(run_test_26);
         });
-      });
+      }));
     });
   };
 
   installAllFiles([do_get_addon("test_dictionary")], function test_25_installed() { });
 }
 
 // Tests that updating from a normal add-on to a bootstrappable add-on calls
 // the install method
 function run_test_26() {
   installAllFiles([do_get_addon("test_dictionary")], function test_26_install() {
     // Needs a restart to complete this
     do_check_false(HunspellEngine.isDictionaryEnabled("ab-CD.dic"));
 
-    AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org", function(b1) {
+    AddonManager.getAddonByID("ab-CD@dictionaries.addons.mozilla.org",
+     callback_soon(function(b1) {
       do_check_neq(b1, null);
       do_check_eq(b1.version, "2.0");
       do_check_true(b1.isActive);
       do_check_true(hasFlag(b1.pendingOperations, AddonManager.PENDING_UPGRADE));
 
       restartManager();
 
       do_check_true(HunspellEngine.isDictionaryEnabled("ab-CD.dic"));
@@ -639,17 +645,17 @@ function run_test_26() {
         do_check_eq(b1.version, "1.0");
         do_check_true(b1.isActive);
         do_check_eq(b1.pendingOperations, AddonManager.PENDING_NONE);
 
         HunspellEngine.deactivate();
         b1.uninstall();
         do_execute_soon(run_test_27);
       });
-    });
+    }));
   });
 }
 
 // Tests that an update check from a normal add-on to a bootstrappable add-on works
 function run_test_27() {
   restartManager();
   writeInstallRDFForExtension({
     id: "ab-CD@dictionaries.addons.mozilla.org",
@@ -669,17 +675,17 @@ function run_test_27() {
       "onInstalling"
     ]
   }, [
     "onNewInstall",
     "onDownloadStarted",
     "onDownloadEnded",
     "onInstallStarted",
     "onInstallEnded"
-  ], check_test_27);
+  ], callback_soon(check_test_27));
 
   AddonManagerPrivate.backgroundUpdateCheck();
 }
 
 function check_test_27(install) {
   do_check_eq(install.existingAddon.pendingUpgrade.install, install);
 
   restartManager();
@@ -715,17 +721,17 @@ function run_test_28() {
       "onInstalling"
     ]
   }, [
     "onNewInstall",
     "onDownloadStarted",
     "onDownloadEnded",
     "onInstallStarted",
     "onInstallEnded"
-  ], check_test_28);
+  ], callback_soon(check_test_28));
 
   AddonManagerPrivate.backgroundUpdateCheck();
 }
 
 function check_test_28(install) {
   do_check_eq(install.existingAddon.pendingUpgrade.install, install);
 
   restartManager();
@@ -779,17 +785,17 @@ function check_test_29(install) {
     do_check_eq(b2.type, "dictionary");
 
     prepare_test({
       "gh@dictionaries.addons.mozilla.org": [
         ["onUninstalling", false],
         ["onUninstalled", false],
       ]
     }, [
-    ], finish_test_29);
+    ], callback_soon(finish_test_29));
 
     b2.uninstall();
   });
 }
 
 function finish_test_29() {
   testserver.stop(do_test_finished);
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_disable.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_disable.js
@@ -27,17 +27,17 @@ var gIconURL = null;
 
 // Sets up the profile by installing an add-on.
 function run_test() {
   do_test_pending();
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
 
   startupManager();
 
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
     do_check_eq(a1, null);
     do_check_not_in_crash_annotation(addon1.id, addon1.version);
 
     writeInstallRDFForExtension(addon1, profileDir, addon1.id, "icon.png");
     gIconURL = do_get_addon_root_uri(profileDir.clone(), addon1.id) + "icon.png";
 
     restartManager();
 
@@ -52,17 +52,17 @@ function run_test() {
       do_check_true(hasFlag(newa1.permissions, AddonManager.PERM_CAN_DISABLE));
       do_check_false(hasFlag(newa1.permissions, AddonManager.PERM_CAN_ENABLE));
       do_check_eq(newa1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_DISABLE |
                                                     AddonManager.OP_NEEDS_RESTART_UNINSTALL);
       do_check_in_crash_annotation(addon1.id, addon1.version);
 
       run_test_1();
     });
-  });
+  }));
 }
 
 // Disabling an add-on should work
 function run_test_1() {
   prepare_test({
     "addon1@tests.mozilla.org": [
       "onDisabling"
     ]
@@ -78,17 +78,17 @@ function run_test_1() {
     do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_DISABLE));
     do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_ENABLE));
     do_check_eq(a1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_DISABLE |
                                                AddonManager.OP_NEEDS_RESTART_UNINSTALL);
     do_check_in_crash_annotation(addon1.id, addon1.version);
 
     ensure_test_completed();
 
-    AddonManager.getAddonsWithOperationsByTypes(null, function(list) {
+    AddonManager.getAddonsWithOperationsByTypes(null, callback_soon(function(list) {
       do_check_eq(list.length, 1);
       do_check_eq(list[0].id, "addon1@tests.mozilla.org");
 
       restartManager();
 
       AddonManager.getAddonByID("addon1@tests.mozilla.org", function(newa1) {
         do_check_neq(newa1, null);
         do_check_false(newa1.isActive);
@@ -99,17 +99,17 @@ function run_test_1() {
         do_check_false(isExtensionInAddonsList(profileDir, newa1.id));
         do_check_false(hasFlag(newa1.permissions, AddonManager.PERM_CAN_DISABLE));
         do_check_true(hasFlag(newa1.permissions, AddonManager.PERM_CAN_ENABLE));
         do_check_eq(newa1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_ENABLE);
         do_check_not_in_crash_annotation(addon1.id, addon1.version);
 
         run_test_2();
       });
-    });
+    }));
   });
 }
 
 // Enabling an add-on should work.
 function run_test_2() {
   prepare_test({
     "addon1@tests.mozilla.org": [
       "onEnabling"
@@ -122,17 +122,17 @@ function run_test_2() {
     do_check_eq(a1.optionsURL, null);
     do_check_eq(a1.iconURL, gIconURL);
     do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_DISABLE));
     do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_ENABLE));
     do_check_eq(a1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_ENABLE);
 
     ensure_test_completed();
 
-    AddonManager.getAddonsWithOperationsByTypes(null, function(list) {
+    AddonManager.getAddonsWithOperationsByTypes(null, callback_soon(function(list) {
       do_check_eq(list.length, 1);
       do_check_eq(list[0].id, "addon1@tests.mozilla.org");
 
       restartManager();
 
       AddonManager.getAddonByID("addon1@tests.mozilla.org", function(newa1) {
         do_check_neq(newa1, null);
         do_check_true(newa1.isActive);
@@ -144,29 +144,29 @@ function run_test_2() {
         do_check_true(hasFlag(newa1.permissions, AddonManager.PERM_CAN_DISABLE));
         do_check_false(hasFlag(newa1.permissions, AddonManager.PERM_CAN_ENABLE));
         do_check_eq(newa1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_DISABLE |
                                                       AddonManager.OP_NEEDS_RESTART_UNINSTALL);
         do_check_in_crash_annotation(addon1.id, addon1.version);
 
         run_test_3();
       });
-    });
+    }));
   });
 }
 
 // Disabling then enabling without restart should fire onOperationCancelled.
 function run_test_3() {
   prepare_test({
     "addon1@tests.mozilla.org": [
       "onDisabling"
     ]
   });
 
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
     a1.userDisabled = true;
     ensure_test_completed();
     prepare_test({
       "addon1@tests.mozilla.org": [
         "onOperationCancelled"
       ]
     });
     a1.userDisabled = false;
@@ -183,12 +183,12 @@ function run_test_3() {
       do_check_false(newa1.userDisabled);
       do_check_eq(newa1.aboutURL, "chrome://foo/content/about.xul");
       do_check_eq(newa1.optionsURL, "chrome://foo/content/options.xul");
       do_check_eq(newa1.iconURL, "chrome://foo/content/icon.png");
       do_check_true(isExtensionInAddonsList(profileDir, newa1.id));
       do_check_true(hasFlag(newa1.permissions, AddonManager.PERM_CAN_DISABLE));
       do_check_false(hasFlag(newa1.permissions, AddonManager.PERM_CAN_ENABLE));
 
-      do_test_finished();
+      do_execute_soon(do_test_finished);
     });
-  });
+  }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_distribution.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_distribution.js
@@ -144,27 +144,27 @@ function run_test_4() {
     do_check_eq(a1.scope, AddonManager.SCOPE_PROFILE);
 
     do_execute_soon(run_test_5);
   });
 }
 
 // Tests that after uninstalling a restart doesn't re-install the extension
 function run_test_5() {
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
     a1.uninstall();
 
     restartManager();
 
     AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
       do_check_eq(a1, null);
 
       do_execute_soon(run_test_6);
     });
-  });
+  }));
 }
 
 // Tests that upgrading the application still doesn't re-install the uninstalled
 // extension
 function run_test_6() {
   restartManager("4");
 
   AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
@@ -252,11 +252,11 @@ function run_test_9() {
     do_check_true(addonDir.exists());
     do_check_true(addonDir.isDirectory());
     addonDir.append("dummy2.txt");
     do_check_true(addonDir.exists());
     do_check_true(addonDir.isFile());
 
     a2.uninstall();
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_dss.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_dss.js
@@ -110,17 +110,17 @@ function run_test() {
     do_check_false(hasFlag(t2.permissions, AddonManager.PERM_CAN_DISABLE));
     do_check_true(hasFlag(t2.permissions, AddonManager.PERM_CAN_ENABLE));
 
     do_execute_soon(run_test_1);
   });
 }
 
 function end_test() {
-  do_test_finished();
+  do_execute_soon(do_test_finished);
 }
 
 // Checks enabling one theme disables the others
 function run_test_1() {
   prepare_test({
     "theme1@tests.mozilla.org": [
       ["onDisabling", false],
       "onDisabled"
@@ -587,17 +587,17 @@ function run_test_9() {
 
       do_execute_soon(run_test_10);
     });
   });
 }
 
 // Uninstalling a custom theme in use should require a restart
 function run_test_10() {
-  AddonManager.getAddonByID("theme2@tests.mozilla.org", function(oldt2) {
+  AddonManager.getAddonByID("theme2@tests.mozilla.org", callback_soon(function(oldt2) {
     prepare_test({
       "theme2@tests.mozilla.org": [
         ["onEnabling", false],
         "onEnabled"
       ],
       "default@tests.mozilla.org": [
         ["onDisabling", false],
         "onDisabled"
@@ -606,17 +606,18 @@ function run_test_10() {
 
     oldt2.userDisabled = false;
 
     ensure_test_completed();
 
     restartManager();
 
     AddonManager.getAddonsByIDs(["default@tests.mozilla.org",
-                                 "theme2@tests.mozilla.org"], function([d, t2]) {
+                                 "theme2@tests.mozilla.org"],
+                                 callback_soon(function([d, t2]) {
       do_check_true(t2.isActive);
       do_check_false(t2.userDisabled);
       do_check_false(t2.appDisabled);
       do_check_false(d.isActive);
       do_check_true(d.userDisabled);
       do_check_false(d.appDisabled);
 
       prepare_test({
@@ -633,18 +634,18 @@ function run_test_10() {
       t2.uninstall();
 
       ensure_test_completed();
       do_check_false(gLWThemeChanged);
 
       restartManager();
 
       do_execute_soon(run_test_11);
-    });
-  });
+    }));
+  }));
 }
 
 // Installing a custom theme not in use should not require a restart
 function run_test_11() {
   prepare_test({ }, [
     "onNewInstall"
   ]);
 
@@ -660,17 +661,17 @@ function run_test_11() {
     prepare_test({
       "theme1@tests.mozilla.org": [
         ["onInstalling", false],
         "onInstalled"
       ]
     }, [
       "onInstallStarted",
       "onInstallEnded",
-    ], check_test_11);
+    ], callback_soon(check_test_11));
     install.install();
   });
 }
 
 function check_test_11() {
   restartManager();
   AddonManager.getAddonByID("theme1@tests.mozilla.org", function(t1) {
     do_check_neq(t1, null);
@@ -717,17 +718,17 @@ function check_test_12() {
     do_check_false(gLWThemeChanged);
 
     do_execute_soon(run_test_13);
   });
 }
 
 // Updating a custom theme in use should require a restart
 function run_test_13() {
-  AddonManager.getAddonByID("theme1@tests.mozilla.org", function(t1) {
+  AddonManager.getAddonByID("theme1@tests.mozilla.org", callback_soon(function(t1) {
     prepare_test({
       "theme1@tests.mozilla.org": [
         ["onEnabling", false],
         "onEnabled"
       ],
       "default@tests.mozilla.org": [
         ["onDisabling", false],
         "onDisabled"
@@ -753,39 +754,39 @@ function run_test_13() {
 
       prepare_test({
         "theme1@tests.mozilla.org": [
           "onInstalling",
         ]
       }, [
         "onInstallStarted",
         "onInstallEnded",
-      ], check_test_13);
+      ], callback_soon(check_test_13));
       install.install();
     });
-  });
+  }));
 }
 
 function check_test_13() {
   restartManager();
 
   AddonManager.getAddonByID("theme1@tests.mozilla.org", function(t1) {
     do_check_neq(t1, null);
     do_check_true(t1.isActive);
     do_check_false(gLWThemeChanged);
     t1.uninstall();
-    restartManager();
 
     do_execute_soon(run_test_14);
   });
 }
 
 // Switching from a lightweight theme to the default theme should not require
 // a restart
 function run_test_14() {
+  restartManager();
   LightweightThemeManager.currentTheme = {
     id: "1",
     version: "1",
     name: "Test LW Theme",
     description: "A test theme",
     author: "Mozilla",
     homepageURL: "http://localhost:" + gPort + "/data/index.html",
     headerURL: "http://localhost:" + gPort + "/data/header.png",
--- a/toolkit/mozapps/extensions/test/xpcshell/test_duplicateplugins.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_duplicateplugins.js
@@ -159,26 +159,26 @@ function run_test_2() {
     do_execute_soon(run_test_3);
   });
 }
 
 // Test that IDs persist across restart
 function run_test_3() {
   restartManager();
 
-  AddonManager.getAddonByID(gPluginIDs[0], function(p) {
+  AddonManager.getAddonByID(gPluginIDs[0], callback_soon(function(p) {
     do_check_neq(p, null);
     do_check_eq(p.name, "Duplicate Plugin 1");
     do_check_eq(p.description, "A duplicate plugin");
 
     // Reorder the plugins and restart again
     [PLUGINS[0], PLUGINS[1]] = [PLUGINS[1], PLUGINS[0]];
     restartManager();
 
     AddonManager.getAddonByID(gPluginIDs[0], function(p) {
       do_check_neq(p, null);
       do_check_eq(p.name, "Duplicate Plugin 1");
       do_check_eq(p.description, "A duplicate plugin");
 
-      do_test_finished();
+      do_execute_soon(do_test_finished);
     });
-  });
+  }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_error.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_error.js
@@ -80,11 +80,11 @@ function run_test_4() {
 
 // Checks that an add-on with an illegal ID shows an error
 function run_test_5() {
   AddonManager.getInstallForFile(do_get_addon("test_bug567173"), function(install) {
     do_check_neq(install, null);
     do_check_eq(install.state, AddonManager.STATE_DOWNLOAD_FAILED);
     do_check_eq(install.error, AddonManager.ERROR_CORRUPT_FILE);
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_filepointer.js
@@ -145,17 +145,17 @@ function run_test_2() {
       "addon1@tests.mozilla.org": [
         "onInstalling"
       ]
     }, [
       "onDownloadStarted",
       "onDownloadEnded",
       "onInstallStarted",
       "onInstallEnded"
-    ], check_test_2);
+    ], callback_soon(check_test_2));
 
     install.install();
   }, "application/x-xpinstall");
 }
 
 function check_test_2() {
   restartManager();
 
@@ -185,30 +185,30 @@ function check_test_2() {
 // Tests that uninstalling doesn't clobber the original sources
 function run_test_3() {
   restartManager();
 
   writePointer(addon1.id);
 
   restartManager();
 
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
     do_check_neq(a1, null);
     do_check_eq(a1.version, "1.0");
 
     a1.uninstall();
 
     restartManager();
 
     let source = sourceDir.clone();
     source.append(addon1.id);
     do_check_true(source.exists());
 
     do_execute_soon(run_test_4);
-  });
+  }));
 }
 
 // Tests that misnaming a pointer doesn't clobber the sources
 function run_test_4() {
   writePointer("addon2@tests.mozilla.org", addon1.id);
 
   restartManager();
 
@@ -233,17 +233,17 @@ function run_test_4() {
 function run_test_5() {
   var dest = writeInstallRDFForExtension(addon1, sourceDir);
   // Make sure the modification time changes enough to be detected.
   setExtensionModifiedTime(dest, dest.lastModifiedTime - 5000);
   writePointer(addon1.id);
 
   restartManager();
 
-  AddonManager.getAddonByID(addon1.id, function(a1) {
+  AddonManager.getAddonByID(addon1.id, callback_soon(function(a1) {
     do_check_neq(a1, null);
     do_check_eq(a1.version, "1.0");
 
     writeInstallRDFForExtension(addon2, sourceDir, addon1.id);
 
     restartManager();
 
     AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
@@ -256,53 +256,53 @@ function run_test_5() {
       do_check_true(source.exists());
 
       let pointer = profileDir.clone();
       pointer.append(addon1.id);
       do_check_false(pointer.exists());
 
       do_execute_soon(run_test_6);
     });
-  });
+  }));
 }
 
 // Removing the pointer file should uninstall the add-on
 function run_test_6() {
   var dest = writeInstallRDFForExtension(addon1, sourceDir);
   // Make sure the modification time changes enough to be detected in run_test_8.
   setExtensionModifiedTime(dest, dest.lastModifiedTime - 5000);
   writePointer(addon1.id);
 
   restartManager();
 
-  AddonManager.getAddonByID(addon1.id, function(a1) {
+  AddonManager.getAddonByID(addon1.id, callback_soon(function(a1) {
     do_check_neq(a1, null);
     do_check_eq(a1.version, "1.0");
 
     let pointer = profileDir.clone();
     pointer.append(addon1.id);
     pointer.remove(false);
 
     restartManager();
 
     AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
       do_check_eq(a1, null);
 
       do_execute_soon(run_test_7);
     });
-  });
+  }));
 }
 
 // Removing the pointer file and replacing it with a directory should work
 function run_test_7() {
   writePointer(addon1.id);
 
   restartManager();
 
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
     do_check_neq(a1, null);
     do_check_eq(a1.version, "1.0");
 
     let pointer = profileDir.clone();
     pointer.append(addon1.id);
     pointer.remove(false);
 
     writeInstallRDFForExtension(addon1_2, profileDir);
@@ -310,75 +310,75 @@ function run_test_7() {
     restartManager();
 
     AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
       do_check_neq(a1, null);
       do_check_eq(a1.version, "2.0");
 
       a1.uninstall();
 
-      restartManager();
-
       do_execute_soon(run_test_8);
     });
-  });
+  }));
 }
 
 // Changes to the source files should be detected
 function run_test_8() {
+  restartManager();
+
   writePointer(addon1.id);
 
   restartManager();
 
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
     do_check_neq(a1, null);
     do_check_eq(a1.version, "1.0");
 
     writeInstallRDFForExtension(addon1_2, sourceDir);
 
     restartManager();
 
     AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
       do_check_neq(a1, null);
       do_check_eq(a1.version, "2.0");
 
       a1.uninstall();
 
-      restartManager();
-
       do_execute_soon(run_test_9);
     });
-  });
+  }));
 }
 
 // Removing the add-on the pointer file points at should uninstall the add-on
 function run_test_9() {
+  restartManager();
+
   var dest = writeInstallRDFForExtension(addon1, sourceDir);
   writePointer(addon1.id);
 
   restartManager();
 
-  AddonManager.getAddonByID(addon1.id, function(a1) {
+  AddonManager.getAddonByID(addon1.id, callback_soon(function(a1) {
     do_check_neq(a1, null);
     do_check_eq(a1.version, "1.0");
 
     dest.remove(true);
 
     restartManager();
 
     AddonManager.getAddonByID(addon1.id, function(a1) {
       do_check_eq(a1, null);
 
       let pointer = profileDir.clone();
       pointer.append(addon1.id);
       do_check_false(pointer.exists());
 
       do_execute_soon(run_test_10);
     });
-  });
+  }));
 }
 
 // Tests that installing a new add-on by pointer with a relative path works
 function run_test_10() {
   writeInstallRDFForExtension(addon1, sourceDir);
   writeRelativePointer(addon1.id);
 
   restartManager();
--- a/toolkit/mozapps/extensions/test/xpcshell/test_fuel.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_fuel.js
@@ -155,10 +155,10 @@ function onPrefChange(evt) {
     inspector3.prefs.get("fuel.fuel-test").events.addListener("change", onPrefChange2);
     inspector3.prefs.setValue("fuel.fuel-test", "change event2");
   });
 }
 
 function onPrefChange2(evt) {
   do_check_eq(evt.data, testdata.dummy);
 
-  do_test_finished();
+  do_execute_soon(do_test_finished);
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_general.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_general.js
@@ -13,17 +13,17 @@ function run_test() {
   do_test_pending();
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
 
   var count = 0;
   startupManager();
   AddonManager.getAddonsByTypes(null, function(list) {
     gCount = list.length;
 
-    run_test_1();
+    do_execute_soon(run_test_1);
   });
 }
 
 function run_test_1() {
   restartManager();
 
   AddonManager.getAddonsByTypes(null, function(addons) {
     do_check_eq(gCount, addons.length);
@@ -46,14 +46,13 @@ function run_test_2() {
 
     do_execute_soon(run_test_3);
   });
 }
 
 function run_test_3() {
   restartManager();
 
-  AddonManager.getAddonsByTypes(null, function(addons) {
+  AddonManager.getAddonsByTypes(null, callback_soon(function(addons) {
     do_check_eq(gCount, addons.length);
-    shutdownManager();
     do_test_finished();
-  });
+  }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_getresource.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_getresource.js
@@ -70,24 +70,25 @@ function run_test() {
 
         try {
           // hasResource should never throw an exception.
           do_check_false(a1.hasResource("icon.png"));
         } catch (e) {
           do_check_true(false);
         }
 
-        AddonManager.getInstallForFile(do_get_addon("test_getresource"), function(aInstall) {
+        AddonManager.getInstallForFile(do_get_addon("test_getresource"),
+            callback_soon(function(aInstall) {
           do_check_false(a1.hasResource("icon.png"));
           do_check_true(aInstall.addon.hasResource("icon.png"));
 
           restartManager();
 
           AddonManager.getAddonByID("addon1@tests.mozilla.org", function(newa1) {
             do_check_eq(newa1, null);
 
-            do_test_finished();
+            do_execute_soon(do_test_finished);
           });
-        });
+        }));
       });
     });
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_hasbinarycomponents.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_hasbinarycomponents.js
@@ -71,12 +71,12 @@ function run_test() {
         do_check_true(a5.hasBinaryComponents);
       else
         do_check_false(a5.hasBinaryComponents);
       do_check_true(a5.isCompatible);
       do_check_false(a5.appDisabled);
       do_check_true(a5.isActive);
       do_check_true(isExtensionInAddonsList(profileDir, a5.id));
 
-      do_test_finished();
+      do_execute_soon(do_test_finished);
     });
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_hotfix.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_hotfix.js
@@ -45,17 +45,17 @@ function run_test_1() {
       "onInstalling"
     ]
   }, [
     "onNewInstall",
     "onDownloadStarted",
     "onDownloadEnded",
     "onInstallStarted",
     "onInstallEnded",
-  ], check_test_1);
+  ], callback_soon(check_test_1));
 
   // Fake a timer event
   gInternalManager.notify(null);
 }
 
 function check_test_1() {
   restartManager();
 
@@ -100,17 +100,17 @@ function run_test_3() {
       "onInstalling"
     ]
   }, [
     "onNewInstall",
     "onDownloadStarted",
     "onDownloadEnded",
     "onInstallStarted",
     "onInstallEnded",
-  ], check_test_3);
+  ], callback_soon(check_test_3));
 
   // Fake a timer event
   gInternalManager.notify(null);
 }
 
 function check_test_3() {
   restartManager();
 
@@ -184,17 +184,17 @@ function run_test_6() {
       "onInstalling"
     ]
   }, [
     "onNewInstall",
     "onDownloadStarted",
     "onDownloadEnded",
     "onInstallStarted",
     "onInstallEnded",
-  ], check_test_6);
+  ], callback_soon(check_test_6));
 
   // Fake a timer event
   gInternalManager.notify(null);
 }
 
 function check_test_6() {
   AddonManager.addInstallListener({
     onNewInstall: function() {
@@ -256,17 +256,17 @@ function check_test_7(aInstall) {
       "onInstalling"
     ]
   }, [
     "onNewInstall",
     "onDownloadStarted",
     "onDownloadEnded",
     "onInstallStarted",
     "onInstallEnded",
-  ], finish_test_7);
+  ], callback_soon(finish_test_7));
 
   // Fake a timer event
   gInternalManager.notify(null);
 }
 
 function finish_test_7() {
   restartManager();
 
@@ -321,25 +321,25 @@ function check_test_8() {
     "onInstallEnded",
   ], finish_test_8);
 
   // Fake a timer event
   gInternalManager.notify(null);
 }
 
 function finish_test_8() {
-  AddonManager.getAllInstalls(function(aInstalls) {
+  AddonManager.getAllInstalls(callback_soon(function(aInstalls) {
     do_check_eq(aInstalls.length, 1);
     do_check_eq(aInstalls[0].version, "2.0");
 
     restartManager();
 
-    AddonManager.getAddonByID("hotfix@tests.mozilla.org", function(aAddon) {
+    AddonManager.getAddonByID("hotfix@tests.mozilla.org", callback_soon(function(aAddon) {
       do_check_neq(aAddon, null);
       do_check_eq(aAddon.version, "2.0");
 
       aAddon.uninstall();
       restartManager();
 
       end_test();
-    });
-  });
+    }));
+  }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_install.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_install.js
@@ -119,17 +119,17 @@ function run_test_1() {
   });
 }
 
 function check_test_1(installSyncGUID) {
   ensure_test_completed();
   AddonManager.getAddonByID("addon1@tests.mozilla.org", function(olda1) {
     do_check_eq(olda1, null);
 
-    AddonManager.getAddonsWithOperationsByTypes(null, function(pendingAddons) {
+    AddonManager.getAddonsWithOperationsByTypes(null, callback_soon(function(pendingAddons) {
       do_check_eq(pendingAddons.length, 1);
       do_check_eq(pendingAddons[0].id, "addon1@tests.mozilla.org");
       let uri = NetUtil.newURI(pendingAddons[0].iconURL);
       if (uri instanceof AM_Ci.nsIJARURI) {
         let jarURI = uri.QueryInterface(AM_Ci.nsIJARURI);
         let archiveURI = jarURI.JARFile;
         let archiveFile = archiveURI.QueryInterface(AM_Ci.nsIFileURL).file;
         let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].
@@ -157,17 +157,17 @@ function check_test_1(installSyncGUID) {
       do_check_false(hasFlag(pendingAddons[0].permissions, AddonManager.PERM_CAN_ENABLE));
       do_check_false(hasFlag(pendingAddons[0].permissions, AddonManager.PERM_CAN_DISABLE));
 
       restartManager();
 
       AddonManager.getAllInstalls(function(activeInstalls) {
         do_check_eq(activeInstalls, 0);
 
-        AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+        AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
           do_check_neq(a1, null);
           do_check_neq(a1.syncGUID, null);
           do_check_true(a1.syncGUID.length >= 9);
           do_check_eq(a1.syncGUID, installSyncGUID);
           do_check_eq(a1.type, "extension");
           do_check_eq(a1.version, "1.0");
           do_check_eq(a1.name, "Test 1");
           do_check_true(isExtensionInAddonsList(profileDir, a1.id));
@@ -193,20 +193,20 @@ function check_test_1(installSyncGUID) {
           do_check_eq(a1.getResourceURI("install.rdf").spec, uri + "install.rdf");
           do_check_eq(a1.iconURL, uri + "icon.png");
           do_check_eq(a1.icon64URL, uri + "icon64.png");
 
           a1.uninstall();
           restartManager();
           do_check_not_in_crash_annotation(a1.id, a1.version);
 
-          run_test_2();
-        });
+          do_execute_soon(run_test_2);
+        }));
       });
-    });
+    }));
   });
 }
 
 // Tests that an install from a url downloads.
 function run_test_2() {
   let url = "http://localhost:" + gPort + "/addons/test_install2_1.xpi";
   AddonManager.getInstallForURL(url, function(install) {
     do_check_neq(install, null);
@@ -270,17 +270,17 @@ function run_test_3(install) {
 function check_test_3(aInstall) {
   // Make the pending install have a sensible date
   let updateDate = Date.now();
   let extURI = aInstall.addon.getResourceURI("");
   let ext = extURI.QueryInterface(AM_Ci.nsIFileURL).file;
   setExtensionModifiedTime(ext, updateDate);
 
   ensure_test_completed();
-  AddonManager.getAddonByID("addon2@tests.mozilla.org", function(olda2) {
+  AddonManager.getAddonByID("addon2@tests.mozilla.org", callback_soon(function(olda2) {
     do_check_eq(olda2, null);
     restartManager();
 
     AddonManager.getAllInstalls(function(installs) {
       do_check_eq(installs, 0);
 
       AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
         do_check_neq(a2, null);
@@ -302,17 +302,17 @@ function check_test_3(aInstall) {
         if (Math.abs(difference) > MAX_TIME_DIFFERENCE)
           do_throw("Add-on update time was out by " + difference + "ms");
 
         gInstallDate = a2.installDate.getTime();
 
         run_test_4();
       });
     });
-  });
+  }));
 }
 
 // Tests that installing a new version of an existing add-on works
 function run_test_4() {
   prepare_test({ }, [
     "onNewInstall"
   ]);
 
@@ -371,17 +371,17 @@ function check_test_5(install) {
   ensure_test_completed();
 
   do_check_eq(install.existingAddon.pendingUpgrade.install, install);
 
   AddonManager.getAddonByID("addon2@tests.mozilla.org", function(olda2) {
     do_check_neq(olda2, null);
     do_check_true(hasFlag(olda2.pendingOperations, AddonManager.PENDING_UPGRADE));
 
-    AddonManager.getInstallsByTypes(null, function(installs) {
+    AddonManager.getInstallsByTypes(null, callback_soon(function(installs) {
       do_check_eq(installs.length, 1);
       do_check_eq(installs[0].addon, olda2.pendingUpgrade);
       restartManager();
 
       AddonManager.getInstallsByTypes(null, function(installs) {
         do_check_eq(installs.length, 0);
 
         AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
@@ -397,27 +397,27 @@ function check_test_5(install) {
                       "http://localhost:" + gPort + "/addons/test_install2_2.xpi");
           do_check_false(a2.foreignInstall);
 
           do_check_eq(a2.installDate.getTime(), gInstallDate);
           // Update date should be later (or the same if this test is too fast)
           do_check_true(a2.installDate <= a2.updateDate);
 
           a2.uninstall();
-          restartManager();
-
-          run_test_6();
+          do_execute_soon(run_test_6);
         });
       });
-    });
+    }));
   });
 }
 
 // Tests that an install that requires a compatibility update works
 function run_test_6() {
+  restartManager();
+
   prepare_test({ }, [
     "onNewInstall"
   ]);
 
   let url = "http://localhost:" + gPort + "/addons/test_install3.xpi";
   AddonManager.getInstallForURL(url, function(install) {
     ensure_test_completed();
 
@@ -459,17 +459,17 @@ function run_test_7() {
   }, [
     "onInstallStarted",
     "onInstallEnded",
   ], check_test_7);
 }
 
 function check_test_7() {
   ensure_test_completed();
-  AddonManager.getAddonByID("addon3@tests.mozilla.org", function(olda3) {
+  AddonManager.getAddonByID("addon3@tests.mozilla.org", callback_soon(function(olda3) {
     do_check_eq(olda3, null);
     restartManager();
 
     AddonManager.getAllInstalls(function(installs) {
       do_check_eq(installs, 0);
 
       AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) {
         do_check_neq(a3, null);
@@ -477,25 +477,25 @@ function check_test_7() {
         do_check_eq(a3.type, "extension");
         do_check_eq(a3.version, "1.0");
         do_check_eq(a3.name, "Real Test 4");
         do_check_true(a3.isActive);
         do_check_false(a3.appDisabled);
         do_check_true(isExtensionInAddonsList(profileDir, a3.id));
         do_check_true(do_get_addon("test_install3").exists());
         a3.uninstall();
-        restartManager();
-
-        run_test_8();
+        do_execute_soon(run_test_8);
       });
     });
-  });
+  }));
 }
 
 function run_test_8() {
+  restartManager();
+
   AddonManager.addInstallListener(InstallListener);
   AddonManager.addAddonListener(AddonListener);
 
   prepare_test({ }, [
     "onNewInstall"
   ]);
 
   AddonManager.getInstallForFile(do_get_addon("test_install3"), function(install) {
@@ -503,17 +503,17 @@ function run_test_8() {
 
     prepare_test({
       "addon3@tests.mozilla.org": [
         "onInstalling"
       ]
     }, [
       "onInstallStarted",
       "onInstallEnded",
-    ], check_test_8);
+    ], callback_soon(check_test_8));
     install.install();
   });
 }
 
 function check_test_8() {
   restartManager();
 
   AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) {
@@ -522,24 +522,24 @@ function check_test_8() {
     do_check_eq(a3.type, "extension");
     do_check_eq(a3.version, "1.0");
     do_check_eq(a3.name, "Real Test 4");
     do_check_true(a3.isActive);
     do_check_false(a3.appDisabled);
     do_check_true(isExtensionInAddonsList(profileDir, a3.id));
     do_check_true(do_get_addon("test_install3").exists());
     a3.uninstall();
-    restartManager();
-
-    run_test_9();
+    do_execute_soon(run_test_9);
   });
 }
 
 // Test that after cancelling a download it is removed from the active installs
 function run_test_9() {
+  restartManager();
+
   prepare_test({ }, [
     "onNewInstall"
   ]);
 
   let url = "http://localhost:" + gPort + "/addons/test_install3.xpi";
   AddonManager.getInstallForURL(url, function(install) {
     ensure_test_completed();
 
@@ -620,28 +620,28 @@ function check_test_10(install) {
   }, [
     "onInstallCancelled"
   ]);
 
   install.cancel();
 
   ensure_test_completed();
 
-  AddonManager.getAllInstalls(function(activeInstalls) {
+  AddonManager.getAllInstalls(callback_soon(function(activeInstalls) {
     do_check_eq(activeInstalls.length, 0);
 
     restartManager();
 
     // Check that the install did not complete
     AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) {
       do_check_eq(a3, null);
 
-      run_test_11();
+      do_execute_soon(run_test_11);
     });
-  });
+  }));
 }
 
 // Tests that a multi-package install shows up as multiple installs with the
 // correct sourceURI.
 function run_test_11() {
   prepare_test({ }, [
     "onNewInstall",
     "onNewInstall",
@@ -733,17 +733,17 @@ function run_test_11() {
         "addon6@tests.mozilla.org": [
           "onInstallStarted",
           "onInstallEnded"
         ],
         "addon7@tests.mozilla.org": [
           "onInstallStarted",
           "onInstallEnded"
         ]
-      }, check_test_11);
+      }, callback_soon(check_test_11));
 
       installs[0].install();
       installs[1].install();
       installs[3].install();
 
       // Note that we install addon6 last. Since it doesn't need a restart to
       // install it completes asynchronously which would otherwise make the
       // onInstallStarted/onInstallEnded events go out of sequence unless this
@@ -766,24 +766,24 @@ function check_test_11() {
     do_check_neq(a6, null);
     do_check_neq(a7, null);
 
     a4.uninstall();
     a5.uninstall();
     a6.uninstall();
     a7.uninstall();
 
-    restartManager();
-
-    run_test_12();
+    do_execute_soon(run_test_12);
   });
 }
 
 // Same as test 11 but for a remote XPI
 function run_test_12() {
+  restartManager();
+
   prepare_test({ }, [
     "onNewInstall",
   ]);
 
   let url = "http://localhost:" + gPort + "/addons/test_install4.xpi";
   AddonManager.getInstallForURL(url, function(install) {
     gInstall = install;
 
@@ -824,17 +824,17 @@ function run_test_12() {
       "addon6@tests.mozilla.org": [
         "onInstallStarted",
         "onInstallEnded"
       ],
       "addon7@tests.mozilla.org": [
         "onInstallStarted",
         "onInstallEnded"
       ]
-    }, check_test_12);
+    }, callback_soon(check_test_12));
     install.install();
   }, "application/x-xpinstall", null, "Multi Test 4");
 }
 
 function check_test_12() {
   do_check_eq(gInstall.linkedInstalls.length, 3);
 
   // Might be in any order so sort them based on ID
@@ -891,26 +891,26 @@ function check_test_12() {
     do_check_neq(a6, null);
     do_check_neq(a7, null);
 
     a4.uninstall();
     a5.uninstall();
     a6.uninstall();
     a7.uninstall();
 
-    restartManager();
-
-    run_test_13();
+    do_execute_soon(run_test_13);
   });
 }
 
 
 // Tests that cancelling an upgrade leaves the original add-on's pendingOperations
 // correct
 function run_test_13() {
+  restartManager();
+
   installAllFiles([do_get_addon("test_install2_1")], function() {
     restartManager();
 
     prepare_test({ }, [
       "onNewInstall"
     ]);
 
     let url = "http://localhost:" + gPort + "/addons/test_install2_2.xpi";
@@ -948,17 +948,17 @@ function check_test_13(install) {
 
   do_check_eq(install.version, "3.0");
   do_check_eq(install.name, "Real Test 3");
   do_check_eq(install.state, AddonManager.STATE_INSTALLED);
   do_check_neq(install.existingAddon, null);
   do_check_eq(install.existingAddon.id, "addon2@tests.mozilla.org");
   do_check_eq(install.addon.install, install);
 
-  AddonManager.getAddonByID("addon2@tests.mozilla.org", function(olda2) {
+  AddonManager.getAddonByID("addon2@tests.mozilla.org", callback_soon(function(olda2) {
     do_check_neq(olda2, null);
     do_check_true(hasFlag(olda2.pendingOperations, AddonManager.PENDING_UPGRADE));
     do_check_eq(olda2.pendingUpgrade, install.addon);
 
     do_check_true(hasFlag(install.addon.pendingOperations,
                           AddonManager.PENDING_INSTALL));
 
     prepare_test({
@@ -979,25 +979,25 @@ function check_test_13(install) {
     restartManager();
 
     // Check that the upgrade did not complete
     AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
       do_check_eq(a2.version, "2.0");
 
       a2.uninstall();
 
-      restartManager();
-
-      run_test_14();
+      do_execute_soon(run_test_14);
     });
-  });
+  }));
 }
 
 // Check that cancelling the install from onDownloadStarted actually cancels it
 function run_test_14() {
+  restartManager();
+
   prepare_test({ }, [
     "onNewInstall"
   ]);
 
   let url = "http://localhost:" + gPort + "/addons/test_install2_1.xpi";
   AddonManager.getInstallForURL(url, function(install) {
     ensure_test_completed();
 
@@ -1342,17 +1342,17 @@ function run_test_21() {
       AddonManager.getInstallForURL(url, function(aInstall) {
         aInstall.install();
       }, "application/x-xpinstall");
     });
   });
 }
 
 function check_test_21(aInstall) {
-  AddonManager.getAllInstalls(function(aInstalls) {
+  AddonManager.getAllInstalls(callback_soon(function(aInstalls) {
     do_check_eq(aInstalls.length, 1);
     do_check_eq(aInstalls[0], aInstall);
 
     prepare_test({
       "addon2@tests.mozilla.org": [
         "onOperationCancelled"
       ]
     }, [
@@ -1365,17 +1365,17 @@ function check_test_21(aInstall) {
 
     restartManager();
 
     AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
       do_check_eq(a2, null);
 
       run_test_22();
     });
-  });
+  }));
 }
 
 // Tests that an install can be restarted after being cancelled
 function run_test_22() {
   prepare_test({ }, [
     "onNewInstall"
   ]);
 
--- a/toolkit/mozapps/extensions/test/xpcshell/test_install_icons.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_install_icons.js
@@ -51,11 +51,11 @@ function test_3() {
 }
 
 function test_4() {
   AddonManager.getInstallForURL(addon_url, function(aInstall) {
     do_check_eq(aInstall.iconURL, icon32_url);
     do_check_neq(aInstall.icons, null);
     do_check_eq(aInstall.icons[32], icon32_url);
     do_check_eq(aInstall.icons[64], icon64_url);
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   }, "application/x-xpinstall", null, null, { "32": icon32_url, "64": icon64_url }, null, null);
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js
@@ -116,17 +116,17 @@ function run_test_1() {
   });
 }
 
 function check_test_1() {
   ensure_test_completed();
   AddonManager.getAddonByID("addon1@tests.mozilla.org", function(olda1) {
     do_check_eq(olda1, null);
 
-    AddonManager.getAddonsWithOperationsByTypes(null, function(pendingAddons) {
+    AddonManager.getAddonsWithOperationsByTypes(null, callback_soon(function(pendingAddons) {
       do_check_eq(pendingAddons.length, 1);
       do_check_eq(pendingAddons[0].id, "addon1@tests.mozilla.org");
       let uri = NetUtil.newURI(pendingAddons[0].iconURL);
       if (uri instanceof AM_Ci.nsIJARURI) {
         let jarURI = uri.QueryInterface(AM_Ci.nsIJARURI);
         let archiveURI = jarURI.JARFile;
         let archiveFile = archiveURI.QueryInterface(AM_Ci.nsIFileURL).file;
         let zipReader = Cc["@mozilla.org/libjar/zip-reader;1"].
@@ -186,17 +186,17 @@ function check_test_1() {
           do_check_eq(a1.getResourceURI("install.rdf").spec, uri + "install.rdf");
           do_check_eq(a1.iconURL, uri + "icon.png");
           do_check_eq(a1.icon64URL, uri + "icon64.png");
 
           a1.uninstall();
           do_execute_soon(function(){run_test_2(a1)});
         });
       });
-    });
+    }));
   });
 }
 
 // Tests that an install from a url downloads.
 function run_test_2(aAddon) {
   restartManager();
   do_check_not_in_crash_annotation(aAddon.id, aAddon.version);
 
@@ -263,17 +263,17 @@ function run_test_3(install) {
 function check_test_3(aInstall) {
   // Make the pending install have a sensible date
   let updateDate = Date.now();
   let extURI = aInstall.addon.getResourceURI("");
   let ext = extURI.QueryInterface(AM_Ci.nsIFileURL).file;
   setExtensionModifiedTime(ext, updateDate);
 
   ensure_test_completed();
-  AddonManager.getAddonByID("addon2@tests.mozilla.org", function(olda2) {
+  AddonManager.getAddonByID("addon2@tests.mozilla.org", callback_soon(function(olda2) {
     do_check_eq(olda2, null);
     restartManager();
 
     AddonManager.getAllInstalls(function(installs) {
       do_check_eq(installs, 0);
 
       AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
         do_check_neq(a2, null);
@@ -294,17 +294,17 @@ function check_test_3(aInstall) {
         if (Math.abs(difference) > MAX_TIME_DIFFERENCE)
           do_throw("Add-on update time was out by " + difference + "ms");
 
         gInstallDate = a2.installDate.getTime();
 
         run_test_4();
       });
     });
-  });
+  }));
 }
 
 // Tests that installing a new version of an existing add-on works
 function run_test_4() {
   prepare_test({ }, [
     "onNewInstall"
   ]);
 
@@ -363,17 +363,17 @@ function check_test_5(install) {
   ensure_test_completed();
 
   do_check_eq(install.existingAddon.pendingUpgrade.install, install);
 
   AddonManager.getAddonByID("addon2@tests.mozilla.org", function(olda2) {
     do_check_neq(olda2, null);
     do_check_true(hasFlag(olda2.pendingOperations, AddonManager.PENDING_UPGRADE));
 
-    AddonManager.getInstallsByTypes(null, function(installs) {
+    AddonManager.getInstallsByTypes(null, callback_soon(function(installs) {
       do_check_eq(installs.length, 1);
       do_check_eq(installs[0].addon, olda2.pendingUpgrade);
       restartManager();
 
       AddonManager.getInstallsByTypes(null, function(installs) {
         do_check_eq(installs.length, 0);
 
         AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
@@ -391,17 +391,17 @@ function check_test_5(install) {
           do_check_eq(a2.installDate.getTime(), gInstallDate);
           // Update date should be later (or the same if this test is too fast)
           do_check_true(a2.installDate <= a2.updateDate);
 
           a2.uninstall();
           do_execute_soon(run_test_6);
         });
       });
-    });
+    }));
   });
 }
 
 // Tests that an install that requires a compatibility update works
 function run_test_6() {
   restartManager();
 
   prepare_test({ }, [
@@ -450,17 +450,17 @@ function run_test_7() {
   }, [
     "onInstallStarted",
     "onInstallEnded",
   ], check_test_7);
 }
 
 function check_test_7() {
   ensure_test_completed();
-  AddonManager.getAddonByID("addon3@tests.mozilla.org", function(olda3) {
+  AddonManager.getAddonByID("addon3@tests.mozilla.org", callback_soon(function(olda3) {
     do_check_eq(olda3, null);
     restartManager();
 
     AddonManager.getAllInstalls(function(installs) {
       do_check_eq(installs, 0);
 
       AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) {
         do_check_neq(a3, null);
@@ -470,17 +470,17 @@ function check_test_7() {
         do_check_true(a3.isActive);
         do_check_false(a3.appDisabled);
         do_check_true(isExtensionInAddonsList(profileDir, a3.id));
         do_check_true(do_get_addon("test_install3").exists());
         a3.uninstall();
         do_execute_soon(run_test_8);
       });
     });
-  });
+  }));
 }
 
 function run_test_8() {
   restartManager();
 
   AddonManager.addInstallListener(InstallListener);
   AddonManager.addAddonListener(AddonListener);
 
@@ -493,17 +493,17 @@ function run_test_8() {
 
     prepare_test({
       "addon3@tests.mozilla.org": [
         "onInstalling"
       ]
     }, [
       "onInstallStarted",
       "onInstallEnded",
-    ], check_test_8);
+    ], callback_soon(check_test_8));
     install.install();
   });
 }
 
 function check_test_8() {
   restartManager();
 
   AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) {
@@ -609,28 +609,28 @@ function check_test_10(install) {
   }, [
     "onInstallCancelled"
   ]);
 
   install.cancel();
 
   ensure_test_completed();
 
-  AddonManager.getAllInstalls(function(activeInstalls) {
+  AddonManager.getAllInstalls(callback_soon(function(activeInstalls) {
     do_check_eq(activeInstalls.length, 0);
 
     restartManager();
 
     // Check that the install did not complete
     AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) {
       do_check_eq(a3, null);
 
       run_test_11();
     });
-  });
+  }));
 }
 
 // Tests that a multi-package install shows up as multiple installs with the
 // correct sourceURI.
 function run_test_11() {
   prepare_test({ }, [
     "onNewInstall",
     "onNewInstall",
@@ -723,17 +723,17 @@ function run_test_11() {
         "addon6@tests.mozilla.org": [
           "onInstallStarted",
           "onInstallEnded"
         ],
         "addon7@tests.mozilla.org": [
           "onInstallStarted",
           "onInstallEnded"
         ]
-      }, check_test_11);
+      }, callback_soon(check_test_11));
 
       installs[0].install();
       installs[1].install();
       installs[3].install();
 
       // Note that we install addon6 last. Since it doesn't need a restart to
       // install it completes asynchronously which would otherwise make the
       // onInstallStarted/onInstallEnded events go out of sequence unless this
@@ -815,17 +815,17 @@ function run_test_12() {
       "addon6@tests.mozilla.org": [
         "onInstallStarted",
         "onInstallEnded"
       ],
       "addon7@tests.mozilla.org": [
         "onInstallStarted",
         "onInstallEnded"
       ]
-    }, check_test_12);
+    }, callback_soon(check_test_12));
     install.install();
   }, "application/x-xpinstall", null, "Multi Test 4");
 }
 
 function check_test_12() {
   do_check_eq(gInstall.linkedInstalls.length, 3);
 
   // Might be in any order so sort them based on ID
@@ -939,17 +939,17 @@ function check_test_13(install) {
 
   do_check_eq(install.version, "3.0");
   do_check_eq(install.name, "Real Test 3");
   do_check_eq(install.state, AddonManager.STATE_INSTALLED);
   do_check_neq(install.existingAddon, null);
   do_check_eq(install.existingAddon.id, "addon2@tests.mozilla.org");
   do_check_eq(install.addon.install, install);
 
-  AddonManager.getAddonByID("addon2@tests.mozilla.org", function(olda2) {
+  AddonManager.getAddonByID("addon2@tests.mozilla.org", callback_soon(function(olda2) {
     do_check_neq(olda2, null);
     do_check_true(hasFlag(olda2.pendingOperations, AddonManager.PENDING_UPGRADE));
     do_check_eq(olda2.pendingUpgrade, install.addon);
 
     do_check_true(hasFlag(install.addon.pendingOperations,
                           AddonManager.PENDING_INSTALL));
 
     prepare_test({
@@ -972,17 +972,17 @@ function check_test_13(install) {
     // Check that the upgrade did not complete
     AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
       do_check_eq(a2.version, "2.0");
 
       a2.uninstall();
 
       do_execute_soon(run_test_14);
     });
-  });
+  }));
 }
 
 // Check that cancelling the install from onDownloadStarted actually cancels it
 function run_test_14() {
   restartManager();
 
   prepare_test({ }, [
     "onNewInstall"
@@ -1333,17 +1333,17 @@ function run_test_21() {
       AddonManager.getInstallForURL(url, function(aInstall) {
         aInstall.install();
       }, "application/x-xpinstall");
     });
   });
 }
 
 function check_test_21(aInstall) {
-  AddonManager.getAllInstalls(function(aInstalls) {
+  AddonManager.getAllInstalls(callback_soon(function(aInstalls) {
     do_check_eq(aInstalls.length, 1);
     do_check_eq(aInstalls[0], aInstall);
 
     prepare_test({
       "addon2@tests.mozilla.org": [
         "onOperationCancelled"
       ]
     }, [
@@ -1356,17 +1356,17 @@ function check_test_21(aInstall) {
 
     restartManager();
 
     AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
       do_check_eq(a2, null);
 
       run_test_22();
     });
-  });
+  }));
 }
 
 // Tests that an install can be restarted after being cancelled
 function run_test_22() {
   prepare_test({ }, [
     "onNewInstall"
   ]);
 
@@ -1635,10 +1635,10 @@ function finish_test_27(aInstall) {
   }, [
     "onInstallCancelled"
   ]);
 
   aInstall.cancel();
 
   ensure_test_completed();
 
-  do_test_finished();
+  end_test();
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_langpack.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_langpack.js
@@ -137,17 +137,17 @@ function run_test_2() {
 
     AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(newb1) {
       do_check_neq(newb1, null);
       do_check_eq(newb1.version, "1.0");
       do_check_false(newb1.appDisabled);
       do_check_true(newb1.userDisabled);
       do_check_false(newb1.isActive);
 
-      run_test_3();
+      do_execute_soon(run_test_3);
     });
   });
 }
 
 // Test that restarting doesn't accidentally re-enable
 function run_test_3() {
   shutdownManager();
   startupManager(false);
@@ -190,17 +190,17 @@ function run_test_4() {
 
     AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(newb1) {
       do_check_neq(newb1, null);
       do_check_eq(newb1.version, "1.0");
       do_check_false(newb1.appDisabled);
       do_check_false(newb1.userDisabled);
       do_check_true(newb1.isActive);
 
-      run_test_5();
+      do_execute_soon(run_test_5);
     });
   });
 }
 
 // Tests that a restart shuts down and restarts the add-on
 function run_test_5() {
   shutdownManager();
   // check chrome reg that language pack is not registered
@@ -239,38 +239,40 @@ function run_test_7() {
   });
 }
 
 function check_test_7() {
   ensure_test_completed();
   // check chrome reg that language pack is not registered
   do_check_locale_not_registered("test-langpack");
 
-  AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org",
+   callback_soon(function(b1) {
     do_check_eq(b1, null);
 
     restartManager();
 
     AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(newb1) {
       do_check_eq(newb1, null);
 
-      run_test_8();
+      do_execute_soon(run_test_8);
     });
-  });
+  }));
 }
 
 // Tests that a locale detected in the profile starts working immediately
 function run_test_8() {
   shutdownManager();
 
   manuallyInstall(do_get_addon("test_langpack"), profileDir, "langpack-x-testing@tests.mozilla.org");
 
   startupManager(false);
 
-  AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org",
+   callback_soon(function(b1) {
     do_check_neq(b1, null);
     do_check_eq(b1.version, "1.0");
     do_check_false(b1.appDisabled);
     do_check_false(b1.userDisabled);
     do_check_true(b1.isActive);
     // check chrome reg that language pack is registered
     do_check_eq(chrome.getSelectedLocale("test-langpack"), "x-testing");
     do_check_true(b1.hasResource("install.rdf"));
@@ -288,30 +290,30 @@ function run_test_8() {
         "langpack-x-testing@tests.mozilla.org": [
           ["onUninstalling", false],
           "onUninstalled"
         ]
       });
 
       b2.uninstall();
       ensure_test_completed();
-      run_test_9();
+      do_execute_soon(run_test_9);
     });
-  });
+  }));
 }
 
 // Tests that a locale from distribution/extensions gets installed and starts
 // working immediately
 function run_test_9() {
   shutdownManager();
   manuallyInstall(do_get_addon("test_langpack"), distroDir, "langpack-x-testing@tests.mozilla.org");
   gAppInfo.version = "2.0";
   startupManager(true);
 
-  AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", function(b1) {
+  AddonManager.getAddonByID("langpack-x-testing@tests.mozilla.org", callback_soon(function(b1) {
     do_check_neq(b1, null);
     do_check_eq(b1.version, "1.0");
     do_check_false(b1.appDisabled);
     do_check_false(b1.userDisabled);
     do_check_true(b1.isActive);
     // check chrome reg that language pack is registered
     do_check_eq(chrome.getSelectedLocale("test-langpack"), "x-testing");
     do_check_true(b1.hasResource("install.rdf"));
@@ -320,10 +322,10 @@ function run_test_9() {
     shutdownManager();
     // check chrome reg that language pack is not registered
     do_check_locale_not_registered("test-langpack");
     startupManager(false);
     // check chrome reg that language pack is registered
     do_check_eq(chrome.getSelectedLocale("test-langpack"), "x-testing");
 
     do_test_finished();
-  });
+  }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_locale.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_locale.js
@@ -29,45 +29,45 @@ function run_test_1() {
 
     prepare_test({
       "addon1@tests.mozilla.org": [
         "onInstalling"
       ]
     }, [
       "onInstallStarted",
       "onInstallEnded",
-    ], run_test_2);
+    ], callback_soon(run_test_2));
     install.install();
   });
 }
 
 // Tests that the localized properties are visible after installation
 function run_test_2() {
   restartManager();
 
   AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) {
     do_check_neq(addon, null);
 
     do_check_eq(addon.name, "fr-FR Name");
     do_check_eq(addon.description, "fr-FR Description");
 
     addon.userDisabled = true;
-    restartManager();
-
-    run_test_3();
+    do_execute_soon(run_test_3);
   });
 }
 
 // Test that the localized properties are still there when disabled.
 function run_test_3() {
+  restartManager();
+
   AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) {
     do_check_neq(addon, null);
     do_check_eq(addon.name, "fr-FR Name");
 
-    run_test_4();
+    do_execute_soon(run_test_4);
   });
 }
 
 // Localised preference values should be ignored when the add-on is disabled
 function run_test_4() {
   Services.prefs.setCharPref("extensions.addon1@tests.mozilla.org.name", "Name from prefs");
   Services.prefs.setCharPref("extensions.addon1@tests.mozilla.org.contributor.1", "Contributor 1");
   Services.prefs.setCharPref("extensions.addon1@tests.mozilla.org.contributor.2", "Contributor 2");
@@ -77,60 +77,61 @@ function run_test_4() {
     do_check_neq(addon, null);
     do_check_eq(addon.name, "fr-FR Name");
     let contributors = addon.contributors;
     do_check_eq(contributors.length, 3);
     do_check_eq(contributors[0], "Fr Contributor 1");
     do_check_eq(contributors[1], "Fr Contributor 2");
     do_check_eq(contributors[2], "Fr Contributor 3");
 
-    run_test_5();
+    do_execute_soon(run_test_5);
   });
 }
 
 // Test that changing locale works
 function run_test_5() {
   Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "de-DE");
   restartManager();
 
   AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) {
     do_check_neq(addon, null);
 
     do_check_eq(addon.name, "de-DE Name");
     do_check_eq(addon.description, null);
 
-    run_test_6();
+    do_execute_soon(run_test_6);
   });
 }
 
 // Test that missing locales use the fallbacks
 function run_test_6() {
   Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "nl-NL");
   restartManager();
 
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(addon) {
     do_check_neq(addon, null);
 
     do_check_eq(addon.name, "Fallback Name");
     do_check_eq(addon.description, "Fallback Description");
 
     addon.userDisabled = false;
-    restartManager();
-    run_test_7();
-  });
+    do_execute_soon(run_test_7);
+  }));
 }
 
 // Test that the prefs will override the fallbacks
 function run_test_7() {
+  restartManager();
+
   AddonManager.getAddonByID("addon1@tests.mozilla.org", function(addon) {
     do_check_neq(addon, null);
 
     do_check_eq(addon.name, "Name from prefs");
 
-    run_test_8();
+    do_execute_soon(run_test_8);
   });
 }
 
 // Test that the prefs will override localized values from the manifest
 function run_test_8() {
   Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "fr-FR");
   restartManager();
 
@@ -138,11 +139,11 @@ function run_test_8() {
     do_check_neq(addon, null);
 
     do_check_eq(addon.name, "Name from prefs");
     let contributors = addon.contributors;
     do_check_eq(contributors.length, 2);
     do_check_eq(contributors[0], "Contributor 1");
     do_check_eq(contributors[1], "Contributor 2");
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
old mode 100644
new mode 100755
--- a/toolkit/mozapps/extensions/test/xpcshell/test_locked.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked.js
@@ -1,16 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // Checks that we rebuild something sensible from a corrupt database
 
+Components.utils.import("resource://testing-common/httpd.js");
+Components.utils.import("resource://gre/modules/osfile.jsm");
 
-Components.utils.import("resource://testing-common/httpd.js");
 var testserver = new HttpServer();
 testserver.start(-1);
 gPort = testserver.identity.primaryPort;
 mapFile("/data/test_corrupt.rdf", testserver);
 testserver.registerDirectory("/addons/", do_get_file("addons"));
 
 // The test extension uses an insecure update url.
 Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
@@ -249,229 +250,77 @@ function run_test_1() {
 
     do_check_neq(t2, null);
     do_check_true(t2.isActive);
     do_check_false(t2.userDisabled);
     do_check_false(t2.appDisabled);
     do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE);
     do_check_true(isThemeInAddonsList(profileDir, t2.id));
 
-    // After shutting down the database won't be open so we can
-    // mess with permissions
+    // Open another handle on the JSON DB with as much Unix and Windows locking
+    // as we can to simulate some other process interfering with it
     shutdownManager();
-    var savedPermissions = gExtensionsJSON.permissions;
-    gExtensionsJSON.permissions = 0;
-
-    startupManager(false);
-
-    // Shouldn't have seen any startup changes
-    check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []);
-
-    // Accessing the add-ons should open and recover the database
-    AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
-                                 "addon2@tests.mozilla.org",
-                                 "addon3@tests.mozilla.org",
-                                 "addon4@tests.mozilla.org",
-                                 "addon5@tests.mozilla.org",
-                                 "addon6@tests.mozilla.org",
-                                 "addon7@tests.mozilla.org",
-                                 "theme1@tests.mozilla.org",
-                                 "theme2@tests.mozilla.org"],
-                                 callback_soon(function get_after_lock([a1, a2, a3, a4, a5, a6, a7, t1, t2]) {
-      // Should be correctly recovered
-      do_check_neq(a1, null);
-      do_check_true(a1.isActive);
-      do_check_false(a1.userDisabled);
-      do_check_false(a1.appDisabled);
-      do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE);
-      do_check_true(isExtensionInAddonsList(profileDir, a1.id));
-
-      // Should be correctly recovered
-      do_check_neq(a2, null);
-      do_check_false(a2.isActive);
-      do_check_true(a2.userDisabled);
-      do_check_false(a2.appDisabled);
-      do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
-      do_check_false(isExtensionInAddonsList(profileDir, a2.id));
-
-      // The compatibility update won't be recovered but it should still be
-      // active for this session
-      do_check_neq(a3, null);
-      do_check_true(a3.isActive);
-      do_check_false(a3.userDisabled);
-      do_check_false(a3.appDisabled);
-      do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
-      do_check_true(isExtensionInAddonsList(profileDir, a3.id));
-
-      // The compatibility update won't be recovered and with strict
-      // compatibility it would not have been able to tell that it was
-      // previously userDisabled. However, without strict compat, it wasn't
-      // appDisabled, so it knows it must have been userDisabled.
-      do_check_neq(a4, null);
-      do_check_false(a4.isActive);
-      do_check_true(a4.userDisabled);
-      do_check_false(a4.appDisabled);
-      do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE);
-      do_check_false(isExtensionInAddonsList(profileDir, a4.id));
-
-      do_check_neq(a5, null);
-      do_check_true(a5.isActive);
-      do_check_false(a5.userDisabled);
-      do_check_false(a5.appDisabled);
-      do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
-      do_check_true(isExtensionInAddonsList(profileDir, a5.id));
-
-      do_check_neq(a6, null);
-      do_check_true(a6.isActive);
-      do_check_false(a6.userDisabled);
-      do_check_false(a6.appDisabled);
-      do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE);
-
-      do_check_neq(a7, null);
-      do_check_false(a7.isActive);
-      do_check_true(a7.userDisabled);
-      do_check_false(a7.appDisabled);
-      do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE);
-
-      // Should be correctly recovered
-      do_check_neq(t1, null);
-      do_check_false(t1.isActive);
-      do_check_true(t1.userDisabled);
-      do_check_false(t1.appDisabled);
-      do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE);
-      do_check_false(isThemeInAddonsList(profileDir, t1.id));
+    do_print("Locking " + gExtensionsJSON.path);
+    let options = {
+      winShare: 0
+    };
+    if (OS.Constants.libc.O_EXLOCK)
+      options.unixFlags = OS.Constants.libc.O_EXLOCK;
 
-      // Should be correctly recovered
-      do_check_neq(t2, null);
-      do_check_true(t2.isActive);
-      do_check_false(t2.userDisabled);
-      do_check_false(t2.appDisabled);
-      do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE);
-      do_check_true(isThemeInAddonsList(profileDir, t2.id));
-
-      // Restarting will actually apply changes to extensions.ini which will
-      // then be put into the in-memory database when we next fail to load the
-      // real thing
-      restartManager();
-
-      // Shouldn't have seen any startup changes
-      check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []);
-
-      AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
-                                   "addon2@tests.mozilla.org",
-                                   "addon3@tests.mozilla.org",
-                                   "addon4@tests.mozilla.org",
-                                   "addon5@tests.mozilla.org",
-                                   "addon6@tests.mozilla.org",
-                                   "addon7@tests.mozilla.org",
-                                   "theme1@tests.mozilla.org",
-                                   "theme2@tests.mozilla.org"],
-                                   callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) {
-        do_check_neq(a1, null);
-        do_check_true(a1.isActive);
-        do_check_false(a1.userDisabled);
-        do_check_false(a1.appDisabled);
-        do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE);
-        do_check_true(isExtensionInAddonsList(profileDir, a1.id));
-
-        do_check_neq(a2, null);
-        do_check_false(a2.isActive);
-        do_check_true(a2.userDisabled);
-        do_check_false(a2.appDisabled);
-        do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
-        do_check_false(isExtensionInAddonsList(profileDir, a2.id));
-
-        do_check_neq(a3, null);
-        do_check_true(a3.isActive);
-        do_check_false(a3.userDisabled);
-        do_check_false(a3.appDisabled);
-        do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
-        do_check_true(isExtensionInAddonsList(profileDir, a3.id));
-
-        do_check_neq(a4, null);
-        do_check_false(a4.isActive);
-        do_check_true(a4.userDisabled);
-        do_check_false(a4.appDisabled);
-        do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE);
-        do_check_false(isExtensionInAddonsList(profileDir, a4.id));
-
-        do_check_neq(a5, null);
-        do_check_true(a5.isActive);
-        do_check_false(a5.userDisabled);
-        do_check_false(a5.appDisabled);
-        do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
-        do_check_true(isExtensionInAddonsList(profileDir, a5.id));
-
-        do_check_neq(a6, null);
-        do_check_true(a6.isActive);
-        do_check_false(a6.userDisabled);
-        do_check_false(a6.appDisabled);
-        do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE);
-
-        do_check_neq(a7, null);
-        do_check_false(a7.isActive);
-        do_check_true(a7.userDisabled);
-        do_check_false(a7.appDisabled);
-        do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE);
-
-        do_check_neq(t1, null);
-        do_check_false(t1.isActive);
-        do_check_true(t1.userDisabled);
-        do_check_false(t1.appDisabled);
-        do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE);
-        do_check_false(isThemeInAddonsList(profileDir, t1.id));
-
-        do_check_neq(t2, null);
-        do_check_true(t2.isActive);
-        do_check_false(t2.userDisabled);
-        do_check_false(t2.appDisabled);
-        do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE);
-        do_check_true(isThemeInAddonsList(profileDir, t2.id));
-
-        // After allowing access to the original DB things should go back to as
-        // they were previously
-        shutdownManager();
-        gExtensionsJSON.permissions = savedPermissions;
-        startupManager();
-
+    OS.File.open(gExtensionsJSON.path, {read:true, write:true, existing:true}, options).then(
+      file => {
+        filePermissions = gExtensionsJSON.permissions;
+        if (!OS.Constants.Win) {
+          gExtensionsJSON.permissions = 0;
+        }
+        startupManager(false);
 
         // Shouldn't have seen any startup changes
         check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []);
 
+        // Accessing the add-ons should open and recover the database
         AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                      "addon2@tests.mozilla.org",
                                      "addon3@tests.mozilla.org",
                                      "addon4@tests.mozilla.org",
                                      "addon5@tests.mozilla.org",
                                      "addon6@tests.mozilla.org",
                                      "addon7@tests.mozilla.org",
                                      "theme1@tests.mozilla.org",
                                      "theme2@tests.mozilla.org"],
-                                     callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) {
+                                     callback_soon(function get_after_lock([a1, a2, a3, a4, a5, a6, a7, t1, t2]) {
+          // Should be correctly recovered
           do_check_neq(a1, null);
           do_check_true(a1.isActive);
           do_check_false(a1.userDisabled);
           do_check_false(a1.appDisabled);
           do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE);
           do_check_true(isExtensionInAddonsList(profileDir, a1.id));
 
+          // Should be correctly recovered
           do_check_neq(a2, null);
           do_check_false(a2.isActive);
           do_check_true(a2.userDisabled);
           do_check_false(a2.appDisabled);
           do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
           do_check_false(isExtensionInAddonsList(profileDir, a2.id));
 
+          // The compatibility update won't be recovered but it should still be
+          // active for this session
           do_check_neq(a3, null);
           do_check_true(a3.isActive);
           do_check_false(a3.userDisabled);
           do_check_false(a3.appDisabled);
           do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
           do_check_true(isExtensionInAddonsList(profileDir, a3.id));
 
+          // The compatibility update won't be recovered and with strict
+          // compatibility it would not have been able to tell that it was
+          // previously userDisabled. However, without strict compat, it wasn't
+          // appDisabled, so it knows it must have been userDisabled.
           do_check_neq(a4, null);
           do_check_false(a4.isActive);
           do_check_true(a4.userDisabled);
           do_check_false(a4.appDisabled);
           do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE);
           do_check_false(isExtensionInAddonsList(profileDir, a4.id));
 
           do_check_neq(a5, null);
@@ -488,28 +337,195 @@ function run_test_1() {
           do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE);
 
           do_check_neq(a7, null);
           do_check_false(a7.isActive);
           do_check_true(a7.userDisabled);
           do_check_false(a7.appDisabled);
           do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE);
 
+          // Should be correctly recovered
           do_check_neq(t1, null);
           do_check_false(t1.isActive);
           do_check_true(t1.userDisabled);
           do_check_false(t1.appDisabled);
           do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE);
           do_check_false(isThemeInAddonsList(profileDir, t1.id));
 
+          // Should be correctly recovered
           do_check_neq(t2, null);
           do_check_true(t2.isActive);
           do_check_false(t2.userDisabled);
           do_check_false(t2.appDisabled);
           do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE);
           do_check_true(isThemeInAddonsList(profileDir, t2.id));
 
-          end_test();
+          // Restarting will actually apply changes to extensions.ini which will
+          // then be put into the in-memory database when we next fail to load the
+          // real thing
+          restartManager();
+
+          // Shouldn't have seen any startup changes
+          check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []);
+
+          AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+                                       "addon2@tests.mozilla.org",
+                                       "addon3@tests.mozilla.org",
+                                       "addon4@tests.mozilla.org",
+                                       "addon5@tests.mozilla.org",
+                                       "addon6@tests.mozilla.org",
+                                       "addon7@tests.mozilla.org",
+                                       "theme1@tests.mozilla.org",
+                                       "theme2@tests.mozilla.org"],
+                                       callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) {
+            do_check_neq(a1, null);
+            do_check_true(a1.isActive);
+            do_check_false(a1.userDisabled);
+            do_check_false(a1.appDisabled);
+            do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE);
+            do_check_true(isExtensionInAddonsList(profileDir, a1.id));
+
+            do_check_neq(a2, null);
+            do_check_false(a2.isActive);
+            do_check_true(a2.userDisabled);
+            do_check_false(a2.appDisabled);
+            do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
+            do_check_false(isExtensionInAddonsList(profileDir, a2.id));
+
+            do_check_neq(a3, null);
+            do_check_true(a3.isActive);
+            do_check_false(a3.userDisabled);
+            do_check_false(a3.appDisabled);
+            do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
+            do_check_true(isExtensionInAddonsList(profileDir, a3.id));
+
+            do_check_neq(a4, null);
+            do_check_false(a4.isActive);
+            do_check_true(a4.userDisabled);
+            do_check_false(a4.appDisabled);
+            do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE);
+            do_check_false(isExtensionInAddonsList(profileDir, a4.id));
+
+            do_check_neq(a5, null);
+            do_check_true(a5.isActive);
+            do_check_false(a5.userDisabled);
+            do_check_false(a5.appDisabled);
+            do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
+            do_check_true(isExtensionInAddonsList(profileDir, a5.id));
+
+            do_check_neq(a6, null);
+            do_check_true(a6.isActive);
+            do_check_false(a6.userDisabled);
+            do_check_false(a6.appDisabled);
+            do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE);
+
+            do_check_neq(a7, null);
+            do_check_false(a7.isActive);
+            do_check_true(a7.userDisabled);
+            do_check_false(a7.appDisabled);
+            do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE);
+
+            do_check_neq(t1, null);
+            do_check_false(t1.isActive);
+            do_check_true(t1.userDisabled);
+            do_check_false(t1.appDisabled);
+            do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE);
+            do_check_false(isThemeInAddonsList(profileDir, t1.id));
+
+            do_check_neq(t2, null);
+            do_check_true(t2.isActive);
+            do_check_false(t2.userDisabled);
+            do_check_false(t2.appDisabled);
+            do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE);
+            do_check_true(isThemeInAddonsList(profileDir, t2.id));
+
+            // After allowing access to the original DB things should go back to as
+            // they were previously
+            shutdownManager();
+            do_print("Unlocking " + gExtensionsJSON.path);
+            file.close();
+            gExtensionsJSON.permissions = filePermissions;
+            startupManager();
+
+
+            // Shouldn't have seen any startup changes
+            check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []);
+
+            AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+                                         "addon2@tests.mozilla.org",
+                                         "addon3@tests.mozilla.org",
+                                         "addon4@tests.mozilla.org",
+                                         "addon5@tests.mozilla.org",
+                                         "addon6@tests.mozilla.org",
+                                         "addon7@tests.mozilla.org",
+                                         "theme1@tests.mozilla.org",
+                                         "theme2@tests.mozilla.org"],
+                                         callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) {
+              do_check_neq(a1, null);
+              do_check_true(a1.isActive);
+              do_check_false(a1.userDisabled);
+              do_check_false(a1.appDisabled);
+              do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_true(isExtensionInAddonsList(profileDir, a1.id));
+
+              do_check_neq(a2, null);
+              do_check_false(a2.isActive);
+              do_check_true(a2.userDisabled);
+              do_check_false(a2.appDisabled);
+              do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_false(isExtensionInAddonsList(profileDir, a2.id));
+
+              do_check_neq(a3, null);
+              do_check_true(a3.isActive);
+              do_check_false(a3.userDisabled);
+              do_check_false(a3.appDisabled);
+              do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_true(isExtensionInAddonsList(profileDir, a3.id));
+
+              do_check_neq(a4, null);
+              do_check_false(a4.isActive);
+              do_check_true(a4.userDisabled);
+              do_check_false(a4.appDisabled);
+              do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_false(isExtensionInAddonsList(profileDir, a4.id));
+
+              do_check_neq(a5, null);
+              do_check_true(a5.isActive);
+              do_check_false(a5.userDisabled);
+              do_check_false(a5.appDisabled);
+              do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_true(isExtensionInAddonsList(profileDir, a5.id));
+
+              do_check_neq(a6, null);
+              do_check_true(a6.isActive);
+              do_check_false(a6.userDisabled);
+              do_check_false(a6.appDisabled);
+              do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE);
+
+              do_check_neq(a7, null);
+              do_check_false(a7.isActive);
+              do_check_true(a7.userDisabled);
+              do_check_false(a7.appDisabled);
+              do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE);
+
+              do_check_neq(t1, null);
+              do_check_false(t1.isActive);
+              do_check_true(t1.userDisabled);
+              do_check_false(t1.appDisabled);
+              do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_false(isThemeInAddonsList(profileDir, t1.id));
+
+              do_check_neq(t2, null);
+              do_check_true(t2.isActive);
+              do_check_false(t2.userDisabled);
+              do_check_false(t2.appDisabled);
+              do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_true(isThemeInAddonsList(profileDir, t2.id));
+
+              end_test();
+            }));
+          }));
         }));
-      }));
-    }));
+      },
+      do_report_unexpected_exception
+    );
   }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_locked2.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked2.js
@@ -1,15 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // Checks that we handle a locked database when there are extension changes
 // in progress
 
+Components.utils.import("resource://gre/modules/osfile.jsm");
+
 // Will be left alone
 var addon1 = {
   id: "addon1@tests.mozilla.org",
   version: "1.0",
   name: "Test 1",
   targetApplications: [{
     id: "xpcshell@tests.mozilla.org",
     minVersion: "2",
@@ -84,17 +86,17 @@ function run_test() {
   setExtensionModifiedTime(getFileForAddon(profileDir, addon5.id), Date.now() - (60000));
 
   // Startup the profile and setup the initial state
   startupManager();
 
   check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []);
   check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, []);
 
-  AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
+  AddonManager.getAddonByID("addon2@tests.mozilla.org", callback_soon(function(a2) {
     a2.userDisabled = true;
 
     restartManager();
 
     AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                  "addon2@tests.mozilla.org",
                                  "addon3@tests.mozilla.org",
                                  "addon4@tests.mozilla.org",
@@ -137,130 +139,157 @@ function run_test() {
         do_check_neq(a5, null);
         do_check_eq(a5.version, "1.0");
         do_check_true(a5.isActive);
         do_check_false(a5.userDisabled);
         do_check_false(a5.appDisabled);
         do_check_eq(a5.pendingOperations, AddonManager.PENDING_UPGRADE);
         do_check_true(isExtensionInAddonsList(profileDir, a5.id));
 
-        // After shutting down the database won't be open so we can lock it
+        // Open another handle on the JSON DB with as much Unix and Windows locking
+        // as we can to simulate some other process interfering with it
         shutdownManager();
-        var savedPermissions = gExtensionsJSON.permissions;
-        gExtensionsJSON.permissions = 0;
-
-        startupManager(false);
-
-        check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []);
-        check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, []);
+        do_print("Locking " + gExtensionsJSON.path);
+        let options = {
+          winShare: 0
+        };
+        if (OS.Constants.libc.O_EXLOCK)
+          options.unixFlags = OS.Constants.libc.O_EXLOCK;
 
-        AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
-                                     "addon2@tests.mozilla.org",
-                                     "addon3@tests.mozilla.org",
-                                     "addon4@tests.mozilla.org",
-                                     "addon5@tests.mozilla.org",
-                                     "addon6@tests.mozilla.org"],
-                                    function([a1, a2, a3, a4, a5, a6]) {
-          do_check_neq(a1, null);
-          do_check_true(a1.isActive);
-          do_check_false(a1.userDisabled);
-          do_check_false(a1.appDisabled);
-          do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE);
-          do_check_true(isExtensionInAddonsList(profileDir, a1.id));
+        OS.File.open(gExtensionsJSON.path, {read:true, write:true, existing:true}, options).then(
+          file => {
+            filePermissions = gExtensionsJSON.permissions;
+            if (!OS.Constants.Win) {
+              gExtensionsJSON.permissions = 0;
+            }
+            startupManager(false);
+
+            check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []);
+            check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, []);
 
-          do_check_neq(a2, null);
-          do_check_true(a2.isActive);
-          do_check_false(a2.userDisabled);
-          do_check_false(a2.appDisabled);
-          do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
-          do_check_true(isExtensionInAddonsList(profileDir, a2.id));
+            AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+                                         "addon2@tests.mozilla.org",
+                                         "addon3@tests.mozilla.org",
+                                         "addon4@tests.mozilla.org",
+                                         "addon5@tests.mozilla.org",
+                                         "addon6@tests.mozilla.org"],
+                                        callback_soon(function([a1, a2, a3, a4, a5, a6]) {
+              do_check_neq(a1, null);
+              do_check_true(a1.isActive);
+              do_check_false(a1.userDisabled);
+              do_check_false(a1.appDisabled);
+              do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_true(isExtensionInAddonsList(profileDir, a1.id));
 
-          do_check_neq(a3, null);
-          do_check_false(a3.isActive);
-          do_check_true(a3.userDisabled);
-          do_check_false(a3.appDisabled);
-          do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
-          do_check_false(isExtensionInAddonsList(profileDir, a3.id));
+              do_check_neq(a2, null);
+              do_check_true(a2.isActive);
+              do_check_false(a2.userDisabled);
+              do_check_false(a2.appDisabled);
+              do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_true(isExtensionInAddonsList(profileDir, a2.id));
 
-          do_check_eq(a4, null);
+              do_check_neq(a3, null);
+              do_check_false(a3.isActive);
+              do_check_true(a3.userDisabled);
+              do_check_false(a3.appDisabled);
+              do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_false(isExtensionInAddonsList(profileDir, a3.id));
+
+              do_check_eq(a4, null);
 
-          do_check_neq(a5, null);
-          do_check_eq(a5.version, "2.0");
-          do_check_true(a5.isActive);
-          do_check_false(a5.userDisabled);
-          do_check_false(a5.appDisabled);
-          do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
-          do_check_true(isExtensionInAddonsList(profileDir, a5.id));
+              do_check_neq(a5, null);
+              do_check_eq(a5.version, "2.0");
+              do_check_true(a5.isActive);
+              do_check_false(a5.userDisabled);
+              do_check_false(a5.appDisabled);
+              do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_true(isExtensionInAddonsList(profileDir, a5.id));
 
-          do_check_neq(a6, null);
-          do_check_true(a6.isActive);
-          do_check_false(a6.userDisabled);
-          do_check_false(a6.appDisabled);
-          do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE);
-          do_check_true(isExtensionInAddonsList(profileDir, a6.id));
+              do_check_neq(a6, null);
+              do_check_true(a6.isActive);
+              do_check_false(a6.userDisabled);
+              do_check_false(a6.appDisabled);
+              do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_true(isExtensionInAddonsList(profileDir, a6.id));
 
-          // After allowing access to the original DB things should still be
-          // applied correctly
-          shutdownManager();
-          gExtensionsJSON.permissions = savedPermissions;
-          startupManager();
-
-          // These things happened when we had no access to the database so
-          // they are seen as external changes when we get the database back :(
-          check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, ["addon6@tests.mozilla.org"]);
-          check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, ["addon4@tests.mozilla.org"]);
+              // After allowing access to the original DB things should still be
+              // back how they were before the lock
+              shutdownManager();
+              file.close();
+              gExtensionsJSON.permissions = filePermissions;
+              startupManager();
 
-          AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
-                                       "addon2@tests.mozilla.org",
-                                       "addon3@tests.mozilla.org",
-                                       "addon4@tests.mozilla.org",
-                                       "addon5@tests.mozilla.org",
-                                       "addon6@tests.mozilla.org"],
-                                      function([a1, a2, a3, a4, a5, a6]) {
-            do_check_neq(a1, null);
-            do_check_true(a1.isActive);
-            do_check_false(a1.userDisabled);
-            do_check_false(a1.appDisabled);
-            do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE);
-            do_check_true(isExtensionInAddonsList(profileDir, a1.id));
+              // On Unix, we can save the DB even when the original file wasn't
+              // readable, so our changes were saved. On Windows,
+              // these things happened when we had no access to the database so
+              // they are seen as external changes when we get the database back
+              if (gXPISaveError) {
+                do_print("Previous XPI save failed");
+                check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED,
+                    ["addon6@tests.mozilla.org"]);
+                check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED,
+                    ["addon4@tests.mozilla.org"]);
+              }
+              else {
+                do_print("Previous XPI save succeeded");
+                check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []);
+                check_startup_changes(AddonManager.STARTUP_CHANGE_UNINSTALLED, []);
+              }
+
+              AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+                                           "addon2@tests.mozilla.org",
+                                           "addon3@tests.mozilla.org",
+                                           "addon4@tests.mozilla.org",
+                                           "addon5@tests.mozilla.org",
+                                           "addon6@tests.mozilla.org"],
+                                          function([a1, a2, a3, a4, a5, a6]) {
+                do_check_neq(a1, null);
+                do_check_true(a1.isActive);
+                do_check_false(a1.userDisabled);
+                do_check_false(a1.appDisabled);
+                do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE);
+                do_check_true(isExtensionInAddonsList(profileDir, a1.id));
 
-            do_check_neq(a2, null);
-            do_check_true(a2.isActive);
-            do_check_false(a2.userDisabled);
-            do_check_false(a2.appDisabled);
-            do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
-            do_check_true(isExtensionInAddonsList(profileDir, a2.id));
+                do_check_neq(a2, null);
+                do_check_true(a2.isActive);
+                do_check_false(a2.userDisabled);
+                do_check_false(a2.appDisabled);
+                do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
+                do_check_true(isExtensionInAddonsList(profileDir, a2.id));
 
-            do_check_neq(a3, null);
-            do_check_false(a3.isActive);
-            do_check_true(a3.userDisabled);
-            do_check_false(a3.appDisabled);
-            do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
-            do_check_false(isExtensionInAddonsList(profileDir, a3.id));
+                do_check_neq(a3, null);
+                do_check_false(a3.isActive);
+                do_check_true(a3.userDisabled);
+                do_check_false(a3.appDisabled);
+                do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
+                do_check_false(isExtensionInAddonsList(profileDir, a3.id));
 
-            do_check_eq(a4, null);
+                do_check_eq(a4, null);
 
-            do_check_neq(a5, null);
-            do_check_eq(a5.version, "2.0");
-            do_check_true(a5.isActive);
-            do_check_false(a5.userDisabled);
-            do_check_false(a5.appDisabled);
-            do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
-            do_check_true(isExtensionInAddonsList(profileDir, a5.id));
+                do_check_neq(a5, null);
+                do_check_eq(a5.version, "2.0");
+                do_check_true(a5.isActive);
+                do_check_false(a5.userDisabled);
+                do_check_false(a5.appDisabled);
+                do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
+                do_check_true(isExtensionInAddonsList(profileDir, a5.id));
 
-            do_check_neq(a6, null);
-            do_check_true(a6.isActive);
-            do_check_false(a6.userDisabled);
-            do_check_false(a6.appDisabled);
-            do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE);
-            do_check_true(isExtensionInAddonsList(profileDir, a6.id));
+                do_check_neq(a6, null);
+                do_check_true(a6.isActive);
+                do_check_false(a6.userDisabled);
+                do_check_false(a6.appDisabled);
+                do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE);
+                do_check_true(isExtensionInAddonsList(profileDir, a6.id));
 
-            end_test();
-          });
-        });
+                end_test();
+              });
+            }));
+          },
+          do_report_unexpected_exception
+          );
       });
     });
-  });
+  }));
 }
 
 function end_test() {
-  do_test_finished();
+  do_execute_soon(do_test_finished);
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js
@@ -1,16 +1,17 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // Checks that we rebuild something sensible from a corrupt database
 
+Components.utils.import("resource://testing-common/httpd.js");
+Components.utils.import("resource://gre/modules/osfile.jsm");
 
-Components.utils.import("resource://testing-common/httpd.js");
 var testserver = new HttpServer();
 testserver.start(-1);
 gPort = testserver.identity.primaryPort;
 mapFile("/data/test_corrupt.rdf", testserver);
 testserver.registerDirectory("/addons/", do_get_file("addons"));
 
 // The test extension uses an insecure update url.
 Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
@@ -249,229 +250,79 @@ function run_test_1() {
 
     do_check_neq(t2, null);
     do_check_true(t2.isActive);
     do_check_false(t2.userDisabled);
     do_check_false(t2.appDisabled);
     do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE);
     do_check_true(isThemeInAddonsList(profileDir, t2.id));
 
-    // After shutting down the database won't be open so we can lock it
+    // Open another handle on the JSON DB with as much Unix and Windows locking
+    // as we can to simulate some other process interfering with it
     shutdownManager();
-    var savedPermissions = gExtensionsJSON.permissions;
-    gExtensionsJSON.permissions = 0;
-
-    startupManager(false);
-
-    // Shouldn't have seen any startup changes
-    check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []);
-
-    // Accessing the add-ons should open and recover the database
-    AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
-                                 "addon2@tests.mozilla.org",
-                                 "addon3@tests.mozilla.org",
-                                 "addon4@tests.mozilla.org",
-                                 "addon5@tests.mozilla.org",
-                                 "addon6@tests.mozilla.org",
-                                 "addon7@tests.mozilla.org",
-                                 "theme1@tests.mozilla.org",
-                                 "theme2@tests.mozilla.org"],
-                                 callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) {
-      // Should be correctly recovered
-      do_check_neq(a1, null);
-      do_check_true(a1.isActive);
-      do_check_false(a1.userDisabled);
-      do_check_false(a1.appDisabled);
-      do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE);
-      do_check_true(isExtensionInAddonsList(profileDir, a1.id));
-
-      // Should be correctly recovered
-      do_check_neq(a2, null);
-      do_check_false(a2.isActive);
-      do_check_true(a2.userDisabled);
-      do_check_false(a2.appDisabled);
-      do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
-      do_check_false(isExtensionInAddonsList(profileDir, a2.id));
-
-      // The compatibility update won't be recovered but it should still be
-      // active for this session
-      do_check_neq(a3, null);
-      do_check_true(a3.isActive);
-      do_check_false(a3.userDisabled);
-      do_check_true(a3.appDisabled);
-      do_check_eq(a3.pendingOperations, AddonManager.PENDING_DISABLE);
-      do_check_true(isExtensionInAddonsList(profileDir, a3.id));
-
-      // The compatibility update won't be recovered and it will not have been
-      // able to tell that it was previously userDisabled
-      do_check_neq(a4, null);
-      do_check_false(a4.isActive);
-      do_check_false(a4.userDisabled);
-      do_check_true(a4.appDisabled);
-      do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE);
-      do_check_false(isExtensionInAddonsList(profileDir, a4.id));
-
-      do_check_neq(a5, null);
-      do_check_false(a5.isActive);
-      do_check_false(a5.userDisabled);
-      do_check_true(a5.appDisabled);
-      do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
-      do_check_false(isExtensionInAddonsList(profileDir, a5.id));
-
-      do_check_neq(a6, null);
-      do_check_true(a6.isActive);
-      do_check_false(a6.userDisabled);
-      do_check_false(a6.appDisabled);
-      do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE);
-
-      do_check_neq(a7, null);
-      do_check_false(a7.isActive);
-      do_check_true(a7.userDisabled);
-      do_check_false(a7.appDisabled);
-      do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE);
-
-      // Should be correctly recovered
-      do_check_neq(t1, null);
-      do_check_false(t1.isActive);
-      do_check_true(t1.userDisabled);
-      do_check_false(t1.appDisabled);
-      do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE);
-      do_check_false(isThemeInAddonsList(profileDir, t1.id));
+    do_print("Locking " + gExtensionsJSON.path);
+    let options = {
+      winShare: 0
+    };
+    if (OS.Constants.libc.O_EXLOCK)
+      options.unixFlags = OS.Constants.libc.O_EXLOCK;
 
-      // Should be correctly recovered
-      do_check_neq(t2, null);
-      do_check_true(t2.isActive);
-      do_check_false(t2.userDisabled);
-      do_check_false(t2.appDisabled);
-      do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE);
-      do_check_true(isThemeInAddonsList(profileDir, t2.id));
-
-      // Restarting will actually apply changes to extensions.ini which will
-      // then be put into the in-memory database when we next fail to load the
-      // real thing
-      restartManager();
-
-      // Shouldn't have seen any startup changes
-      check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []);
-
-      AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
-                                   "addon2@tests.mozilla.org",
-                                   "addon3@tests.mozilla.org",
-                                   "addon4@tests.mozilla.org",
-                                   "addon5@tests.mozilla.org",
-                                   "addon6@tests.mozilla.org",
-                                   "addon7@tests.mozilla.org",
-                                   "theme1@tests.mozilla.org",
-                                   "theme2@tests.mozilla.org"],
-                                   callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) {
-        do_check_neq(a1, null);
-        do_check_true(a1.isActive);
-        do_check_false(a1.userDisabled);
-        do_check_false(a1.appDisabled);
-        do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE);
-        do_check_true(isExtensionInAddonsList(profileDir, a1.id));
-
-        do_check_neq(a2, null);
-        do_check_false(a2.isActive);
-        do_check_true(a2.userDisabled);
-        do_check_false(a2.appDisabled);
-        do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
-        do_check_false(isExtensionInAddonsList(profileDir, a2.id));
-
-        do_check_neq(a3, null);
-        do_check_false(a3.isActive);
-        do_check_false(a3.userDisabled);
-        do_check_true(a3.appDisabled);
-        do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
-        do_check_false(isExtensionInAddonsList(profileDir, a3.id));
-
-        do_check_neq(a4, null);
-        do_check_false(a4.isActive);
-        do_check_false(a4.userDisabled);
-        do_check_true(a4.appDisabled);
-        do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE);
-        do_check_false(isExtensionInAddonsList(profileDir, a4.id));
-
-        do_check_neq(a5, null);
-        do_check_false(a5.isActive);
-        do_check_false(a5.userDisabled);
-        do_check_true(a5.appDisabled);
-        do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
-        do_check_false(isExtensionInAddonsList(profileDir, a5.id));
-
-        do_check_neq(a6, null);
-        do_check_true(a6.isActive);
-        do_check_false(a6.userDisabled);
-        do_check_false(a6.appDisabled);
-        do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE);
-
-        do_check_neq(a7, null);
-        do_check_false(a7.isActive);
-        do_check_true(a7.userDisabled);
-        do_check_false(a7.appDisabled);
-        do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE);
-
-        do_check_neq(t1, null);
-        do_check_false(t1.isActive);
-        do_check_true(t1.userDisabled);
-        do_check_false(t1.appDisabled);
-        do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE);
-        do_check_false(isThemeInAddonsList(profileDir, t1.id));
-
-        do_check_neq(t2, null);
-        do_check_true(t2.isActive);
-        do_check_false(t2.userDisabled);
-        do_check_false(t2.appDisabled);
-        do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE);
-        do_check_true(isThemeInAddonsList(profileDir, t2.id));
-
-        // After allowing access to the original DB things should go back to as
-        // they were previously
-        shutdownManager();
-        gExtensionsJSON.permissions = savedPermissions;
+    OS.File.open(gExtensionsJSON.path, {read:true, write:true, existing:true}, options).then(
+      file => {
+        filePermissions = gExtensionsJSON.permissions;
+        if (!OS.Constants.Win) {
+          gExtensionsJSON.permissions = 0;
+        }
         startupManager(false);
 
         // Shouldn't have seen any startup changes
         check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []);
 
+        // Accessing the add-ons should open and recover the database
         AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                      "addon2@tests.mozilla.org",
                                      "addon3@tests.mozilla.org",
                                      "addon4@tests.mozilla.org",
                                      "addon5@tests.mozilla.org",
                                      "addon6@tests.mozilla.org",
                                      "addon7@tests.mozilla.org",
                                      "theme1@tests.mozilla.org",
                                      "theme2@tests.mozilla.org"],
                                      callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) {
+          // Should be correctly recovered
           do_check_neq(a1, null);
           do_check_true(a1.isActive);
           do_check_false(a1.userDisabled);
           do_check_false(a1.appDisabled);
           do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE);
           do_check_true(isExtensionInAddonsList(profileDir, a1.id));
 
+          // Should be correctly recovered
           do_check_neq(a2, null);
           do_check_false(a2.isActive);
           do_check_true(a2.userDisabled);
           do_check_false(a2.appDisabled);
           do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
           do_check_false(isExtensionInAddonsList(profileDir, a2.id));
 
+          // The compatibility update won't be recovered but it should still be
+          // active for this session
           do_check_neq(a3, null);
           do_check_true(a3.isActive);
           do_check_false(a3.userDisabled);
-          do_check_false(a3.appDisabled);
-          do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
+          do_check_true(a3.appDisabled);
+          do_check_eq(a3.pendingOperations, AddonManager.PENDING_DISABLE);
           do_check_true(isExtensionInAddonsList(profileDir, a3.id));
 
+          // The compatibility update won't be recovered and it will not have been
+          // able to tell that it was previously userDisabled
           do_check_neq(a4, null);
           do_check_false(a4.isActive);
-          do_check_true(a4.userDisabled);
-          do_check_false(a4.appDisabled);
+          do_check_false(a4.userDisabled);
+          do_check_true(a4.appDisabled);
           do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE);
           do_check_false(isExtensionInAddonsList(profileDir, a4.id));
 
           do_check_neq(a5, null);
           do_check_false(a5.isActive);
           do_check_false(a5.userDisabled);
           do_check_true(a5.appDisabled);
           do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
@@ -484,28 +335,216 @@ function run_test_1() {
           do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE);
 
           do_check_neq(a7, null);
           do_check_false(a7.isActive);
           do_check_true(a7.userDisabled);
           do_check_false(a7.appDisabled);
           do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE);
 
+          // Should be correctly recovered
           do_check_neq(t1, null);
           do_check_false(t1.isActive);
           do_check_true(t1.userDisabled);
           do_check_false(t1.appDisabled);
           do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE);
           do_check_false(isThemeInAddonsList(profileDir, t1.id));
 
+          // Should be correctly recovered
           do_check_neq(t2, null);
           do_check_true(t2.isActive);
           do_check_false(t2.userDisabled);
           do_check_false(t2.appDisabled);
           do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE);
           do_check_true(isThemeInAddonsList(profileDir, t2.id));
 
-          end_test();
+          // Restarting will actually apply changes to extensions.ini which will
+          // then be put into the in-memory database when we next fail to load the
+          // real thing
+          restartManager();
+
+          // Shouldn't have seen any startup changes
+          check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []);
+
+          AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+                                       "addon2@tests.mozilla.org",
+                                       "addon3@tests.mozilla.org",
+                                       "addon4@tests.mozilla.org",
+                                       "addon5@tests.mozilla.org",
+                                       "addon6@tests.mozilla.org",
+                                       "addon7@tests.mozilla.org",
+                                       "theme1@tests.mozilla.org",
+                                       "theme2@tests.mozilla.org"],
+                                       callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) {
+            do_check_neq(a1, null);
+            do_check_true(a1.isActive);
+            do_check_false(a1.userDisabled);
+            do_check_false(a1.appDisabled);
+            do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE);
+            do_check_true(isExtensionInAddonsList(profileDir, a1.id));
+
+            do_check_neq(a2, null);
+            do_check_false(a2.isActive);
+            do_check_true(a2.userDisabled);
+            do_check_false(a2.appDisabled);
+            do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
+            do_check_false(isExtensionInAddonsList(profileDir, a2.id));
+
+            do_check_neq(a3, null);
+            do_check_false(a3.isActive);
+            do_check_false(a3.userDisabled);
+            do_check_true(a3.appDisabled);
+            do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
+            do_check_false(isExtensionInAddonsList(profileDir, a3.id));
+
+            do_check_neq(a4, null);
+            do_check_false(a4.isActive);
+            do_check_false(a4.userDisabled);
+            do_check_true(a4.appDisabled);
+            do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE);
+            do_check_false(isExtensionInAddonsList(profileDir, a4.id));
+
+            do_check_neq(a5, null);
+            do_check_false(a5.isActive);
+            do_check_false(a5.userDisabled);
+            do_check_true(a5.appDisabled);
+            do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
+            do_check_false(isExtensionInAddonsList(profileDir, a5.id));
+
+            do_check_neq(a6, null);
+            do_check_true(a6.isActive);
+            do_check_false(a6.userDisabled);
+            do_check_false(a6.appDisabled);
+            do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE);
+
+            do_check_neq(a7, null);
+            do_check_false(a7.isActive);
+            do_check_true(a7.userDisabled);
+            do_check_false(a7.appDisabled);
+            do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE);
+
+            do_check_neq(t1, null);
+            do_check_false(t1.isActive);
+            do_check_true(t1.userDisabled);
+            do_check_false(t1.appDisabled);
+            do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE);
+            do_check_false(isThemeInAddonsList(profileDir, t1.id));
+
+            do_check_neq(t2, null);
+            do_check_true(t2.isActive);
+            do_check_false(t2.userDisabled);
+            do_check_false(t2.appDisabled);
+            do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE);
+            do_check_true(isThemeInAddonsList(profileDir, t2.id));
+
+            // After allowing access to the original DB things should go back to as
+            // back how they were before the lock
+            shutdownManager();
+            do_print("Unlocking " + gExtensionsJSON.path);
+            file.close();
+            gExtensionsJSON.permissions = filePermissions;
+            startupManager(false);
+
+            // Shouldn't have seen any startup changes
+            check_startup_changes(AddonManager.STARTUP_CHANGE_INSTALLED, []);
+
+            AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+                                         "addon2@tests.mozilla.org",
+                                         "addon3@tests.mozilla.org",
+                                         "addon4@tests.mozilla.org",
+                                         "addon5@tests.mozilla.org",
+                                         "addon6@tests.mozilla.org",
+                                         "addon7@tests.mozilla.org",
+                                         "theme1@tests.mozilla.org",
+                                         "theme2@tests.mozilla.org"],
+                                         callback_soon(function([a1, a2, a3, a4, a5, a6, a7, t1, t2]) {
+              do_check_neq(a1, null);
+              do_check_true(a1.isActive);
+              do_check_false(a1.userDisabled);
+              do_check_false(a1.appDisabled);
+              do_check_eq(a1.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_true(isExtensionInAddonsList(profileDir, a1.id));
+
+              do_check_neq(a2, null);
+              do_check_false(a2.isActive);
+              do_check_true(a2.userDisabled);
+              do_check_false(a2.appDisabled);
+              do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_false(isExtensionInAddonsList(profileDir, a2.id));
+
+              do_check_neq(a3, null);
+              do_check_false(a3.userDisabled);
+              // On Unix, we may be able to save our changes over the locked DB so we
+              // remember that this extension was changed to disabled. On Windows we
+              // couldn't replace the old DB so we read the older version of the DB
+              // where the extension is enabled
+              if (gXPISaveError) {
+                do_print("XPI save failed");
+                do_check_true(a3.isActive);
+                do_check_false(a3.appDisabled);
+                do_check_true(isExtensionInAddonsList(profileDir, a3.id));
+              }
+              else {
+                do_print("XPI save succeeded");
+                do_check_false(a3.isActive);
+                do_check_true(a3.appDisabled);
+                do_check_false(isExtensionInAddonsList(profileDir, a3.id));
+              }
+              do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
+
+              do_check_neq(a4, null);
+              do_check_false(a4.isActive);
+              // The reverse of the platform difference for a3 - Unix should
+              // stay the same as the last iteration because the save succeeded,
+              // Windows should still say userDisabled
+              if (OS.Constants.Win) {
+                do_check_true(a4.userDisabled);
+                do_check_false(a4.appDisabled);
+              }
+              else {
+                do_check_false(a4.userDisabled);
+                do_check_true(a4.appDisabled);
+              }
+              do_check_false(isExtensionInAddonsList(profileDir, a4.id));
+              do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE);
+
+              do_check_neq(a5, null);
+              do_check_false(a5.isActive);
+              do_check_false(a5.userDisabled);
+              do_check_true(a5.appDisabled);
+              do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_false(isExtensionInAddonsList(profileDir, a5.id));
+
+              do_check_neq(a6, null);
+              do_check_true(a6.isActive);
+              do_check_false(a6.userDisabled);
+              do_check_false(a6.appDisabled);
+              do_check_eq(a6.pendingOperations, AddonManager.PENDING_NONE);
+
+              do_check_neq(a7, null);
+              do_check_false(a7.isActive);
+              do_check_true(a7.userDisabled);
+              do_check_false(a7.appDisabled);
+              do_check_eq(a7.pendingOperations, AddonManager.PENDING_NONE);
+
+              do_check_neq(t1, null);
+              do_check_false(t1.isActive);
+              do_check_true(t1.userDisabled);
+              do_check_false(t1.appDisabled);
+              do_check_eq(t1.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_false(isThemeInAddonsList(profileDir, t1.id));
+
+              do_check_neq(t2, null);
+              do_check_true(t2.isActive);
+              do_check_false(t2.userDisabled);
+              do_check_false(t2.appDisabled);
+              do_check_eq(t2.pendingOperations, AddonManager.PENDING_NONE);
+              do_check_true(isThemeInAddonsList(profileDir, t2.id));
+
+              end_test();
+            }));
+          }));
         }));
-      }));
-    }));
+      },
+      do_report_unexpected_exception
+    );
   }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_manifest.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_manifest.js
@@ -552,11 +552,11 @@ function run_test() {
     do_check_neq(a25, null);
     do_check_eq(a25.optionsType, null);
     do_check_eq(a25.optionsURL, null);
 
     do_check_neq(a26, null);
     do_check_eq(a26.optionsType, AddonManager.OPTIONS_TYPE_INLINE_INFO);
     do_check_neq(a26.optionsURL, null);
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_mapURIToAddonID.js
@@ -135,17 +135,17 @@ function run_test_2(uri) {
 
     b1.userDisabled = true;
     ensure_test_completed();
 
     AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(newb1) {
       do_check_true(newb1.userDisabled);
       check_mapping(uri, newb1.id);
 
-      run_test_3(uri);
+      do_execute_soon(() => run_test_3(uri));
     });
   });
 }
 
 // Tests that add-on URIs aren't mappable if the add-on was never started in a
 // session
 function run_test_3(uri) {
   restartManager();
@@ -169,30 +169,30 @@ function run_test_4() {
 
     b1.userDisabled = false;
     ensure_test_completed();
 
     AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(newb1) {
       let uri = newb1.getResourceURI(".");
       check_mapping(uri, newb1.id);
 
-      run_test_5();
+      do_execute_soon(run_test_5);
     });
   });
 }
 
 // Tests that add-on URIs are mappable after a restart
 function run_test_5() {
   restartManager();
 
   AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
     let uri = b1.getResourceURI(".");
     check_mapping(uri, b1.id);
 
-    run_test_invalidarg();
+    do_execute_soon(run_test_invalidarg);
   });
 }
 
 // Tests that the AddonManager will bail when mapURIToAddonID is called with an
 // invalid argument
 function run_test_invalidarg() {
   restartManager();
 
--- a/toolkit/mozapps/extensions/test/xpcshell/test_migrate1.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate1.js
@@ -241,11 +241,11 @@ function run_test() {
     do_check_true(t2.userDisabled);
     do_check_false(t2.appDisabled);
     do_check_false(t2.isActive);
     do_check_false(isThemeInAddonsList(profileDir, t2.id));
     do_check_true(hasFlag(t2.permissions, AddonManager.PERM_CAN_ENABLE));
 
     do_check_false(stagedXPIs.exists());
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_migrate2.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate2.js
@@ -249,11 +249,11 @@ function run_test() {
     // addon8 is in the user install location so should be a foreignInstall
     do_check_neq(a8, null);
     do_check_false(a8.userDisabled);
     do_check_false(a8.appDisabled);
     do_check_true(a8.isActive);
     do_check_false(a8.strictCompatibility);
     do_check_true(a8.foreignInstall);
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_migrate3.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate3.js
@@ -229,11 +229,11 @@ function run_test() {
     do_check_true(t2.userDisabled);
     do_check_false(t2.appDisabled);
     do_check_false(t2.isActive);
     do_check_false(isThemeInAddonsList(profileDir, t2.id));
     do_check_true(hasFlag(t2.permissions, AddonManager.PERM_CAN_ENABLE));
 
     do_check_false(stagedXPIs.exists());
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_migrate5.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_migrate5.js
@@ -129,11 +129,11 @@ function run_test() {
     do_check_false(t1.appDisabled);
     do_check_true(t1.isActive);
 
     do_check_neq(d, null);
     do_check_true(d.userDisabled);
     do_check_false(d.appDisabled);
     do_check_false(d.isActive);
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_onPropertyChanged_appDisabled.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_onPropertyChanged_appDisabled.js
@@ -54,13 +54,13 @@ function run_test_2() {
     do_check_true(aAddon.userDisabled);
     do_check_false(aAddon.isActive);
     do_check_true(aAddon.appDisabled);
 
     prepare_test({
       "addon1@tests.mozilla.org": [
         ["onPropertyChanged", ["appDisabled"]]
       ]
-    }, [], do_test_finished);
+    }, [], callback_soon(do_test_finished));
 
     AddonManager.strictCompatibility = false;
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_pluginchange.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_pluginchange.js
@@ -70,17 +70,17 @@ function run_test() {
   startupManager();
   AddonManager.addAddonListener(AddonListener);
   AddonManager.addInstallListener(InstallListener);
 
   run_test_1();
 }
 
 function end_test() {
-  do_test_finished();
+  do_execute_soon(do_test_finished);
 }
 
 function sortAddons(addons) {
   addons.sort(function(a, b) {
     return a.name.localeCompare(b.name);
   });
 }
 
--- a/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_plugins.js
@@ -168,11 +168,11 @@ function run_test_4() {
   restartManager();
 
   AddonManager.getAddonByID(gID, function(p) {
     do_check_neq(p, null);
     do_check_eq(p.name, "Test Plug-in");
 
     Services.prefs.clearUserPref("plugins.click_to_play");
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_registry.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_registry.js
@@ -141,11 +141,11 @@ function run_test_4() {
 
   restartManager();
 
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                "addon2@tests.mozilla.org"], function([a1, a2]) {
     do_check_eq(a1, null);
     do_check_neq(a2, null);
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_safemode.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_safemode.js
@@ -28,17 +28,17 @@ var gIconURL = null;
 // Sets up the profile by installing an add-on.
 function run_test() {
   do_test_pending();
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
   gAppInfo.inSafeMode = true;
 
   startupManager();
 
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
     do_check_eq(a1, null);
     do_check_not_in_crash_annotation(addon1.id, addon1.version);
 
     writeInstallRDFForExtension(addon1, profileDir, addon1.id, "icon.png");
     gIconURL = do_get_addon_root_uri(profileDir.clone(), addon1.id) + "icon.png";
 
     restartManager();
 
@@ -52,17 +52,17 @@ function run_test() {
       do_check_true(isExtensionInAddonsList(profileDir, newa1.id));
       do_check_true(hasFlag(newa1.permissions, AddonManager.PERM_CAN_DISABLE));
       do_check_false(hasFlag(newa1.permissions, AddonManager.PERM_CAN_ENABLE));
       do_check_eq(newa1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_NONE);
       do_check_not_in_crash_annotation(addon1.id, addon1.version);
 
       run_test_1();
     });
-  });
+  }));
 }
 
 // Disabling an add-on should work
 function run_test_1() {
   prepare_test({
     "addon1@tests.mozilla.org": [
       ["onDisabling", false],
       "onDisabled"
@@ -105,11 +105,11 @@ function run_test_2() {
     do_check_eq(a1.iconURL, gIconURL);
     do_check_true(hasFlag(a1.permissions, AddonManager.PERM_CAN_DISABLE));
     do_check_false(hasFlag(a1.permissions, AddonManager.PERM_CAN_ENABLE));
     do_check_eq(a1.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_NONE);
     do_check_not_in_crash_annotation(addon1.id, addon1.version);
 
     ensure_test_completed();
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_startup.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_startup.js
@@ -823,17 +823,17 @@ function run_test_12() {
 
   restartManager();
 
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                "addon2@tests.mozilla.org",
                                "addon3@tests.mozilla.org",
                                "addon4@tests.mozilla.org",
                                "addon5@tests.mozilla.org"],
-                               function([a1, a2, a3, a4, a5]) {
+                               callback_soon(function([a1, a2, a3, a4, a5]) {
     do_check_neq(a1, null);
     do_check_false(a1.userDisabled);
     do_check_true(a1.isActive);
 
     do_check_neq(a2, null);
     do_check_true(a2.userDisabled);
     do_check_false(a2.isActive);
 
@@ -912,13 +912,13 @@ function run_test_12() {
         do_check_neq(a2, null);
         do_check_true(a2.userDisabled);
         do_check_false(a2.isActive);
 
         do_check_neq(a3, null);
         do_check_true(a3.userDisabled);
         do_check_false(a3.isActive);
 
-        end_test();
+        do_execute_soon(end_test);
       });
     });
-  });
+  }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_syncGUID.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_syncGUID.js
@@ -81,33 +81,33 @@ add_test(function test_error_on_duplicat
     onInstallEnded: function onInstallEnded() {
       installCount++;
 
       if (installCount == installNames.length) {
        AddonManager.removeInstallListener(listener);
        do_execute_soon(function duplicate_syncguid_install_ended() {
         restartManager();
 
-        AddonManager.getAddonsByIDs(installIDs, function(addons) {
+        AddonManager.getAddonsByIDs(installIDs, callback_soon(function(addons) {
           let initialGUID = addons[1].syncGUID;
 
           try {
             addons[1].syncGUID = addons[0].syncGUID;
             do_throw("Should not get here.");
           }
           catch (e) {
             do_check_true(e.message.startsWith("Addon sync GUID conflict"));
             restartManager();
 
             AddonManager.getAddonByID(installIDs[1], function(addon) {
               do_check_eq(initialGUID, addon.syncGUID);
               run_next_test();
             });
           }
-        });
+        }));
        });
       }
     }
   };
 
   AddonManager.addInstallListener(listener);
   let getInstallCB = function(install) { install.install(); };
 
--- a/toolkit/mozapps/extensions/test/xpcshell/test_targetPlatforms.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_targetPlatforms.js
@@ -136,11 +136,11 @@ function run_test() {
 
     do_check_neq(a5, null);
     do_check_true(a5.appDisabled);
     do_check_false(a5.isPlatformCompatible);
     do_check_false(a5.isActive);
     do_check_false(isExtensionInAddonsList(profileDir, a5.id));
     do_check_not_in_crash_annotation(addon5.id, addon5.version);
 
-    do_test_finished();
+    do_execute_soon(do_test_finished);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_theme.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_theme.js
@@ -121,17 +121,17 @@ function run_test() {
     do_check_true(hasFlag(t2.permissions, AddonManager.PERM_CAN_ENABLE));
     do_check_eq(t2.operationsRequiringRestart, AddonManager.OP_NEEDS_RESTART_ENABLE);
 
     do_execute_soon(run_test_1);
   });
 }
 
 function end_test() {
-  do_test_finished();
+  do_execute_soon(do_test_finished);
 }
 
 // Checks enabling one theme disables the others
 function run_test_1() {
   prepare_test({
     "theme1@tests.mozilla.org": [
       "onDisabling"
     ],
@@ -608,17 +608,17 @@ function run_test_9() {
 
       do_execute_soon(run_test_10);
     });
   });
 }
 
 // Uninstalling a custom theme in use should require a restart
 function run_test_10() {
-  AddonManager.getAddonByID("theme2@tests.mozilla.org", function(oldt2) {
+  AddonManager.getAddonByID("theme2@tests.mozilla.org", callback_soon(function(oldt2) {
     prepare_test({
       "theme2@tests.mozilla.org": [
         "onEnabling",
       ],
       "default@tests.mozilla.org": [
         "onDisabling"
       ]
     });
@@ -649,17 +649,17 @@ function run_test_10() {
 
       t2.uninstall();
 
       ensure_test_completed();
       do_check_false(gLWThemeChanged);
 
       do_execute_soon(run_test_11);
     });
-  });
+  }));
 }
 
 // Installing a custom theme not in use should not require a restart
 function run_test_11() {
   restartManager();
 
   prepare_test({ }, [
     "onNewInstall"
@@ -737,17 +737,17 @@ function check_test_12() {
     do_check_false(gLWThemeChanged);
 
     do_execute_soon(run_test_13);
   });
 }
 
 // Updating a custom theme in use should require a restart
 function run_test_13() {
-  AddonManager.getAddonByID("theme1@tests.mozilla.org", function(t1) {
+  AddonManager.getAddonByID("theme1@tests.mozilla.org", callback_soon(function(t1) {
     prepare_test({
       "theme1@tests.mozilla.org": [
         "onEnabling",
       ],
       "default@tests.mozilla.org": [
         "onDisabling"
       ]
     });
@@ -772,34 +772,34 @@ function run_test_13() {
 
       prepare_test({
         "theme1@tests.mozilla.org": [
           "onInstalling",
         ]
       }, [
         "onInstallStarted",
         "onInstallEnded",
-      ], check_test_13);
+      ], callback_soon(check_test_13));
       install.install();
     });
-  });
+  }));
 }
 
 function check_test_13() {
   restartManager();
 
-  AddonManager.getAddonByID("theme1@tests.mozilla.org", function(t1) {
+  AddonManager.getAddonByID("theme1@tests.mozilla.org", callback_soon(function(t1) {
     do_check_neq(t1, null);
     do_check_true(t1.isActive);
     do_check_false(gLWThemeChanged);
     t1.uninstall();
     restartManager();
 
     do_execute_soon(run_test_14);
-  });
+  }));
 }
 
 // Switching from a lightweight theme to the default theme should not require
 // a restart
 function run_test_14() {
   LightweightThemeManager.currentTheme = {
     id: "1",
     version: "1",
@@ -841,24 +841,25 @@ function run_test_14() {
   });
 }
 
 // Upgrading the application with a custom theme in use should not disable it
 function run_test_15() {
   restartManager();
 
   installAllFiles([do_get_addon("test_theme")], function() {
-    AddonManager.getAddonByID("theme1@tests.mozilla.org", function(t1) {
+    AddonManager.getAddonByID("theme1@tests.mozilla.org", callback_soon(function(t1) {
       t1.userDisabled = false;
 
       restartManager();
 
       do_check_eq(Services.prefs.getCharPref(PREF_GENERAL_SKINS_SELECTEDSKIN), "theme1/1.0");
       AddonManager.getAddonsByIDs(["default@tests.mozilla.org",
-                                   "theme1@tests.mozilla.org"], function([d, t1]) {
+                                   "theme1@tests.mozilla.org"],
+                                   callback_soon(function([d, t1]) {
         do_check_true(d.userDisabled);
         do_check_false(d.appDisabled);
         do_check_false(d.isActive);
 
         do_check_false(t1.userDisabled);
         do_check_false(t1.appDisabled);
         do_check_true(t1.isActive);
 
@@ -872,18 +873,18 @@ function run_test_15() {
           do_check_false(d.isActive);
 
           do_check_false(t1.userDisabled);
           do_check_false(t1.appDisabled);
           do_check_true(t1.isActive);
 
           do_execute_soon(run_test_16);
         });
-      });
-    });
+      }));
+    }));
   });
 }
 
 // Upgrading the application with a custom theme in use should disable it if it
 // is no longer compatible
 function run_test_16() {
   restartManager("3");
 
@@ -927,23 +928,24 @@ function run_test_17() {
     do_execute_soon(run_test_18);
   });
 }
 
 // Disabling the active theme should switch back to the default theme
 function run_test_18() {
   restartManager(2);
 
-  AddonManager.getAddonByID("theme1@tests.mozilla.org", function(t1) {
+  AddonManager.getAddonByID("theme1@tests.mozilla.org", callback_soon(function(t1) {
     t1.userDisabled = false;
 
     restartManager();
 
     AddonManager.getAddonsByIDs(["default@tests.mozilla.org",
-                                 "theme1@tests.mozilla.org"], function([d, t1]) {
+                                 "theme1@tests.mozilla.org"],
+                                 callback_soon(function([d, t1]) {
       do_check_true(d.userDisabled);
       do_check_false(d.appDisabled);
       do_check_false(d.isActive);
 
       do_check_false(t1.userDisabled);
       do_check_false(t1.appDisabled);
       do_check_true(t1.isActive);
 
@@ -975,18 +977,18 @@ function run_test_18() {
         do_check_true(d.isActive);
 
         do_check_true(t1.userDisabled);
         do_check_false(t1.appDisabled);
         do_check_false(t1.isActive);
 
         do_execute_soon(run_test_19);
       });
-    });
-  });
+    }));
+  }));
 }
 
 // Disabling the active persona should switch back to the default theme
 function run_test_19() {
   AddonManager.getAddonsByIDs(["default@tests.mozilla.org",
                                "1@personas.mozilla.org"], function([d, p1]) {
     p1.userDisabled = false;
 
@@ -1039,17 +1041,17 @@ function run_test_20() {
 
     do_execute_soon(run_test_21);
   });
 }
 
 // Tests that cached copies of a lightweight theme have the right permissions
 // and pendingOperations during the onEnabling event
 function run_test_21() {
-  AddonManager.getAddonByID("theme1@tests.mozilla.org", function(t1) {
+  AddonManager.getAddonByID("theme1@tests.mozilla.org", callback_soon(function(t1) {
     // Switch to a custom theme so we can test pendingOperations properly.
 
     prepare_test({
       "theme1@tests.mozilla.org": [
         "onEnabling"
       ],
       "default@tests.mozilla.org": [
         "onDisabling"
@@ -1081,10 +1083,10 @@ function run_test_21() {
         ]
       });
 
       p1.userDisabled = false;
       ensure_test_completed();
 
       end_test();
     });
-  });
+  }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_uninstall.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_uninstall.js
@@ -20,38 +20,38 @@ profileDir.append("extensions");
 
 // Sets up the profile by installing an add-on.
 function run_test() {
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
 
   do_test_pending();
   startupManager();
 
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(olda1) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(olda1) {
     do_check_eq(olda1, null);
 
     writeInstallRDFForExtension(addon1, profileDir);
 
     restartManager();
 
     AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
       do_check_neq(a1, null);
       do_check_true(a1.isActive);
       do_check_false(a1.userDisabled);
       do_check_true(isExtensionInAddonsList(profileDir, a1.id));
       do_check_eq(a1.pendingOperations, 0);
       do_check_in_crash_annotation(addon1.id, addon1.version);
 
-      run_test_1();
+      do_execute_soon(run_test_1);
     });
-  });
+  }));
 }
 
 function end_test() {
-  do_test_finished();
+  do_execute_soon(do_test_finished);
 }
 
 // Uninstalling an add-on should work.
 function run_test_1() {
   prepare_test({
     "addon1@tests.mozilla.org": [
       "onUninstalling"
     ]
--- a/toolkit/mozapps/extensions/test/xpcshell/test_update.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_update.js
@@ -205,17 +205,17 @@ function run_test_2(install) {
       });
     }
   }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
 }
 
 function check_test_2() {
   ensure_test_completed();
 
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(olda1) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(olda1) {
     do_check_neq(olda1, null);
     do_check_eq(olda1.version, "1.0");
     do_check_true(isExtensionInAddonsList(profileDir, olda1.id));
 
     shutdownManager();
 
     startupManager();
 
@@ -229,17 +229,17 @@ function check_test_2() {
       do_check_eq(a1.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml");
       do_check_true(a1.foreignInstall);
       do_check_neq(a1.syncGUID, null);
       do_check_eq(originalSyncGUID, a1.syncGUID);
 
       a1.uninstall();
       do_execute_soon(run_test_3);
     });
-  });
+  }));
 }
 
 
 // Check that an update check finds compatibility updates and applies them
 function run_test_3() {
   restartManager();
 
   AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
@@ -396,36 +396,36 @@ function continue_test_6(install) {
 
   prepare_test({
     "addon1@tests.mozilla.org": [
       "onInstalling"
     ]
   }, [
     "onInstallStarted",
     "onInstallEnded",
-  ], check_test_6);
+  ], callback_soon(check_test_6));
 }
 
 function check_test_6(install) {
   do_check_eq(install.existingAddon.pendingUpgrade.install, install);
 
   restartManager();
   AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
     do_check_neq(a1, null);
     do_check_eq(a1.version, "2.0");
     do_check_eq(a1.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml");
     a1.uninstall();
-    restartManager();
-
-    run_test_7();
+    do_execute_soon(run_test_7);
   });
 }
 
 // Test that background update checks work for lightweight themes
 function run_test_7() {
+  restartManager();
+
   LightweightThemeManager.currentTheme = {
     id: "1",
     version: "1",
     name: "Test LW Theme",
     description: "A test theme",
     author: "Mozilla",
     homepageURL: "http://localhost:" + gPort + "/data/index.html",
     headerURL: "http://localhost:" + gPort + "/data/header.png",
@@ -573,17 +573,17 @@ function check_test_7_cache() {
     do_check_eq(p1.iconURL, "http://localhost:" + gPort + "/data/icon2.png?v=3");
     do_check_eq(currentTheme.headerURL, "http://localhost:" + gPort + "/data/header.png?v=3");
     do_check_eq(currentTheme.footerURL, "http://localhost:" + gPort + "/data/footer.png?v=3");
     do_check_eq(currentTheme.updateURL, "https://localhost:" + gPort + "/data/lwtheme.js?v=3");
 
     do_check_eq(p1.installDate.getTime(), gInstallDate);
     do_check_true(p1.installDate.getTime() < p1.updateDate.getTime());
 
-    run_test_8();
+    do_execute_soon(run_test_8);
   });
 }
 
 // Verify the parameter escaping in update urls.
 function run_test_8() {
   writeInstallRDFForExtension({
     id: "addon1@tests.mozilla.org",
     version: "5.0",
@@ -657,17 +657,17 @@ function run_test_8() {
       minVersion: "1",
       maxVersion: "1"
     }],
     name: "Test Addon 6",
   }, profileDir);
 
   restartManager();
 
-  AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
+  AddonManager.getAddonByID("addon2@tests.mozilla.org", callback_soon(function(a2) {
     a2.userDisabled = true;
     restartManager();
 
     testserver.registerPathHandler("/data/param_test.rdf", function(request, response) {
       do_check_neq(request.queryString, "");
       let [req_version, item_id, item_version,
            item_maxappversion, item_status,
            app_id, app_version, current_app_version,
@@ -751,17 +751,17 @@ function run_test_8() {
 
         restartManager();
         run_test_9();
       }
 
       let compatListener = {
         onUpdateFinished: function(addon, error) {
           if (--count == 0)
-            run_next_test();
+            do_execute_soon(run_next_test);
         }
       };
 
       let updateListener = {
         onUpdateAvailable: function(addon, update) {
           // Dummy so the update checker knows we care about new versions
         },
 
@@ -773,17 +773,17 @@ function run_test_8() {
 
       a1.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED);
       a2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_ADDON_INSTALLED);
       a3.findUpdates(updateListener, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE);
       a4.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "2");
       a5.findUpdates(compatListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED);
       a6.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED);
     });
-  });
+  }));
 }
 
 // Tests that if an install.rdf claims compatibility then the add-on will be
 // seen as compatible regardless of what the update.rdf says.
 function run_test_9() {
   writeInstallRDFForExtension({
     id: "addon4@tests.mozilla.org",
     version: "5.0",
@@ -823,17 +823,17 @@ function run_test_10() {
 // Tests that an update check for a new application will decrease a
 // targetApplication's maxVersion.
 function run_test_11() {
   AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) {
     a4.findUpdates({
       onUpdateFinished: function(addon) {
         do_check_true(addon.isCompatible);
 
-        run_test_12();
+        do_execute_soon(run_test_12);
       }
     }, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED);
   });
 }
 
 // Check that the decreased maxVersion applied and disables the add-on
 function run_test_12() {
   restartManager();
@@ -1291,25 +1291,27 @@ function continue_test_20(install) {
 
   prepare_test({
     "addon12@tests.mozilla.org": [
       "onInstalling"
     ]
   }, [
     "onInstallStarted",
     "onInstallEnded",
-  ], check_test_20);
+  ], callback_soon(check_test_20));
 }
 
 function check_test_20(install) {
   do_check_eq(install.existingAddon.pendingUpgrade.install, install);
 
   restartManager();
   AddonManager.getAddonByID("addon12@tests.mozilla.org", function(a12) {
     do_check_neq(a12, null);
     do_check_eq(a12.version, "2.0");
     do_check_eq(a12.type, "extension");
     a12.uninstall();
-    restartManager();
 
-    end_test();
+    do_execute_soon(() => {
+      restartManager();
+      end_test();
+    });
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js
@@ -202,17 +202,17 @@ function run_test_2(install) {
       });
     }
   }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
 }
 
 function check_test_2() {
   ensure_test_completed();
 
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(olda1) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(olda1) {
     do_check_neq(olda1, null);
     do_check_eq(olda1.version, "1.0");
     do_check_true(isExtensionInAddonsList(profileDir, olda1.id));
 
     shutdownManager();
 
     startupManager();
 
@@ -223,17 +223,17 @@ function check_test_2() {
       do_check_eq(a1.version, "2.0");
       do_check_true(isExtensionInAddonsList(profileDir, a1.id));
       do_check_eq(a1.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE);
       do_check_eq(a1.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml");
 
       a1.uninstall();
       do_execute_soon(run_test_3);
     });
-  });
+  }));
 }
 
 
 // Check that an update check finds compatibility updates and applies them
 function run_test_3() {
   restartManager();
 
   AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
@@ -491,17 +491,17 @@ function check_test_7() {
 
     // 5 seconds leeway seems like a lot, but tests can run slow and really if
     // this is within 5 seconds it is fine. If it is going to be wrong then it
     // is likely to be hours out at least
     do_check_true((Date.now() - p1.updateDate.getTime()) < 5000);
 
     gInstallDate = p1.installDate.getTime();
 
-    run_test_8();
+    do_execute_soon(run_test_8);
   });
 }
 
 // Verify the parameter escaping in update urls.
 function run_test_8() {
   writeInstallRDFForExtension({
     id: "addon1@tests.mozilla.org",
     version: "5.0",
@@ -575,17 +575,17 @@ function run_test_8() {
       minVersion: "1",
       maxVersion: "1"
     }],
     name: "Test Addon 6",
   }, profileDir);
 
   restartManager();
 
-  AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
+  AddonManager.getAddonByID("addon2@tests.mozilla.org", callback_soon(function(a2) {
     a2.userDisabled = true;
     restartManager();
 
     testserver.registerPathHandler("/data/param_test.rdf", function(request, response) {
       do_check_neq(request.queryString, "");
       let [req_version, item_id, item_version,
            item_maxappversion, item_status,
            app_id, app_version, current_app_version,
@@ -691,17 +691,17 @@ function run_test_8() {
 
       a1.findUpdates(updateListener, AddonManager.UPDATE_WHEN_USER_REQUESTED);
       a2.findUpdates(compatListener, AddonManager.UPDATE_WHEN_ADDON_INSTALLED);
       a3.findUpdates(updateListener, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE);
       a4.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "2");
       a5.findUpdates(compatListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED);
       a6.findUpdates(updateListener, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED);
     });
-  });
+  }));
 }
 
 // Tests that if an install.rdf claims compatibility then the add-on will be
 // seen as compatible regardless of what the update.rdf says.
 function run_test_9() {
   writeInstallRDFForExtension({
     id: "addon4@tests.mozilla.org",
     version: "5.0",
@@ -741,17 +741,17 @@ function run_test_10() {
 // Tests that an update check for a new application will decrease a
 // targetApplication's maxVersion.
 function run_test_11() {
   AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) {
     a4.findUpdates({
       onUpdateFinished: function(addon) {
         do_check_false(addon.isCompatible);
 
-        run_test_12();
+        do_execute_soon(run_test_12);
       }
     }, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED);
   });
 }
 
 // Check that the decreased maxVersion applied and disables the add-on
 function run_test_12() {
   restartManager();
@@ -1080,13 +1080,13 @@ function run_test_17() {
         do_throw("Should have not have seen compatibility information");
       },
 
       onUpdateAvailable: function() {
         do_throw("Should not have seen an available update");
       },
 
       onUpdateFinished: function() {
-        end_test();
+        do_execute_soon(end_test);
       }
     }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
   });
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_updateid.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_updateid.js
@@ -88,17 +88,17 @@ function run_test_1() {
 
         installUpdate(install, check_test_1);
       }
     }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
   });
 }
 
 function check_test_1(install) {
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
     // Existing add-on should have a pending upgrade
     do_check_neq(a1.pendingUpgrade, null);
     do_check_eq(a1.pendingUpgrade.id, "addon2@tests.mozilla.org");
     do_check_eq(a1.pendingUpgrade.install.existingAddon, a1);
     do_check_neq(a1.syncGUID);
 
     let a1SyncGUID = a1.syncGUID;
 
@@ -113,17 +113,17 @@ function check_test_1(install) {
 
       // The Sync GUID should change when the ID changes
       do_check_neq(a1SyncGUID, a2.syncGUID);
 
       a2.uninstall();
 
       do_execute_soon(run_test_2);
     });
-  });
+  }));
 }
 
 // Test that when the new add-on already exists we just upgrade that
 function run_test_2() {
   restartManager();
   shutdownManager();
 
   writeInstallRDFForExtension({
@@ -159,17 +159,18 @@ function run_test_2() {
         installUpdate(install, check_test_2);
       }
     }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
   });
 }
 
 function check_test_2(install) {
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
-                               "addon2@tests.mozilla.org"], function([a1, a2]) {
+                               "addon2@tests.mozilla.org"],
+                               callback_soon(function([a1, a2]) {
     do_check_eq(a1.pendingUpgrade, null);
     // Existing add-on should have a pending upgrade
     do_check_neq(a2.pendingUpgrade, null);
     do_check_eq(a2.pendingUpgrade.id, "addon2@tests.mozilla.org");
     do_check_eq(a2.pendingUpgrade.install.existingAddon, a2);
 
     restartManager();
 
@@ -179,17 +180,17 @@ function check_test_2(install) {
       do_check_neq(a1, null);
       do_check_neq(a2, null);
 
       a1.uninstall();
       a2.uninstall();
 
       do_execute_soon(run_test_3);
     });
-  });
+  }));
 }
 
 // Test that we rollback correctly when removing the old add-on fails
 function run_test_3() {
   restartManager();
   shutdownManager();
 
   // This test only works on Windows
@@ -220,17 +221,17 @@ function run_test_3() {
       onUpdateAvailable: function(addon, install) {
         installUpdate(install, check_test_3);
       }
     }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
   });
 }
 
 function check_test_3(install) {
-  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", callback_soon(function(a1) {
     // Existing add-on should have a pending upgrade
     do_check_neq(a1.pendingUpgrade, null);
     do_check_eq(a1.pendingUpgrade.id, "addon2@tests.mozilla.org");
     do_check_eq(a1.pendingUpgrade.install.existingAddon, a1);
 
     // Lock the old add-on open so it can't be uninstalled
     var file = profileDir.clone();
     file.append("addon1@tests.mozilla.org");
@@ -243,17 +244,18 @@ function check_test_3(install) {
                   createInstance(AM_Ci.nsIFileOutputStream);
     fstream.init(file, FileUtils.MODE_APPEND | FileUtils.MODE_WRONLY, FileUtils.PERMS_FILE, 0);
 
     restartManager();
 
     fstream.close();
 
     AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
-                                 "addon2@tests.mozilla.org"], function([a1, a2]) {
+                                 "addon2@tests.mozilla.org"],
+                                 callback_soon(function([a1, a2]) {
       // Should not have installed the new add-on but it should still be
       // pending install
       do_check_neq(a1, null);
       do_check_eq(a2, null);
 
       restartManager();
 
       AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
@@ -261,18 +263,18 @@ function check_test_3(install) {
         // Should have installed the new add-on
         do_check_eq(a1, null);
         do_check_neq(a2, null);
 
         a2.uninstall();
 
         do_execute_soon(run_test_4);
       });
-    });
-  });
+    }));
+  }));
 }
 
 // Tests that upgrading to a bootstrapped add-on works but requires a restart
 function run_test_4() {
   restartManager();
   shutdownManager();
 
   writeInstallRDFForExtension({
@@ -301,17 +303,18 @@ function run_test_4() {
         installUpdate(install, check_test_4);
       }
     }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
   });
 }
 
 function check_test_4() {
   AddonManager.getAddonsByIDs(["addon2@tests.mozilla.org",
-                               "addon3@tests.mozilla.org"], function([a2, a3]) {
+                               "addon3@tests.mozilla.org"],
+                               callback_soon(function([a2, a3]) {
     // Should still be pending install even though the new add-on is restartless
     do_check_neq(a2, null);
     do_check_eq(a3, null);
 
     do_check_neq(a2.pendingUpgrade, null);
     do_check_eq(a2.pendingUpgrade.id, "addon3@tests.mozilla.org");
 
     do_check_eq(getInstalledVersion(), -1);
@@ -325,17 +328,17 @@ function check_test_4() {
       do_check_eq(a2, null);
       do_check_neq(a3, null);
 
       do_check_eq(getInstalledVersion(), 3);
       do_check_eq(getActiveVersion(), 3);
 
       do_execute_soon(run_test_5);
     });
-  });
+  }));
 }
 
 // Tests that upgrading to another bootstrapped add-on works without a restart
 function run_test_5() {
   AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) {
     do_check_neq(a3, null);
     do_check_eq(a3.version, "3.0");
 
@@ -344,17 +347,18 @@ function run_test_5() {
         installUpdate(install, check_test_5);
       }
     }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
   });
 }
 
 function check_test_5() {
   AddonManager.getAddonsByIDs(["addon3@tests.mozilla.org",
-                               "addon4@tests.mozilla.org"], function([a3, a4]) {
+                               "addon4@tests.mozilla.org"],
+                               callback_soon(function([a3, a4]) {
     // Should have updated
     do_check_eq(a3, null);
     do_check_neq(a4, null);
 
     do_check_eq(getInstalledVersion(), 4);
     do_check_eq(getActiveVersion(), 4);
 
     restartManager();
@@ -365,17 +369,17 @@ function check_test_5() {
       do_check_eq(a3, null);
       do_check_neq(a4, null);
 
       do_check_eq(getInstalledVersion(), 4);
       do_check_eq(getActiveVersion(), 4);
 
       run_test_6();
     });
-  });
+  }));
 }
 
 // Tests that upgrading to a non-bootstrapped add-on works but requires a restart
 function run_test_6() {
   AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) {
     do_check_neq(a4, null);
     do_check_eq(a4.version, "4.0");
 
@@ -384,17 +388,18 @@ function run_test_6() {
         installUpdate(install, check_test_6);
       }
     }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
   });
 }
 
 function check_test_6() {
   AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org",
-                               "addon2@tests.mozilla.org"], function([a4, a2]) {
+                               "addon2@tests.mozilla.org"],
+                               callback_soon(function([a4, a2]) {
     // Should still be pending install even though the old add-on is restartless
     do_check_neq(a4, null);
     do_check_eq(a2, null);
 
     do_check_neq(a4.pendingUpgrade, null);
     do_check_eq(a4.pendingUpgrade.id, "addon2@tests.mozilla.org");
 
     do_check_eq(getInstalledVersion(), 4);
@@ -408,10 +413,10 @@ function check_test_6() {
       do_check_eq(a4, null);
       do_check_neq(a2, null);
 
       do_check_eq(getInstalledVersion(), 0);
       do_check_eq(getActiveVersion(), 0);
 
       end_test();
     });
-  });
+  }));
 }
--- a/toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js
@@ -88,17 +88,17 @@ function run_test() {
 function end_test() {
   if (!gGlobalExisted) {
     globalDir.remove(true);
   }
   else {
     globalDir.append(do_get_expected_addon_name("addon4@tests.mozilla.org"));
     globalDir.remove(true);
   }
-  do_test_finished();
+  do_execute_soon(do_test_finished);
 }
 
 // Test that the test extensions are all installed
 function run_test_1() {
   startupManager();
 
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                "addon2@tests.mozilla.org",
--- a/toolkit/mozapps/extensions/test/xpcshell/test_upgrade_strictcompat.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade_strictcompat.js
@@ -91,17 +91,17 @@ function end_test() {
   }
   else {
     globalDir.append(do_get_expected_addon_name("addon4@tests.mozilla.org"));
     globalDir.remove(true);
   }
 
   Services.prefs.clearUserPref(PREF_EM_STRICT_COMPATIBILITY);
 
-  do_test_finished();
+  do_execute_soon(do_test_finished);
 }
 
 // Test that the test extensions are all installed
 function run_test_1() {
   startupManager();
 
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                "addon2@tests.mozilla.org",