Bug 693901 - Add preference to globally (re)enable strict compatibility checks. r=dtownsend
authorBlair McBride <bmcbride@mozilla.com>
Tue, 01 Nov 2011 18:48:45 +1300
changeset 79469 1fb831781a15926b4d4969621f18f0937170b28e
parent 79468 b78d449f0c8b8e77a78a3b7ce8fb859ad7d253c8
child 79470 6b7874f5b777f0d61c955cac2c4f5bb1c8974205
push id21407
push usertim.taubert@gmx.de
push dateTue, 01 Nov 2011 12:25:29 +0000
treeherdermozilla-central@6e219763ddd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdtownsend
bugs693901
milestone10.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 693901 - Add preference to globally (re)enable strict compatibility checks. r=dtownsend
browser/app/profile/firefox.js
browser/base/content/test/browser_bug553455.js
toolkit/mozapps/extensions/AddonManager.jsm
toolkit/mozapps/extensions/XPIProvider.jsm
toolkit/mozapps/extensions/test/browser/browser_bug557956.js
toolkit/mozapps/extensions/test/browser/head.js
toolkit/mozapps/extensions/test/xpcshell/head_addons.js
toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js
toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1_strictcompat.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_corrupt.js
toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js
toolkit/mozapps/extensions/test/xpcshell/test_install.js
toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js
toolkit/mozapps/extensions/test/xpcshell/test_locked.js
toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js
toolkit/mozapps/extensions/test/xpcshell/test_strictcompatibility.js
toolkit/mozapps/extensions/test/xpcshell/test_update.js
toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js
toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js
toolkit/mozapps/extensions/test/xpcshell/test_upgrade_strictcompat.js
toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
toolkit/mozapps/update/test/chrome/utils.js
toolkit/mozapps/update/test/shared.js
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -49,16 +49,20 @@
 #endif
 
 pref("browser.chromeURL","chrome://browser/content/");
 pref("browser.hiddenWindowChromeURL", "chrome://browser/content/hiddenWindow.xul");
 
 // Enables some extra Extension System Logging (can reduce performance)
 pref("extensions.logging.enabled", false);
 
+// Enables strict compatibility. To be toggled in bug 698653, to make addons
+// compatibile by default.
+pref("extensions.strictCompatibility", true);
+
 // Preferences for AMO integration
 pref("extensions.getAddons.cache.enabled", true);
 pref("extensions.getAddons.maxResults", 15);
 pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/guid:%IDS%?src=firefox&appOS=%OS%&appVersion=%VERSION%&tMain=%TIME_MAIN%&tFirstPaint=%TIME_FIRST_PAINT%&tSessionRestored=%TIME_SESSION_RESTORED%");
 pref("extensions.getAddons.search.browseURL", "https://addons.mozilla.org/%LOCALE%/firefox/search?q=%TERMS%");
 pref("extensions.getAddons.search.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/%TERMS%/all/%MAX_RESULTS%/%OS%/%VERSION%?src=firefox");
 pref("extensions.webservice.discoverURL", "https://services.addons.mozilla.org/%LOCALE%/firefox/discovery/pane/%VERSION%/%OS%");
 
--- a/browser/base/content/test/browser_bug553455.js
+++ b/browser/base/content/test/browser_bug553455.js
@@ -861,16 +861,17 @@ var XPInstallObserver = {
   }
 };
 
 function test() {
   requestLongerTimeout(4);
   waitForExplicitFinish();
 
   Services.prefs.setBoolPref("extensions.logging.enabled", true);
+  Services.prefs.setBoolPref("extensions.strictCompatibility", true);
 
   Services.obs.addObserver(XPInstallObserver, "addon-install-started", false);
   Services.obs.addObserver(XPInstallObserver, "addon-install-blocked", false);
   Services.obs.addObserver(XPInstallObserver, "addon-install-failed", false);
   Services.obs.addObserver(XPInstallObserver, "addon-install-complete", false);
 
   registerCleanupFunction(function() {
     // Make sure no more test parts run in case we were timed out
@@ -879,16 +880,17 @@ function test() {
 
     AddonManager.getAllInstalls(function(aInstalls) {
       aInstalls.forEach(function(aInstall) {
         aInstall.cancel();
       });
     });
 
     Services.prefs.clearUserPref("extensions.logging.enabled");
+    Services.prefs.clearUserPref("extensions.strictCompatibility");
 
     Services.obs.removeObserver(XPInstallObserver, "addon-install-started");
     Services.obs.removeObserver(XPInstallObserver, "addon-install-blocked");
     Services.obs.removeObserver(XPInstallObserver, "addon-install-failed");
     Services.obs.removeObserver(XPInstallObserver, "addon-install-complete");
   });
 
   runNextTest();
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -43,16 +43,19 @@ const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 
 const PREF_BLOCKLIST_PINGCOUNTVERSION = "extensions.blocklist.pingCountVersion";
 const PREF_EM_UPDATE_ENABLED          = "extensions.update.enabled";
 const PREF_EM_LAST_APP_VERSION        = "extensions.lastAppVersion";
 const PREF_EM_LAST_PLATFORM_VERSION   = "extensions.lastPlatformVersion";
 const PREF_EM_AUTOUPDATE_DEFAULT      = "extensions.update.autoUpdateDefault";
+const PREF_EM_STRICT_COMPATIBILITY    = "extensions.strictCompatibility";
+
+const STRICT_COMPATIBILITY_DEFAULT    = true;
 
 const VALID_TYPES_REGEXP = /^[\w\-]+$/;
 
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 var EXPORTED_SYMBOLS = [ "AddonManager", "AddonManagerPrivate" ];
 
 const CATEGORY_PROVIDER_MODULE = "addon-provider-module";
@@ -276,16 +279,17 @@ function AddonType(aId, aLocaleURI, aLoc
     });
   }
   else {
     this.name = aLocaleKey;
   }
 }
 
 var gStarted = false;
+var gStrictCompatibility = STRICT_COMPATIBILITY_DEFAULT;
 
 /**
  * This is the real manager, kept here rather than in AddonManager to keep its
  * contents hidden from API users.
  */
 var AddonManagerInternal = {
   installListeners: [],
   addonListeners: [],
@@ -369,16 +373,21 @@ var AddonManagerInternal = {
       Services.prefs.setCharPref(PREF_EM_LAST_APP_VERSION,
                                  Services.appinfo.version);
       Services.prefs.setCharPref(PREF_EM_LAST_PLATFORM_VERSION,
                                  Services.appinfo.platformVersion);
       Services.prefs.setIntPref(PREF_BLOCKLIST_PINGCOUNTVERSION,
                                 (appChanged === undefined ? 0 : -1));
     }
 
+    try {
+      gStrictCompatibility = Services.prefs.getBoolPref(PREF_EM_STRICT_COMPATIBILITY);
+    } catch (e) {}
+    Services.prefs.addObserver(PREF_EM_STRICT_COMPATIBILITY, this, false);
+
     // Ensure all default providers have had a chance to register themselves
     DEFAULT_PROVIDERS.forEach(function(url) {
       try {
         Components.utils.import(url, {});
       }
       catch (e) {
         ERROR("Exception loading default provider \"" + url + "\"", e);
       }
@@ -490,29 +499,56 @@ var AddonManagerInternal = {
       callProvider(aProvider, "shutdown");
   },
 
   /**
    * Shuts down the addon manager and all registered providers, this must clean
    * up everything in order for automated tests to fake restarts.
    */
   shutdown: function AMI_shutdown() {
+    Services.prefs.removeObserver(PREF_EM_STRICT_COMPATIBILITY, this);
+
     this.providers.forEach(function(provider) {
       callProvider(provider, "shutdown");
     });
 
     this.installListeners.splice(0, this.installListeners.length);
     this.addonListeners.splice(0, this.addonListeners.length);
     this.typeListeners.splice(0, this.typeListeners.length);
     for (let type in this.startupChanges)
       delete this.startupChanges[type];
     gStarted = false;
   },
 
   /**
+   * Notified when a preference we're interested in has changed.
+   *
+   * @see nsIObserver
+   */
+  observe: function AMI_observe(aSubject, aTopic, aData) {
+    switch (aData) {
+    case PREF_EM_STRICT_COMPATIBILITY:
+      let oldValue = gStrictCompatibility;
+      try {
+        gStrictCompatibility = Services.prefs.getBoolPref(PREF_EM_STRICT_COMPATIBILITY);
+      } catch(e) {
+        gStrictCompatibility = STRICT_COMPATIBILITY_DEFAULT;
+      }
+
+      // XXXunf Currently, this won't notify listeners that an addon's
+      // compatibility status has changed if the addon's appDisabled state
+      // doesn't change.
+      if (gStrictCompatibility != oldValue)
+        this.updateAddonAppDisabledStates();
+
+      break;
+    }
+  },
+
+  /**
    * Performs a background update check by starting an update for all add-ons
    * that can be updated.
    */
   backgroundUpdateCheck: function AMI_backgroundUpdateCheck() {
     if (!Services.prefs.getBoolPref(PREF_EM_UPDATE_ENABLED))
       return;
 
     Services.obs.notifyObservers(null, "addons-background-update-start", null);
@@ -1090,16 +1126,20 @@ var AddonManagerInternal = {
     return this.typesProxy;
   },
 
   get autoUpdateDefault() {
     try {
       return Services.prefs.getBoolPref(PREF_EM_AUTOUPDATE_DEFAULT);
     } catch(e) { }
     return true;
+  },
+
+  get strictCompatibility() {
+    return gStrictCompatibility;
   }
 };
 
 /**
  * Should not be used outside of core Mozilla code. This is a private API for
  * the startup and platform integration code to use. Refer to the methods on
  * AddonManagerInternal for documentation however note that these methods are
  * subject to change at any time.
@@ -1410,14 +1450,18 @@ var AddonManager = {
   shouldAutoUpdate: function AM_shouldAutoUpdate(aAddon) {
     if (!("applyBackgroundUpdates" in aAddon))
       return false;
     if (aAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_ENABLE)
       return true;
     if (aAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DISABLE)
       return false;
     return this.autoUpdateDefault;
+  },
+
+  get strictCompatibility() {
+    return AddonManagerInternal.strictCompatibility;
   }
 };
 
 Object.freeze(AddonManagerInternal);
 Object.freeze(AddonManagerPrivate);
 Object.freeze(AddonManager);
--- a/toolkit/mozapps/extensions/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/XPIProvider.jsm
@@ -6903,16 +6903,21 @@ AddonInternal.prototype = {
     return matchedOS && !needsABI;
   },
 
   isCompatibleWith: function(aAppVersion, aPlatformVersion) {
     let app = this.matchingTargetApplication;
     if (!app)
       return false;
 
+    // Only extensions can be compatible by default; themes always use strict
+    // compatibility checking.
+    if (this.type == "extension" && !AddonManager.strictCompatibility)
+      return true;
+
     if (!aAppVersion)
       aAppVersion = Services.appinfo.version;
     if (!aPlatformVersion)
       aPlatformVersion = Services.appinfo.platformVersion;
 
     let version;
     if (app.id == Services.appinfo.ID)
       version = aAppVersion;
--- a/toolkit/mozapps/extensions/test/browser/browser_bug557956.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_bug557956.js
@@ -2,16 +2,18 @@
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // Test that the compatibility dialog that normally displays during startup
 // appears to work correctly.
 
 const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul";
 
+Services.prefs.setBoolPref(PREF_STRICT_COMPAT, true);
+
 /**
  * Test add-ons:
  *
  * Addon    minVersion   maxVersion   Notes
  * addon1   0            *
  * addon2   0            0
  * addon3   0            0
  * addon4   1            *
--- a/toolkit/mozapps/extensions/test/browser/head.js
+++ b/toolkit/mozapps/extensions/test/browser/head.js
@@ -21,16 +21,17 @@ const TESTROOT2 = "http://example.org/" 
 const CHROMEROOT = pathParts.join("/") + "/";
 const PREF_DISCOVERURL = "extensions.webservice.discoverURL";
 const PREF_UPDATEURL = "extensions.update.url";
 
 const MANAGER_URI = "about:addons";
 const INSTALL_URI = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul";
 const PREF_LOGGING_ENABLED = "extensions.logging.enabled";
 const PREF_SEARCH_MAXRESULTS = "extensions.getAddons.maxResults";
+const PREF_STRICT_COMPAT = "extensions.strictCompatibility";
 
 var gPendingTests = [];
 var gTestsRun = 0;
 var gTestStart = null;
 
 var gUseInContentUI = !gTestInWindow && ("switchToTabHavingURI" in window);
 
 var gDiscoveryURL = Services.prefs.getCharPref(PREF_DISCOVERURL);
@@ -39,19 +40,20 @@ var gUpdateURL = Services.prefs.getCharP
 // Turn logging on for all tests
 Services.prefs.setBoolPref(PREF_LOGGING_ENABLED, true);
 // Turn off remote results in searches
 Services.prefs.setIntPref(PREF_SEARCH_MAXRESULTS, 0);
 registerCleanupFunction(function() {
   Services.prefs.clearUserPref(PREF_LOGGING_ENABLED);
   try {
     Services.prefs.clearUserPref(PREF_SEARCH_MAXRESULTS);
-  }
-  catch (e) {
-  }
+  } catch (e) {}
+  try {
+    Services.prefs.clearUserPref(PREF_STRICT_COMPAT);
+  } catch (e) {}
 
   Services.prefs.setCharPref(PREF_DISCOVERURL, gDiscoveryURL);
   Services.prefs.setCharPref(PREF_UPDATEURL, gUpdateURL);
 
   // Throw an error if the add-ons manager window is open anywhere
   var windows = Services.wm.getEnumerator("Addons:Manager");
   if (windows.hasMoreElements())
     ok(false, "Found unexpected add-ons manager window still open");
--- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
@@ -3,16 +3,19 @@
  */
 
 const AM_Cc = Components.classes;
 const AM_Ci = Components.interfaces;
 
 const XULAPPINFO_CONTRACTID = "@mozilla.org/xre/app-info;1";
 const XULAPPINFO_CID = Components.ID("{c763b610-9d49-455a-bbd2-ede71682a1ac}");
 
+const PREF_EM_CHECK_UPDATE_SECURITY   = "extensions.checkUpdateSecurity";
+const PREF_EM_STRICT_COMPATIBILITY    = "extensions.strictCompatibility";
+
 Components.utils.import("resource://gre/modules/AddonManager.jsm");
 Components.utils.import("resource://gre/modules/AddonRepository.jsm");
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/FileUtils.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/NetUtil.jsm");
 
 var gInternalManager = null;
@@ -1098,16 +1101,20 @@ Services.prefs.setBoolPref("extensions.s
 
 // Point update checks to the local machine for fast failures
 Services.prefs.setCharPref("extensions.update.url", "http://127.0.0.1/updateURL");
 Services.prefs.setCharPref("extensions.blocklist.url", "http://127.0.0.1/blocklistURL");
 
 // By default ignore bundled add-ons
 Services.prefs.setBoolPref("extensions.installDistroAddons", false);
 
+// By default use strict compatibility
+Services.prefs.setBoolPref("extensions.strictCompatibility", true);
+
+
 // Register a temporary directory for the tests.
 const gTmpD = gProfD.clone();
 gTmpD.append("temp");
 gTmpD.create(AM_Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECTORY);
 registerDirectory("TmpD", gTmpD);
 
 // Write out an empty blocklist.xml file to the profile to ensure nothing
 // is blocklisted by default
@@ -1141,9 +1148,17 @@ do_register_cleanup(function() {
 
   testDir.leafName = "staged";
   do_check_false(testDir.exists());
 
   testDir.leafName = "staged-xpis";
   do_check_false(testDir.exists());
 
   shutdownManager();
+
+  // Clear commonly set prefs.
+  try {
+    Services.prefs.clearUserPref(PREF_EM_CHECK_UPDATE_SECURITY);
+  } catch (e) {}
+  try {
+    Services.prefs.clearUserPref(PREF_EM_STRICT_COMPATIBILITY);
+  } catch (e) {}
 });
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1.js
@@ -32,17 +32,18 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL
  *
  * ***** END LICENSE BLOCK *****
  */
 
 // Disables security checking our updates which haven't been signed
-Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false);
+Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
+Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false);
 
 var ADDONS = [
   "test_bug470377_1",
   "test_bug470377_2",
   "test_bug470377_3",
   "test_bug470377_4",
   "test_bug470377_5",
 ];
@@ -65,17 +66,17 @@ function run_test() {
 
     AddonManager.getAddonsByIDs(["bug470377_1@tests.mozilla.org",
                                  "bug470377_2@tests.mozilla.org",
                                  "bug470377_3@tests.mozilla.org",
                                  "bug470377_4@tests.mozilla.org",
                                  "bug470377_5@tests.mozilla.org"],
                                  function([a1, a2, a3, a4, a5]) {
       do_check_eq(a1, null);
-      do_check_eq(a2, null);
-      do_check_eq(a3, null);
+      do_check_neq(a2, null);
+      do_check_neq(a3, null);
       do_check_neq(a4, null);
       do_check_neq(a5, null);
 
       server.stop(do_test_finished);
     });
   }, true);
 }
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_1_strictcompat.js
@@ -0,0 +1,82 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Dave Townsend <dtownsend@oxymoronical.com>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+// Disables security checking our updates which haven't been signed
+Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
+Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true);
+
+var ADDONS = [
+  "test_bug470377_1",
+  "test_bug470377_2",
+  "test_bug470377_3",
+  "test_bug470377_4",
+  "test_bug470377_5",
+];
+
+do_load_httpd_js();
+var server;
+
+function run_test() {
+  do_test_pending();
+  createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2");
+
+  server = new nsHttpServer();
+  server.registerDirectory("/", do_get_file("data/test_bug470377"));
+  server.start(4444);
+
+  startupManager();
+
+  installAllFiles([do_get_addon(a) for each (a in ADDONS)], function() {
+    restartManager();
+
+    AddonManager.getAddonsByIDs(["bug470377_1@tests.mozilla.org",
+                                 "bug470377_2@tests.mozilla.org",
+                                 "bug470377_3@tests.mozilla.org",
+                                 "bug470377_4@tests.mozilla.org",
+                                 "bug470377_5@tests.mozilla.org"],
+                                 function([a1, a2, a3, a4, a5]) {
+      do_check_eq(a1, null);
+      do_check_eq(a2, null);
+      do_check_eq(a3, null);
+      do_check_neq(a4, null);
+      do_check_neq(a5, null);
+
+      server.stop(do_test_finished);
+    });
+  }, true);
+}
--- a/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3.js
@@ -31,16 +31,18 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL
  *
  * ***** END LICENSE BLOCK *****
  */
 
+Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false);
+
 function run_test() {
   do_test_pending();
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2.2.3", "2");
 
   // inject the add-ons into the profile
   var dest = gProfD.clone();
   dest.append("extensions");
   dest.append("bug470377_1@tests.mozilla.org");
@@ -82,19 +84,19 @@ function run_test_1() {
                                "bug470377_2@tests.mozilla.org",
                                "bug470377_3@tests.mozilla.org",
                                "bug470377_4@tests.mozilla.org",
                                "bug470377_5@tests.mozilla.org"],
                                function([a1, a2, a3, a4, a5]) {
     do_check_neq(a1, null);
     do_check_false(a1.isActive);
     do_check_neq(a2, null);
-    do_check_false(a2.isActive);
+    do_check_true(a2.isActive);
     do_check_neq(a3, null);
-    do_check_false(a3.isActive);
+    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);
 
     run_test_2();
   });
 }
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_bug470377_3_strictcompat.js
@@ -0,0 +1,140 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Dave Townsend <dtownsend@oxymoronical.com>.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL
+ *
+ * ***** END LICENSE BLOCK *****
+ */
+
+function run_test() {
+  do_test_pending();
+  createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2.2.3", "2");
+  Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true);
+
+  // inject the add-ons into the profile
+  var dest = gProfD.clone();
+  dest.append("extensions");
+  dest.append("bug470377_1@tests.mozilla.org");
+  dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755);
+  var source = do_get_file("data/test_bug470377/install_1.rdf");
+  source.copyTo(dest, "install.rdf");
+  dest = gProfD.clone();
+  dest.append("extensions");
+  dest.append("bug470377_2@tests.mozilla.org");
+  dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755);
+  source = do_get_file("data/test_bug470377/install_2.rdf");
+  source.copyTo(dest, "install.rdf");
+  dest = gProfD.clone();
+  dest.append("extensions");
+  dest.append("bug470377_3@tests.mozilla.org");
+  dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755);
+  source = do_get_file("data/test_bug470377/install_3.rdf");
+  source.copyTo(dest, "install.rdf");
+  dest = gProfD.clone();
+  dest.append("extensions");
+  dest.append("bug470377_4@tests.mozilla.org");
+  dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755);
+  source = do_get_file("data/test_bug470377/install_4.rdf");
+  source.copyTo(dest, "install.rdf");
+  dest = gProfD.clone();
+  dest.append("extensions");
+  dest.append("bug470377_5@tests.mozilla.org");
+  dest.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755);
+  source = do_get_file("data/test_bug470377/install_5.rdf");
+  source.copyTo(dest, "install.rdf");
+
+  startupManager();
+
+  run_test_1();
+}
+
+function run_test_1() {
+  AddonManager.getAddonsByIDs(["bug470377_1@tests.mozilla.org",
+                               "bug470377_2@tests.mozilla.org",
+                               "bug470377_3@tests.mozilla.org",
+                               "bug470377_4@tests.mozilla.org",
+                               "bug470377_5@tests.mozilla.org"],
+                               function([a1, a2, a3, a4, a5]) {
+    do_check_neq(a1, null);
+    do_check_false(a1.isActive);
+    do_check_neq(a2, null);
+    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);
+
+    run_test_2();
+  });
+}
+
+function run_test_2() {
+  // Disable compatibility checks
+  var channel = "default";
+  try {
+    channel = Services.prefs.getCharPref("app.update.channel");
+  }
+  catch (e) { }
+
+  if (channel != "aurora" &&
+      channel != "beta" &&
+      channel != "release") {
+    Services.prefs.setBoolPref("extensions.checkCompatibility.nightly", false);
+  }
+  else {
+    Services.prefs.setBoolPref("extensions.checkCompatibility.2.2", false);
+  }
+  restartManager();
+
+  AddonManager.getAddonsByIDs(["bug470377_1@tests.mozilla.org",
+                               "bug470377_2@tests.mozilla.org",
+                               "bug470377_3@tests.mozilla.org",
+                               "bug470377_4@tests.mozilla.org",
+                               "bug470377_5@tests.mozilla.org"],
+                               function([a1, a2, a3, a4, a5]) {
+    do_check_neq(a1, null);
+    do_check_false(a1.isActive);
+    do_check_neq(a2, null);
+    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();
+  });
+}
--- a/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt.js
@@ -4,17 +4,18 @@
 
 // Checks that we rebuild something sensible from a corrupt database
 
 
 do_load_httpd_js();
 var testserver;
 
 // The test extension uses an insecure update url.
-Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false);
+Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
+Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false);
 
 // Will be enabled
 var addon1 = {
   id: "addon1@tests.mozilla.org",
   version: "1.0",
   name: "Test 1",
   targetApplications: [{
     id: "xpcshell@tests.mozilla.org",
@@ -30,43 +31,43 @@ var addon2 = {
   name: "Test 2",
   targetApplications: [{
     id: "xpcshell@tests.mozilla.org",
     minVersion: "2",
     maxVersion: "2"
   }]
 };
 
-// Will get a compatibility update and be enabled
+// Will get a compatibility update and stay enabled
 var addon3 = {
   id: "addon3@tests.mozilla.org",
   version: "1.0",
   name: "Test 3",
   updateURL: "http://localhost:4444/data/test_corrupt.rdf",
   targetApplications: [{
     id: "xpcshell@tests.mozilla.org",
     minVersion: "1",
     maxVersion: "1"
   }]
 };
 
-// Will get a compatibility update and be disabled
+// Will get a compatibility update and be enabled
 var addon4 = {
   id: "addon4@tests.mozilla.org",
   version: "1.0",
   name: "Test 4",
   updateURL: "http://localhost:4444/data/test_corrupt.rdf",
   targetApplications: [{
     id: "xpcshell@tests.mozilla.org",
     minVersion: "1",
     maxVersion: "1"
   }]
 };
 
-// Stays incompatible
+// Would stay incompatible with strict compat
 var addon5 = {
   id: "addon5@tests.mozilla.org",
   version: "1.0",
   name: "Test 5",
   targetApplications: [{
     id: "xpcshell@tests.mozilla.org",
     minVersion: "1",
     maxVersion: "1"
@@ -212,19 +213,19 @@ function run_test_1() {
 
     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_neq(a5, null);
-    do_check_false(a5.isActive);
+    do_check_true(a5.isActive);
     do_check_false(a5.userDisabled);
-    do_check_true(a5.appDisabled);
+    do_check_false(a5.appDisabled);
     do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
 
     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);
 
@@ -280,31 +281,33 @@ function run_test_1() {
       do_check_false(a2.appDisabled);
       do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
 
       // 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_false(a3.appDisabled);
+      do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
 
-      // The compatibility update won't be recovered and it will not have been
-      // able to tell that it was previously userDisabled
+      // 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_false(a4.userDisabled);
-      do_check_true(a4.appDisabled);
+      do_check_true(a4.userDisabled);
+      do_check_false(a4.appDisabled);
       do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE);
 
       do_check_neq(a5, null);
-      do_check_false(a5.isActive);
+      do_check_true(a5.isActive);
       do_check_false(a5.userDisabled);
-      do_check_true(a5.appDisabled);
+      do_check_false(a5.appDisabled);
       do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
 
       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);
 
@@ -349,31 +352,31 @@ function run_test_1() {
 
         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_neq(a3, null);
-        do_check_false(a3.isActive);
+        do_check_true(a3.isActive);
         do_check_false(a3.userDisabled);
-        do_check_true(a3.appDisabled);
+        do_check_false(a3.appDisabled);
         do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
 
         do_check_neq(a4, null);
         do_check_false(a4.isActive);
-        do_check_false(a4.userDisabled);
-        do_check_true(a4.appDisabled);
+        do_check_true(a4.userDisabled);
+        do_check_false(a4.appDisabled);
         do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE);
 
         do_check_neq(a5, null);
-        do_check_false(a5.isActive);
+        do_check_true(a5.isActive);
         do_check_false(a5.userDisabled);
-        do_check_true(a5.appDisabled);
+        do_check_false(a5.appDisabled);
         do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
 
         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);
 
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_corrupt_strictcompat.js
@@ -0,0 +1,403 @@
+/* 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
+
+
+do_load_httpd_js();
+var testserver;
+
+// The test extension uses an insecure update url.
+Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
+Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true);
+
+// Will be enabled
+var addon1 = {
+  id: "addon1@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 1",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "2",
+    maxVersion: "2"
+  }]
+};
+
+// Will be disabled
+var addon2 = {
+  id: "addon2@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 2",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "2",
+    maxVersion: "2"
+  }]
+};
+
+// Will get a compatibility update and be enabled
+var addon3 = {
+  id: "addon3@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 3",
+  updateURL: "http://localhost:4444/data/test_corrupt.rdf",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "1",
+    maxVersion: "1"
+  }]
+};
+
+// Will get a compatibility update and be disabled
+var addon4 = {
+  id: "addon4@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 4",
+  updateURL: "http://localhost:4444/data/test_corrupt.rdf",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "1",
+    maxVersion: "1"
+  }]
+};
+
+// Stays incompatible
+var addon5 = {
+  id: "addon5@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 5",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "1",
+    maxVersion: "1"
+  }]
+};
+
+// Enabled bootstrapped
+var addon6 = {
+  id: "addon6@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 6",
+  bootstrap: "true",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "2",
+    maxVersion: "2"
+  }]
+};
+
+// Disabled bootstrapped
+var addon7 = {
+  id: "addon7@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 7",
+  bootstrap: "true",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "2",
+    maxVersion: "2"
+  }]
+};
+
+// The default theme
+var theme1 = {
+  id: "theme1@tests.mozilla.org",
+  version: "1.0",
+  name: "Theme 1",
+  internalName: "classic/1.0",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "2",
+    maxVersion: "2"
+  }]
+};
+
+// The selected theme
+var theme2 = {
+  id: "theme2@tests.mozilla.org",
+  version: "1.0",
+  name: "Theme 2",
+  internalName: "test/1.0",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "2",
+    maxVersion: "2"
+  }]
+};
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+function run_test() {
+  do_test_pending();
+  createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2");
+
+  writeInstallRDFForExtension(addon1, profileDir);
+  writeInstallRDFForExtension(addon2, profileDir);
+  writeInstallRDFForExtension(addon3, profileDir);
+  writeInstallRDFForExtension(addon4, profileDir);
+  writeInstallRDFForExtension(addon5, profileDir);
+  writeInstallRDFForExtension(addon6, profileDir);
+  writeInstallRDFForExtension(addon7, profileDir);
+  writeInstallRDFForExtension(theme1, profileDir);
+  writeInstallRDFForExtension(theme2, profileDir);
+
+  // Create and configure the HTTP server.
+  testserver = new nsHttpServer();
+  testserver.registerDirectory("/addons/", do_get_file("addons"));
+  testserver.registerDirectory("/data/", do_get_file("data"));
+  testserver.start(4444);
+
+  // Startup the profile and setup the initial state
+  startupManager();
+
+  AddonManager.getAddonsByIDs(["addon2@tests.mozilla.org",
+                               "addon3@tests.mozilla.org",
+                               "addon4@tests.mozilla.org",
+                               "addon7@tests.mozilla.org",
+                               "theme2@tests.mozilla.org"], function([a2, a3, a4,
+                                                                      a7, t2]) {
+    // Set up the initial state
+    a2.userDisabled = true;
+    a4.userDisabled = true;
+    a7.userDisabled = true;
+    t2.userDisabled = false;
+    a3.findUpdates({
+      onUpdateFinished: function() {
+        a4.findUpdates({
+          onUpdateFinished: function() {
+            restartManager();
+
+            run_test_1();
+          }
+        }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE);
+      }
+    }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE);
+  });
+}
+
+function end_test() {
+  testserver.stop(do_test_finished);
+}
+
+function run_test_1() {
+  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"], 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_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_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_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_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_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_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);
+
+    // After restarting the database won't be open and so can be replaced with
+    // a bad file
+    restartManager();
+    var dbfile = gProfD.clone();
+    dbfile.append("extensions.sqlite");
+    dbfile.remove(true);
+    dbfile.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755);
+
+    // 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"], 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);
+
+      // 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);
+
+      // 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);
+
+      // 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_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_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);
+
+      // 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);
+
+      restartManager();
+
+      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"], 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_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_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_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_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_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_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);
+
+        end_test();
+      });
+    });
+  });
+}
--- a/toolkit/mozapps/extensions/test/xpcshell/test_install.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_install.js
@@ -16,17 +16,18 @@ Components.utils.import("resource://gre/
 const ADDON1_SIZE = 705 + 16 + 16;
 
 do_load_httpd_js();
 var testserver;
 var gInstallDate;
 var gInstall = null;
 
 // The test extension uses an insecure update url.
-Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false);
+Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
+Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false);
 
 const profileDir = gProfD.clone();
 profileDir.append("extensions");
 
 function run_test() {
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
 
   startupManager();
@@ -666,24 +667,24 @@ function run_test_11() {
     do_check_eq(installs[1].addon.id, "addon5@tests.mozilla.org");
     do_check_false(installs[1].addon.appDisabled);
     do_check_eq(installs[1].version, "3.0");
     do_check_eq(installs[1].name, "Multi Test 2");
     do_check_eq(installs[1].state, AddonManager.STATE_DOWNLOADED);
     do_check_true(hasFlag(installs[1].addon.operationsRequiringRestart,
                           AddonManager.OP_NEEDS_RESTART_INSTALL));
 
-    // Comes from addon6.xpi and is incompatible
+    // Comes from addon6.xpi and would be incompatible with strict compat enabled
     do_check_eq(installs[2].sourceURI, install.sourceURI);
     do_check_eq(installs[2].addon.id, "addon6@tests.mozilla.org");
-    do_check_true(installs[2].addon.appDisabled);
+    do_check_false(installs[2].addon.appDisabled);
     do_check_eq(installs[2].version, "2.0");
     do_check_eq(installs[2].name, "Multi Test 3");
     do_check_eq(installs[2].state, AddonManager.STATE_DOWNLOADED);
-    do_check_false(hasFlag(installs[2].addon.operationsRequiringRestart,
+    do_check_true(hasFlag(installs[2].addon.operationsRequiringRestart,
                            AddonManager.OP_NEEDS_RESTART_INSTALL));
 
     // Comes from addon7.jar and is made compatible by an update check
     do_check_eq(installs[3].sourceURI, install.sourceURI);
     do_check_eq(installs[3].addon.id, "addon7@tests.mozilla.org");
     do_check_false(installs[3].addon.appDisabled);
     do_check_eq(installs[3].version, "5.0");
     do_check_eq(installs[3].name, "Multi Test 4");
@@ -697,18 +698,17 @@ function run_test_11() {
       prepare_test({
         "addon4@tests.mozilla.org": [
           "onInstalling"
         ],
         "addon5@tests.mozilla.org": [
           "onInstalling"
         ],
         "addon6@tests.mozilla.org": [
-          ["onInstalling", false],
-          "onInstalled"
+          "onInstalling"
         ],
         "addon7@tests.mozilla.org": [
           "onInstalling"
         ]
       }, {
         "addon4@tests.mozilla.org": [
           "onInstallStarted",
           "onInstallEnded"
@@ -782,18 +782,17 @@ function run_test_12() {
     prepare_test({
       "addon4@tests.mozilla.org": [
         "onInstalling"
       ],
       "addon5@tests.mozilla.org": [
         "onInstalling"
       ],
       "addon6@tests.mozilla.org": [
-        ["onInstalling", false],
-        "onInstalled"
+        "onInstalling"
       ],
       "addon7@tests.mozilla.org": [
         "onInstalling"
       ]
     }, {
       "NO_ID": [
         "onDownloadStarted",
         "onNewInstall",
@@ -846,20 +845,20 @@ function check_test_12() {
   // Comes from addon5.jar and is compatible by default
   do_check_eq(installs[1].sourceURI, gInstall.sourceURI);
   do_check_eq(installs[1].addon.id, "addon5@tests.mozilla.org");
   do_check_false(installs[1].addon.appDisabled);
   do_check_eq(installs[1].version, "3.0");
   do_check_eq(installs[1].name, "Multi Test 2");
   do_check_eq(installs[1].state, AddonManager.STATE_INSTALLED);
 
-  // Comes from addon6.xpi and is incompatible
+  // Comes from addon6.xpi and would be incompatible with strict compat enabled
   do_check_eq(installs[2].sourceURI, gInstall.sourceURI);
   do_check_eq(installs[2].addon.id, "addon6@tests.mozilla.org");
-  do_check_true(installs[2].addon.appDisabled);
+  do_check_false(installs[2].addon.appDisabled);
   do_check_eq(installs[2].version, "2.0");
   do_check_eq(installs[2].name, "Multi Test 3");
   do_check_eq(installs[2].state, AddonManager.STATE_INSTALLED);
 
   // Comes from addon7.jar and is made compatible by an update check
   do_check_eq(installs[3].sourceURI, gInstall.sourceURI);
   do_check_eq(installs[3].addon.id, "addon7@tests.mozilla.org");
   do_check_false(installs[3].addon.appDisabled);
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_install_strictcompat.js
@@ -0,0 +1,1623 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// This verifies that add-ons can be installed from XPI files
+
+// Maximum error in file modification times. Some file systems don't store
+// modification times exactly. As long as we are closer than this then it
+// still passes.
+const MAX_TIME_DIFFERENCE = 3000;
+
+Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource://gre/modules/NetUtil.jsm");
+
+// install.rdf size, icon.png, icon64.png size
+const ADDON1_SIZE = 705 + 16 + 16;
+
+do_load_httpd_js();
+var testserver;
+var gInstallDate;
+var gInstall = null;
+
+// The test extension uses an insecure update url.
+Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
+Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true);
+
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+function run_test() {
+  createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
+
+  startupManager();
+  // Make sure we only register once despite multiple calls
+  AddonManager.addInstallListener(InstallListener);
+  AddonManager.addAddonListener(AddonListener);
+  AddonManager.addInstallListener(InstallListener);
+  AddonManager.addAddonListener(AddonListener);
+
+  // Create and configure the HTTP server.
+  testserver = new nsHttpServer();
+  testserver.registerDirectory("/addons/", do_get_file("addons"));
+  testserver.registerDirectory("/data/", do_get_file("data"));
+  testserver.registerPathHandler("/redirect", function(aRequest, aResponse) {
+    aResponse.setStatusLine(null, 301, "Moved Permanently");
+    let url = aRequest.host + ":" + aRequest.port + aRequest.queryString;
+    aResponse.setHeader("Location", "http://" + url);
+  });
+  testserver.start(4444);
+
+  do_test_pending();
+  run_test_1();
+}
+
+function end_test() {
+  testserver.stop(do_test_finished);
+}
+
+// Checks that an install from a local file proceeds as expected
+function run_test_1() {
+  prepare_test({ }, [
+    "onNewInstall"
+  ]);
+
+  AddonManager.getInstallForFile(do_get_addon("test_install1"), function(install) {
+    ensure_test_completed();
+
+    do_check_neq(install, null);
+    do_check_eq(install.linkedInstalls, null);
+    do_check_eq(install.type, "extension");
+    do_check_eq(install.version, "1.0");
+    do_check_eq(install.name, "Test 1");
+    do_check_eq(install.state, AddonManager.STATE_DOWNLOADED);
+    do_check_true(install.addon.hasResource("install.rdf"));
+    do_check_eq(install.addon.install, install);
+    do_check_eq(install.addon.size, ADDON1_SIZE);
+    do_check_true(hasFlag(install.addon.operationsRequiringRestart,
+                          AddonManager.OP_NEEDS_RESTART_INSTALL));
+    let file = do_get_addon("test_install1");
+    let uri = Services.io.newFileURI(file).spec;
+    do_check_eq(install.addon.getResourceURI("install.rdf").spec, "jar:" + uri + "!/install.rdf");
+    do_check_eq(install.addon.iconURL, "jar:" + uri + "!/icon.png");
+    do_check_eq(install.addon.icon64URL, "jar:" + uri + "!/icon64.png");
+    do_check_eq(install.iconURL, null);
+
+    do_check_eq(install.sourceURI.spec, uri);
+    do_check_eq(install.addon.sourceURI.spec, uri);
+
+    AddonManager.getAllInstalls(function(activeInstalls) {
+      do_check_eq(activeInstalls.length, 1);
+      do_check_eq(activeInstalls[0], install);
+
+      AddonManager.getInstallsByTypes(["foo"], function(fooInstalls) {
+        do_check_eq(fooInstalls.length, 0);
+
+        AddonManager.getInstallsByTypes(["extension"], function(extensionInstalls) {
+          do_check_eq(extensionInstalls.length, 1);
+          do_check_eq(extensionInstalls[0], install);
+
+          prepare_test({
+            "addon1@tests.mozilla.org": [
+              "onInstalling"
+            ]
+          }, [
+            "onInstallStarted",
+            "onInstallEnded",
+          ], check_test_1);
+          install.install();
+        });
+      });
+    });
+  });
+}
+
+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) {
+      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"].
+                        createInstance(Ci.nsIZipReader);
+        try {
+          zipReader.open(archiveFile);
+          do_check_true(zipReader.hasEntry(jarURI.JAREntry));
+        }
+        finally {
+          zipReader.close();
+        }
+      }
+      else {
+        let iconFile = uri.QueryInterface(AM_Ci.nsIFileURL).file;
+        do_check_true(iconFile.exists());
+      }
+
+      // Make the pending install have a sensible date
+      let updateDate = Date.now();
+      let extURI = pendingAddons[0].getResourceURI("");
+      let ext = extURI.QueryInterface(AM_Ci.nsIFileURL).file;
+      setExtensionModifiedTime(ext, updateDate);
+
+      // The pending add-on cannot be disabled or enabled.
+      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) {
+          do_check_neq(a1, null);
+          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));
+          do_check_true(do_get_addon("test_install1").exists());
+          do_check_in_crash_annotation(a1.id, a1.version);
+          do_check_eq(a1.size, ADDON1_SIZE);
+
+          do_check_eq(a1.sourceURI.spec,
+                      Services.io.newFileURI(do_get_addon("test_install1")).spec);
+          let difference = a1.installDate.getTime() - updateDate;
+          if (Math.abs(difference) > MAX_TIME_DIFFERENCE)
+            do_throw("Add-on install time was out by " + difference + "ms");
+
+          difference = a1.updateDate.getTime() - updateDate;
+          if (Math.abs(difference) > MAX_TIME_DIFFERENCE)
+            do_throw("Add-on update time was out by " + difference + "ms");
+
+          do_check_true(a1.hasResource("install.rdf"));
+          do_check_false(a1.hasResource("foo.bar"));
+
+          let uri = do_get_addon_root_uri(profileDir, "addon1@tests.mozilla.org");
+          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();
+        });
+      });
+    });
+  });
+}
+
+// Tests that an install from a url downloads.
+function run_test_2() {
+  let url = "http://localhost:4444/addons/test_install2_1.xpi";
+  AddonManager.getInstallForURL(url, function(install) {
+    do_check_neq(install, null);
+    do_check_eq(install.linkedInstalls, null);
+    do_check_eq(install.version, "1.0");
+    do_check_eq(install.name, "Test 2");
+    do_check_eq(install.state, AddonManager.STATE_AVAILABLE);
+    do_check_eq(install.iconURL, null);
+    do_check_eq(install.sourceURI.spec, url);
+
+    AddonManager.getAllInstalls(function(activeInstalls) {
+      do_check_eq(activeInstalls.length, 1);
+      do_check_eq(activeInstalls[0], install);
+
+      prepare_test({}, [
+        "onDownloadStarted",
+        "onDownloadEnded",
+      ], check_test_2);
+
+      install.addListener({
+        onDownloadProgress: function(install) {
+          do_execute_soon(function() {
+            Components.utils.forceGC();
+          });
+        }
+      });
+
+      install.install();
+    });
+  }, "application/x-xpinstall", null, "Test 2", null, "1.0");
+}
+
+function check_test_2(install) {
+  ensure_test_completed();
+  do_check_eq(install.version, "2.0");
+  do_check_eq(install.name, "Real Test 2");
+  do_check_eq(install.state, AddonManager.STATE_DOWNLOADED);
+  do_check_eq(install.addon.install, install);
+  do_check_true(hasFlag(install.addon.operationsRequiringRestart,
+                        AddonManager.OP_NEEDS_RESTART_INSTALL));
+  do_check_eq(install.iconURL, null);
+
+  // Pause the install here and start it again in run_test_3
+  do_execute_soon(function() { run_test_3(install); });
+  return false;
+}
+
+// Tests that the downloaded XPI installs ok
+function run_test_3(install) {
+  prepare_test({
+    "addon2@tests.mozilla.org": [
+      "onInstalling"
+    ]
+  }, [
+    "onInstallStarted",
+    "onInstallEnded",
+  ], check_test_3);
+  install.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) {
+    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);
+        do_check_eq(a2.type, "extension");
+        do_check_eq(a2.version, "2.0");
+        do_check_eq(a2.name, "Real Test 2");
+        do_check_true(isExtensionInAddonsList(profileDir, a2.id));
+        do_check_true(do_get_addon("test_install2_1").exists());
+        do_check_in_crash_annotation(a2.id, a2.version);
+        do_check_eq(a2.sourceURI.spec,
+                    "http://localhost:4444/addons/test_install2_1.xpi");
+
+        let difference = a2.installDate.getTime() - updateDate;
+        if (Math.abs(difference) > MAX_TIME_DIFFERENCE)
+          do_throw("Add-on install time was out by " + difference + "ms");
+
+        difference = a2.updateDate.getTime() - updateDate;
+        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"
+  ]);
+
+  let url = "http://localhost:4444/addons/test_install2_2.xpi";
+  AddonManager.getInstallForURL(url, function(install) {
+    ensure_test_completed();
+
+    do_check_neq(install, null);
+    do_check_eq(install.version, "3.0");
+    do_check_eq(install.name, "Test 3");
+    do_check_eq(install.state, AddonManager.STATE_AVAILABLE);
+
+    AddonManager.getAllInstalls(function(activeInstalls) {
+      do_check_eq(activeInstalls.length, 1);
+      do_check_eq(activeInstalls[0], install);
+      do_check_eq(install.existingAddon, null);
+
+      prepare_test({}, [
+        "onDownloadStarted",
+        "onDownloadEnded",
+      ], check_test_4);
+      install.install();
+    });
+  }, "application/x-xpinstall", null, "Test 3", null, "3.0");
+}
+
+function check_test_4(install) {
+  ensure_test_completed();
+
+  do_check_eq(install.version, "3.0");
+  do_check_eq(install.name, "Real Test 3");
+  do_check_eq(install.state, AddonManager.STATE_DOWNLOADED);
+  do_check_neq(install.existingAddon);
+  do_check_eq(install.existingAddon.id, "addon2@tests.mozilla.org");
+  do_check_eq(install.addon.install, install);
+  do_check_true(hasFlag(install.addon.operationsRequiringRestart,
+                        AddonManager.OP_NEEDS_RESTART_INSTALL));
+
+  run_test_5();
+  // Installation will continue when there is nothing returned.
+}
+
+// Continue installing the new version
+function run_test_5() {
+  prepare_test({
+    "addon2@tests.mozilla.org": [
+      "onInstalling"
+    ]
+  }, [
+    "onInstallStarted",
+    "onInstallEnded",
+  ], check_test_5);
+}
+
+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) {
+      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) {
+          do_check_neq(a2, null);
+          do_check_eq(a2.type, "extension");
+          do_check_eq(a2.version, "3.0");
+          do_check_eq(a2.name, "Real Test 3");
+          do_check_true(a2.isActive);
+          do_check_true(isExtensionInAddonsList(profileDir, a2.id));
+          do_check_true(do_get_addon("test_install2_2").exists());
+          do_check_in_crash_annotation(a2.id, a2.version);
+          do_check_eq(a2.sourceURI.spec,
+                      "http://localhost:4444/addons/test_install2_2.xpi");
+
+          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();
+        });
+      });
+    });
+  });
+}
+
+// Tests that an install that requires a compatibility update works
+function run_test_6() {
+  prepare_test({ }, [
+    "onNewInstall"
+  ]);
+
+  let url = "http://localhost:4444/addons/test_install3.xpi";
+  AddonManager.getInstallForURL(url, function(install) {
+    ensure_test_completed();
+
+    do_check_neq(install, null);
+    do_check_eq(install.version, "1.0");
+    do_check_eq(install.name, "Real Test 4");
+    do_check_eq(install.state, AddonManager.STATE_AVAILABLE);
+
+    AddonManager.getInstallsByTypes(null, function(activeInstalls) {
+      do_check_eq(activeInstalls.length, 1);
+      do_check_eq(activeInstalls[0], install);
+
+      prepare_test({}, [
+        "onDownloadStarted",
+        "onDownloadEnded",
+      ], check_test_6);
+      install.install();
+    });
+  }, "application/x-xpinstall", null, "Real Test 4", null, "1.0");
+}
+
+function check_test_6(install) {
+  ensure_test_completed();
+  do_check_eq(install.version, "1.0");
+  do_check_eq(install.name, "Real Test 4");
+  do_check_eq(install.state, AddonManager.STATE_DOWNLOADED);
+  do_check_eq(install.existingAddon, null);
+  do_check_false(install.addon.appDisabled);
+  run_test_7();
+  return true;
+}
+
+// Continue the install
+function run_test_7() {
+  prepare_test({
+    "addon3@tests.mozilla.org": [
+      "onInstalling"
+    ]
+  }, [
+    "onInstallStarted",
+    "onInstallEnded",
+  ], check_test_7);
+}
+
+function check_test_7() {
+  ensure_test_completed();
+  AddonManager.getAddonByID("addon3@tests.mozilla.org", 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);
+        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();
+      });
+    });
+  });
+}
+
+function run_test_8() {
+  AddonManager.addInstallListener(InstallListener);
+  AddonManager.addAddonListener(AddonListener);
+
+  prepare_test({ }, [
+    "onNewInstall"
+  ]);
+
+  AddonManager.getInstallForFile(do_get_addon("test_install3"), function(install) {
+    do_check_true(install.addon.isCompatible);
+
+    prepare_test({
+      "addon3@tests.mozilla.org": [
+        "onInstalling"
+      ]
+    }, [
+      "onInstallStarted",
+      "onInstallEnded",
+    ], check_test_8);
+    install.install();
+  });
+}
+
+function check_test_8() {
+  restartManager();
+
+  AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) {
+    do_check_neq(a3, null);
+    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();
+  });
+}
+
+// Test that after cancelling a download it is removed from the active installs
+function run_test_9() {
+  prepare_test({ }, [
+    "onNewInstall"
+  ]);
+
+  let url = "http://localhost:4444/addons/test_install3.xpi";
+  AddonManager.getInstallForURL(url, function(install) {
+    ensure_test_completed();
+
+    do_check_neq(install, null);
+    do_check_eq(install.version, "1.0");
+    do_check_eq(install.name, "Real Test 4");
+    do_check_eq(install.state, AddonManager.STATE_AVAILABLE);
+
+    AddonManager.getInstallsByTypes(null, function(activeInstalls) {
+      do_check_eq(activeInstalls.length, 1);
+      do_check_eq(activeInstalls[0], install);
+
+      prepare_test({}, [
+        "onDownloadStarted",
+        "onDownloadEnded",
+      ], check_test_9);
+      install.install();
+    });
+  }, "application/x-xpinstall", null, "Real Test 4", null, "1.0");
+}
+
+function check_test_9(install) {
+  prepare_test({}, [
+    "onDownloadCancelled"
+  ]);
+
+  install.cancel();
+
+  ensure_test_completed();
+
+  AddonManager.getAllInstalls(function(activeInstalls) {
+    do_check_eq(activeInstalls.length, 0);
+
+    run_test_10();
+  });
+}
+
+// Tests that after cancelling a pending install it is removed from the active
+// installs
+function run_test_10() {
+  prepare_test({ }, [
+    "onNewInstall"
+  ]);
+
+  let url = "http://localhost:4444/addons/test_install3.xpi";
+  AddonManager.getInstallForURL(url, function(install) {
+    ensure_test_completed();
+
+    do_check_neq(install, null);
+    do_check_eq(install.version, "1.0");
+    do_check_eq(install.name, "Real Test 4");
+    do_check_eq(install.state, AddonManager.STATE_AVAILABLE);
+
+    AddonManager.getInstallsByTypes(null, function(activeInstalls) {
+      do_check_eq(activeInstalls.length, 1);
+      do_check_eq(activeInstalls[0], install);
+
+      prepare_test({
+        "addon3@tests.mozilla.org": [
+          "onInstalling"
+        ]
+      }, [
+        "onDownloadStarted",
+        "onDownloadEnded",
+        "onInstallStarted",
+        "onInstallEnded"
+      ], check_test_10);
+      install.install();
+    });
+  }, "application/x-xpinstall", null, "Real Test 4", null, "1.0");
+}
+
+function check_test_10(install) {
+  prepare_test({
+    "addon3@tests.mozilla.org": [
+      "onOperationCancelled"
+    ]
+  }, [
+    "onInstallCancelled"
+  ]);
+
+  install.cancel();
+
+  ensure_test_completed();
+
+  AddonManager.getAllInstalls(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",
+    "onNewInstall",
+    "onNewInstall"
+  ]);
+
+  AddonManager.getInstallForFile(do_get_addon("test_install4"), function(install) {
+    ensure_test_completed();
+    do_check_neq(install, null);
+    do_check_neq(install.linkedInstalls, null);
+    do_check_eq(install.linkedInstalls.length, 3);
+
+    // Might be in any order so sort them based on ID
+    let installs = [install].concat(install.linkedInstalls);
+    installs.sort(function(a, b) {
+      if (a.addon.id < b.addon.id)
+        return -1;
+      if (a.addon.id > b.addon.id)
+        return 1;
+      return 0;
+    });
+
+    // Comes from addon4.xpi and is made compatible by an update check
+    do_check_eq(installs[0].sourceURI, install.sourceURI);
+    do_check_eq(installs[0].addon.id, "addon4@tests.mozilla.org");
+    do_check_false(installs[0].addon.appDisabled);
+    do_check_eq(installs[0].version, "1.0");
+    do_check_eq(installs[0].name, "Multi Test 1");
+    do_check_eq(installs[0].state, AddonManager.STATE_DOWNLOADED);
+    do_check_true(hasFlag(installs[0].addon.operationsRequiringRestart,
+                          AddonManager.OP_NEEDS_RESTART_INSTALL));
+
+    // Comes from addon5.jar and is compatible by default
+    do_check_eq(installs[1].sourceURI, install.sourceURI);
+    do_check_eq(installs[1].addon.id, "addon5@tests.mozilla.org");
+    do_check_false(installs[1].addon.appDisabled);
+    do_check_eq(installs[1].version, "3.0");
+    do_check_eq(installs[1].name, "Multi Test 2");
+    do_check_eq(installs[1].state, AddonManager.STATE_DOWNLOADED);
+    do_check_true(hasFlag(installs[1].addon.operationsRequiringRestart,
+                          AddonManager.OP_NEEDS_RESTART_INSTALL));
+
+    // Comes from addon6.xpi and is incompatible
+    do_check_eq(installs[2].sourceURI, install.sourceURI);
+    do_check_eq(installs[2].addon.id, "addon6@tests.mozilla.org");
+    do_check_true(installs[2].addon.appDisabled);
+    do_check_eq(installs[2].version, "2.0");
+    do_check_eq(installs[2].name, "Multi Test 3");
+    do_check_eq(installs[2].state, AddonManager.STATE_DOWNLOADED);
+    do_check_false(hasFlag(installs[2].addon.operationsRequiringRestart,
+                           AddonManager.OP_NEEDS_RESTART_INSTALL));
+
+    // Comes from addon7.jar and is made compatible by an update check
+    do_check_eq(installs[3].sourceURI, install.sourceURI);
+    do_check_eq(installs[3].addon.id, "addon7@tests.mozilla.org");
+    do_check_false(installs[3].addon.appDisabled);
+    do_check_eq(installs[3].version, "5.0");
+    do_check_eq(installs[3].name, "Multi Test 4");
+    do_check_eq(installs[3].state, AddonManager.STATE_DOWNLOADED);
+    do_check_true(hasFlag(installs[3].addon.operationsRequiringRestart,
+                          AddonManager.OP_NEEDS_RESTART_INSTALL));
+
+    AddonManager.getAllInstalls(function(aInstalls) {
+      do_check_eq(aInstalls.length, 4);
+
+      prepare_test({
+        "addon4@tests.mozilla.org": [
+          "onInstalling"
+        ],
+        "addon5@tests.mozilla.org": [
+          "onInstalling"
+        ],
+        "addon6@tests.mozilla.org": [
+          ["onInstalling", false],
+          "onInstalled"
+        ],
+        "addon7@tests.mozilla.org": [
+          "onInstalling"
+        ]
+      }, {
+        "addon4@tests.mozilla.org": [
+          "onInstallStarted",
+          "onInstallEnded"
+        ],
+        "addon5@tests.mozilla.org": [
+          "onInstallStarted",
+          "onInstallEnded"
+        ],
+        "addon6@tests.mozilla.org": [
+          "onInstallStarted",
+          "onInstallEnded"
+        ],
+        "addon7@tests.mozilla.org": [
+          "onInstallStarted",
+          "onInstallEnded"
+        ]
+      }, 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
+      // is the last install operation
+      installs[2].install();
+    });
+  });
+}
+
+function check_test_11() {
+  restartManager();
+
+  AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org",
+                               "addon5@tests.mozilla.org",
+                               "addon6@tests.mozilla.org",
+                               "addon7@tests.mozilla.org"],
+                               function([a4, a5, a6, a7]) {
+    do_check_neq(a4, null);
+    do_check_neq(a5, null);
+    do_check_neq(a6, null);
+    do_check_neq(a7, null);
+
+    a4.uninstall();
+    a5.uninstall();
+    a6.uninstall();
+    a7.uninstall();
+
+    restartManager();
+
+    run_test_12();
+  });
+}
+
+// Same as test 11 but for a remote XPI
+function run_test_12() {
+  prepare_test({ }, [
+    "onNewInstall",
+  ]);
+
+  let url = "http://localhost:4444/addons/test_install4.xpi";
+  AddonManager.getInstallForURL(url, function(install) {
+    gInstall = install;
+
+    ensure_test_completed();
+    do_check_neq(install, null);
+    do_check_eq(install.linkedInstalls, null);
+    do_check_eq(install.state, AddonManager.STATE_AVAILABLE);
+
+    prepare_test({
+      "addon4@tests.mozilla.org": [
+        "onInstalling"
+      ],
+      "addon5@tests.mozilla.org": [
+        "onInstalling"
+      ],
+      "addon6@tests.mozilla.org": [
+        ["onInstalling", false],
+        "onInstalled"
+      ],
+      "addon7@tests.mozilla.org": [
+        "onInstalling"
+      ]
+    }, {
+      "NO_ID": [
+        "onDownloadStarted",
+        "onNewInstall",
+        "onNewInstall",
+        "onNewInstall",
+        "onDownloadEnded"
+      ],
+      "addon4@tests.mozilla.org": [
+        "onInstallStarted",
+        "onInstallEnded"
+      ],
+      "addon5@tests.mozilla.org": [
+        "onInstallStarted",
+        "onInstallEnded"
+      ],
+      "addon6@tests.mozilla.org": [
+        "onInstallStarted",
+        "onInstallEnded"
+      ],
+      "addon7@tests.mozilla.org": [
+        "onInstallStarted",
+        "onInstallEnded"
+      ]
+    }, 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
+  let installs = [gInstall].concat(gInstall.linkedInstalls);
+  installs.sort(function(a, b) {
+    if (a.addon.id < b.addon.id)
+      return -1;
+    if (a.addon.id > b.addon.id)
+      return 1;
+    return 0;
+  });
+
+  // Comes from addon4.xpi and is made compatible by an update check
+  do_check_eq(installs[0].sourceURI, gInstall.sourceURI);
+  do_check_eq(installs[0].addon.id, "addon4@tests.mozilla.org");
+  do_check_false(installs[0].addon.appDisabled);
+  do_check_eq(installs[0].version, "1.0");
+  do_check_eq(installs[0].name, "Multi Test 1");
+  do_check_eq(installs[0].state, AddonManager.STATE_INSTALLED);
+
+  // Comes from addon5.jar and is compatible by default
+  do_check_eq(installs[1].sourceURI, gInstall.sourceURI);
+  do_check_eq(installs[1].addon.id, "addon5@tests.mozilla.org");
+  do_check_false(installs[1].addon.appDisabled);
+  do_check_eq(installs[1].version, "3.0");
+  do_check_eq(installs[1].name, "Multi Test 2");
+  do_check_eq(installs[1].state, AddonManager.STATE_INSTALLED);
+
+  // Comes from addon6.xpi and is incompatible
+  do_check_eq(installs[2].sourceURI, gInstall.sourceURI);
+  do_check_eq(installs[2].addon.id, "addon6@tests.mozilla.org");
+  do_check_true(installs[2].addon.appDisabled);
+  do_check_eq(installs[2].version, "2.0");
+  do_check_eq(installs[2].name, "Multi Test 3");
+  do_check_eq(installs[2].state, AddonManager.STATE_INSTALLED);
+
+  // Comes from addon7.jar and is made compatible by an update check
+  do_check_eq(installs[3].sourceURI, gInstall.sourceURI);
+  do_check_eq(installs[3].addon.id, "addon7@tests.mozilla.org");
+  do_check_false(installs[3].addon.appDisabled);
+  do_check_eq(installs[3].version, "5.0");
+  do_check_eq(installs[3].name, "Multi Test 4");
+  do_check_eq(installs[3].state, AddonManager.STATE_INSTALLED);
+
+  restartManager();
+
+  AddonManager.getAddonsByIDs(["addon4@tests.mozilla.org",
+                               "addon5@tests.mozilla.org",
+                               "addon6@tests.mozilla.org",
+                               "addon7@tests.mozilla.org"],
+                               function([a4, a5, a6, a7]) {
+    do_check_neq(a4, null);
+    do_check_neq(a5, null);
+    do_check_neq(a6, null);
+    do_check_neq(a7, null);
+
+    a4.uninstall();
+    a5.uninstall();
+    a6.uninstall();
+    a7.uninstall();
+
+    restartManager();
+
+    run_test_13();
+  });
+}
+
+
+// Tests that cancelling an upgrade leaves the original add-on's pendingOperations
+// correct
+function run_test_13() {
+  installAllFiles([do_get_addon("test_install2_1")], function() {
+    restartManager();
+
+    prepare_test({ }, [
+      "onNewInstall"
+    ]);
+
+    let url = "http://localhost:4444/addons/test_install2_2.xpi";
+    AddonManager.getInstallForURL(url, function(install) {
+      ensure_test_completed();
+
+      do_check_neq(install, null);
+      do_check_eq(install.version, "3.0");
+      do_check_eq(install.name, "Test 3");
+      do_check_eq(install.state, AddonManager.STATE_AVAILABLE);
+
+      AddonManager.getAllInstalls(function(activeInstalls) {
+        do_check_eq(activeInstalls.length, 1);
+        do_check_eq(activeInstalls[0], install);
+        do_check_eq(install.existingAddon, null);
+
+        prepare_test({
+          "addon2@tests.mozilla.org": [
+            "onInstalling"
+          ]
+        }, [
+          "onDownloadStarted",
+          "onDownloadEnded",
+          "onInstallStarted",
+          "onInstallEnded",
+        ], check_test_13);
+        install.install();
+      });
+    }, "application/x-xpinstall", null, "Test 3", null, "3.0");
+  });
+}
+
+function check_test_13(install) {
+  ensure_test_completed();
+
+  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) {
+    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({
+      "addon2@tests.mozilla.org": [
+        "onOperationCancelled"
+      ]
+    }, [
+      "onInstallCancelled",
+    ]);
+
+    install.cancel();
+
+    do_check_false(hasFlag(install.addon.pendingOperations, AddonManager.PENDING_INSTALL));
+
+    do_check_false(hasFlag(olda2.pendingOperations, AddonManager.PENDING_UPGRADE));
+    do_check_eq(olda2.pendingUpgrade, null);
+
+    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();
+    });
+  });
+}
+
+// Check that cancelling the install from onDownloadStarted actually cancels it
+function run_test_14() {
+  prepare_test({ }, [
+    "onNewInstall"
+  ]);
+
+  let url = "http://localhost:4444/addons/test_install2_1.xpi";
+  AddonManager.getInstallForURL(url, function(install) {
+    ensure_test_completed();
+
+    do_check_eq(install.file, null);
+
+    prepare_test({ }, [
+      "onDownloadStarted"
+    ], check_test_14);
+    install.install();
+  }, "application/x-xpinstall");
+}
+
+function check_test_14(install) {
+  prepare_test({ }, [
+    "onDownloadCancelled"
+  ]);
+
+  install.cancel();
+
+  ensure_test_completed();
+
+  install.addListener({
+    onDownloadProgress: function() {
+      do_throw("Download should not have continued");
+    },
+    onDownloadEnded: function() {
+      do_throw("Download should not have continued");
+    }
+  });
+
+  // Allow the listener to return to see if it continues downloading. The
+  // The listener only really tests if we give it time to see progress, the
+  // file check isn't ideal either
+  do_execute_soon(function() {
+    do_check_eq(install.file, null);
+
+    run_test_15();
+  });
+}
+
+// Checks that cancelling the install from onDownloadEnded actually cancels it
+function run_test_15() {
+  prepare_test({ }, [
+    "onNewInstall"
+  ]);
+
+  let url = "http://localhost:4444/addons/test_install2_1.xpi";
+  AddonManager.getInstallForURL(url, function(install) {
+    ensure_test_completed();
+
+    do_check_eq(install.file, null);
+
+    prepare_test({ }, [
+      "onDownloadStarted",
+      "onDownloadEnded"
+    ], check_test_15);
+    install.install();
+  }, "application/x-xpinstall");
+}
+
+function check_test_15(install) {
+  prepare_test({ }, [
+    "onDownloadCancelled"
+  ]);
+
+  install.cancel();
+
+  ensure_test_completed();
+
+  install.addListener({
+    onInstallStarted: function() {
+      do_throw("Install should not have continued");
+    }
+  });
+
+  // Allow the listener to return to see if it starts installing
+  do_execute_soon(run_test_16);
+}
+
+// Verify that the userDisabled value carries over to the upgrade by default
+function run_test_16() {
+  restartManager();
+
+  let url = "http://localhost:4444/addons/test_install2_1.xpi";
+  AddonManager.getInstallForURL(url, function(aInstall) {
+    aInstall.addListener({
+      onInstallStarted: function() {
+        do_check_false(aInstall.addon.userDisabled);
+        aInstall.addon.userDisabled = true;
+      },
+
+      onInstallEnded: function() {
+        restartManager();
+
+        AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
+          do_check_true(a2.userDisabled);
+          do_check_false(a2.isActive);
+
+          let url = "http://localhost:4444/addons/test_install2_2.xpi";
+          AddonManager.getInstallForURL(url, function(aInstall) {
+            aInstall.addListener({
+              onInstallEnded: function() {
+                do_check_true(aInstall.addon.userDisabled);
+
+                restartManager();
+
+                AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
+                  do_check_true(a2.userDisabled);
+                  do_check_false(a2.isActive);
+
+                  a2.uninstall();
+                  restartManager();
+
+                  run_test_17();
+                });
+              }
+            });
+            aInstall.install();
+          }, "application/x-xpinstall");
+        });
+      }
+    });
+    aInstall.install();
+  }, "application/x-xpinstall");
+}
+
+// Verify that changing the userDisabled value before onInstallEnded works
+function run_test_17() {
+  let url = "http://localhost:4444/addons/test_install2_1.xpi";
+  AddonManager.getInstallForURL(url, function(aInstall) {
+    aInstall.addListener({
+      onInstallEnded: function() {
+        do_check_false(aInstall.addon.userDisabled);
+
+        restartManager();
+
+        AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
+          do_check_false(a2.userDisabled);
+          do_check_true(a2.isActive);
+
+          let url = "http://localhost:4444/addons/test_install2_2.xpi";
+          AddonManager.getInstallForURL(url, function(aInstall) {
+            aInstall.addListener({
+              onInstallStarted: function() {
+                do_check_false(aInstall.addon.userDisabled);
+                aInstall.addon.userDisabled = true;
+              },
+
+              onInstallEnded: function() {
+                restartManager();
+
+                AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
+                  do_check_true(a2.userDisabled);
+                  do_check_false(a2.isActive);
+
+                  a2.uninstall();
+                  restartManager();
+
+                  run_test_18();
+                });
+              }
+            });
+            aInstall.install();
+          }, "application/x-xpinstall");
+        });
+      }
+    });
+    aInstall.install();
+  }, "application/x-xpinstall");
+}
+
+// Verify that changing the userDisabled value before onInstallEnded works
+function run_test_18() {
+  let url = "http://localhost:4444/addons/test_install2_1.xpi";
+  AddonManager.getInstallForURL(url, function(aInstall) {
+    aInstall.addListener({
+      onInstallStarted: function() {
+        do_check_false(aInstall.addon.userDisabled);
+        aInstall.addon.userDisabled = true;
+      },
+
+      onInstallEnded: function() {
+        restartManager();
+
+        AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
+          do_check_true(a2.userDisabled);
+          do_check_false(a2.isActive);
+
+          let url = "http://localhost:4444/addons/test_install2_2.xpi";
+          AddonManager.getInstallForURL(url, function(aInstall) {
+            aInstall.addListener({
+              onInstallStarted: function() {
+                do_check_true(aInstall.addon.userDisabled);
+                aInstall.addon.userDisabled = false;
+              },
+
+              onInstallEnded: function() {
+                restartManager();
+
+                AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
+                  do_check_false(a2.userDisabled);
+                  do_check_true(a2.isActive);
+
+                  a2.uninstall();
+                  restartManager();
+
+                  run_test_18_1();
+                });
+              }
+            });
+            aInstall.install();
+          }, "application/x-xpinstall");
+        });
+      }
+    });
+    aInstall.install();
+  }, "application/x-xpinstall");
+}
+
+
+// Checks that metadata is not stored if the pref is set to false
+function run_test_18_1() {
+  Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", true);
+  Services.prefs.setCharPref("extensions.getAddons.get.url",
+                             "http://localhost:4444/data/test_install.xml");
+
+  Services.prefs.setBoolPref("extensions.addon2@tests.mozilla.org.getAddons.cache.enabled", false);
+
+  let url = "http://localhost:4444/addons/test_install2_1.xpi";
+  AddonManager.getInstallForURL(url, function(aInstall) {
+    aInstall.addListener({
+      onInstallEnded: function(aInstall, aAddon) {
+        do_check_neq(aAddon.fullDescription, "Repository description");
+
+        restartManager();
+
+        AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
+          do_check_neq(a2.fullDescription, "Repository description");
+
+          a2.uninstall();
+          restartManager();
+
+          Services.prefs.setBoolPref("extensions.addon2@tests.mozilla.org.getAddons.cache.enabled", true);
+          run_test_19();
+        });
+      }
+    });
+    aInstall.install();
+  }, "application/x-xpinstall");
+}
+
+// Checks that metadata is downloaded for new installs and is visible before and
+// after restart
+function run_test_19() {
+  let url = "http://localhost:4444/addons/test_install2_1.xpi";
+  AddonManager.getInstallForURL(url, function(aInstall) {
+    aInstall.addListener({
+      onInstallEnded: function(aInstall, aAddon) {
+        do_check_eq(aAddon.fullDescription, "Repository description");
+
+        restartManager();
+
+        AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
+          do_check_eq(a2.fullDescription, "Repository description");
+
+          a2.uninstall();
+          restartManager();
+
+          run_test_20();
+        });
+      }
+    });
+    aInstall.install();
+  }, "application/x-xpinstall");
+}
+
+// Do the same again to make sure it works when the data is already in the cache
+function run_test_20() {
+  let url = "http://localhost:4444/addons/test_install2_1.xpi";
+  AddonManager.getInstallForURL(url, function(aInstall) {
+    aInstall.addListener({
+      onInstallEnded: function(aInstall, aAddon) {
+        do_check_eq(aAddon.fullDescription, "Repository description");
+
+        restartManager();
+
+        AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
+          do_check_eq(a2.fullDescription, "Repository description");
+
+          a2.uninstall();
+          restartManager();
+
+          Services.prefs.setBoolPref("extensions.getAddons.cache.enabled", false);
+          run_test_21();
+        });
+      }
+    });
+    aInstall.install();
+  }, "application/x-xpinstall");
+}
+
+// Verify that installing an add-on that is already pending install cancels the
+// first install
+function run_test_21() {
+  installAllFiles([do_get_addon("test_install2_1")], function() {
+    AddonManager.getAllInstalls(function(aInstalls) {
+      do_check_eq(aInstalls.length, 1);
+
+      prepare_test({
+        "addon2@tests.mozilla.org": [
+          "onOperationCancelled",
+          "onInstalling"
+        ]
+      }, [
+        "onNewInstall",
+        "onDownloadStarted",
+        "onDownloadEnded",
+        "onInstallStarted",
+        "onInstallCancelled",
+        "onInstallEnded",
+      ], check_test_21);
+
+      let url = "http://localhost:4444/addons/test_install2_1.xpi";
+      AddonManager.getInstallForURL(url, function(aInstall) {
+        aInstall.install();
+      }, "application/x-xpinstall");
+    });
+  });
+}
+
+function check_test_21(aInstall) {
+  AddonManager.getAllInstalls(function(aInstalls) {
+    do_check_eq(aInstalls.length, 1);
+    do_check_eq(aInstalls[0], aInstall);
+
+    prepare_test({
+      "addon2@tests.mozilla.org": [
+        "onOperationCancelled"
+      ]
+    }, [
+      "onInstallCancelled",
+    ]);
+
+    aInstall.cancel();
+
+    ensure_test_completed();
+
+    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"
+  ]);
+
+  let url = "http://localhost:4444/addons/test_install3.xpi";
+  AddonManager.getInstallForURL(url, function(aInstall) {
+    ensure_test_completed();
+
+    do_check_neq(aInstall, null);
+    do_check_eq(aInstall.state, AddonManager.STATE_AVAILABLE);
+
+    prepare_test({}, [
+      "onDownloadStarted",
+      "onDownloadEnded",
+    ], check_test_22);
+    aInstall.install();
+  }, "application/x-xpinstall");
+}
+
+function check_test_22(aInstall) {
+  prepare_test({}, [
+    "onDownloadCancelled"
+  ]);
+
+  aInstall.cancel();
+
+  ensure_test_completed();
+
+  prepare_test({
+    "addon3@tests.mozilla.org": [
+      "onInstalling"
+    ]
+  }, [
+    "onDownloadStarted",
+    "onDownloadEnded",
+    "onInstallStarted",
+    "onInstallEnded"
+  ], finish_test_22);
+
+  aInstall.install();
+}
+
+function finish_test_22(aInstall) {
+  prepare_test({
+    "addon3@tests.mozilla.org": [
+      "onOperationCancelled"
+    ]
+  }, [
+    "onInstallCancelled"
+  ]);
+
+  aInstall.cancel();
+
+  ensure_test_completed();
+
+  run_test_23();
+}
+
+// Tests that an install can be restarted after being cancelled when a hash
+// was provided
+function run_test_23() {
+  prepare_test({ }, [
+    "onNewInstall"
+  ]);
+
+  let url = "http://localhost:4444/addons/test_install3.xpi";
+  AddonManager.getInstallForURL(url, function(aInstall) {
+    ensure_test_completed();
+
+    do_check_neq(aInstall, null);
+    do_check_eq(aInstall.state, AddonManager.STATE_AVAILABLE);
+
+    prepare_test({}, [
+      "onDownloadStarted",
+      "onDownloadEnded",
+    ], check_test_23);
+    aInstall.install();
+  }, "application/x-xpinstall", do_get_addon_hash("test_install3"));
+}
+
+function check_test_23(aInstall) {
+  prepare_test({}, [
+    "onDownloadCancelled"
+  ]);
+
+  aInstall.cancel();
+
+  ensure_test_completed();
+
+  prepare_test({
+    "addon3@tests.mozilla.org": [
+      "onInstalling"
+    ]
+  }, [
+    "onDownloadStarted",
+    "onDownloadEnded",
+    "onInstallStarted",
+    "onInstallEnded"
+  ], finish_test_23);
+
+  aInstall.install();
+}
+
+function finish_test_23(aInstall) {
+  prepare_test({
+    "addon3@tests.mozilla.org": [
+      "onOperationCancelled"
+    ]
+  }, [
+    "onInstallCancelled"
+  ]);
+
+  aInstall.cancel();
+
+  ensure_test_completed();
+
+  run_test_24();
+}
+
+// Tests that an install with a bad hash can be restarted after it fails, though
+// it will only fail again
+function run_test_24() {
+  prepare_test({ }, [
+    "onNewInstall"
+  ]);
+
+  let url = "http://localhost:4444/addons/test_install3.xpi";
+  AddonManager.getInstallForURL(url, function(aInstall) {
+    ensure_test_completed();
+
+    do_check_neq(aInstall, null);
+    do_check_eq(aInstall.state, AddonManager.STATE_AVAILABLE);
+
+    prepare_test({}, [
+      "onDownloadStarted",
+      "onDownloadFailed",
+    ], check_test_24);
+    aInstall.install();
+  }, "application/x-xpinstall", "sha1:foo");
+}
+
+function check_test_24(aInstall) {
+  prepare_test({ }, [
+    "onDownloadStarted",
+    "onDownloadFailed"
+  ], run_test_25);
+
+  aInstall.install();
+}
+
+// Tests that installs with a hash for a local file work
+function run_test_25() {
+  prepare_test({ }, [
+    "onNewInstall"
+  ]);
+
+  let url = Services.io.newFileURI(do_get_addon("test_install3")).spec;
+  AddonManager.getInstallForURL(url, function(aInstall) {
+    ensure_test_completed();
+
+    do_check_neq(aInstall, null);
+    do_check_eq(aInstall.state, AddonManager.STATE_DOWNLOADED);
+    do_check_eq(aInstall.error, 0);
+
+    prepare_test({ }, [
+      "onDownloadCancelled"
+    ]);
+
+    aInstall.cancel();
+
+    ensure_test_completed();
+
+    run_test_26();
+  }, "application/x-xpinstall", do_get_addon_hash("test_install3"));
+}
+
+function run_test_26() {
+  prepare_test({ }, [
+    "onNewInstall",
+    "onDownloadStarted",
+    "onDownloadCancelled"
+  ]);
+
+  let observerService = AM_Cc["@mozilla.org/network/http-activity-distributor;1"].
+                        getService(AM_Ci.nsIHttpActivityDistributor);
+  observerService.addObserver({
+    observeActivity: function(aChannel, aType, aSubtype, aTimestamp, aSizeData,
+                              aStringData) {
+      aChannel.QueryInterface(AM_Ci.nsIChannel);
+      // Wait for the final event for the redirected URL
+      if (aChannel.URI.spec != "http://localhost:4444/addons/test_install1.xpi" ||
+          aType != AM_Ci.nsIHttpActivityObserver.ACTIVITY_TYPE_HTTP_TRANSACTION ||
+          aSubtype != AM_Ci.nsIHttpActivityObserver.ACTIVITY_SUBTYPE_TRANSACTION_CLOSE)
+        return;
+
+      // Request should have been cancelled
+      do_check_eq(aChannel.status, Components.results.NS_BINDING_ABORTED);
+
+      observerService.removeObserver(this);
+
+      run_test_27();
+    }
+  });
+
+  let url = "http://localhost:4444/redirect?/addons/test_install1.xpi";
+  AddonManager.getInstallForURL(url, function(aInstall) {
+    aInstall.addListener({
+      onDownloadProgress: function(aInstall) {
+        aInstall.cancel();
+      }
+    });
+
+    aInstall.install();
+  }, "application/x-xpinstall");
+}
+
+
+// Tests that an install can be restarted during onDownloadCancelled after being
+// cancelled in mid-download
+function run_test_27() {
+  prepare_test({ }, [
+    "onNewInstall"
+  ]);
+
+  let url = "http://localhost:4444/addons/test_install3.xpi";
+  AddonManager.getInstallForURL(url, function(aInstall) {
+    ensure_test_completed();
+
+    do_check_neq(aInstall, null);
+    do_check_eq(aInstall.state, AddonManager.STATE_AVAILABLE);
+
+    aInstall.addListener({
+      onDownloadProgress: function() {
+        aInstall.removeListener(this);
+        aInstall.cancel();
+      }
+    });
+
+    prepare_test({}, [
+      "onDownloadStarted",
+      "onDownloadCancelled",
+    ], check_test_27);
+    aInstall.install();
+  }, "application/x-xpinstall");
+}
+
+function check_test_27(aInstall) {
+  prepare_test({
+    "addon3@tests.mozilla.org": [
+      "onInstalling"
+    ]
+  }, [
+    "onDownloadStarted",
+    "onDownloadEnded",
+    "onInstallStarted",
+    "onInstallEnded"
+  ], finish_test_27);
+
+  aInstall.install();
+}
+
+function finish_test_27(aInstall) {
+  prepare_test({
+    "addon3@tests.mozilla.org": [
+      "onOperationCancelled"
+    ]
+  }, [
+    "onInstallCancelled"
+  ]);
+
+  aInstall.cancel();
+
+  ensure_test_completed();
+
+  do_test_finished();
+}
--- a/toolkit/mozapps/extensions/test/xpcshell/test_locked.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked.js
@@ -4,17 +4,18 @@
 
 // Checks that we rebuild something sensible from a corrupt database
 
 
 do_load_httpd_js();
 var testserver;
 
 // The test extension uses an insecure update url.
-Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false);
+Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
+Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false);
 
 // Will be enabled
 var addon1 = {
   id: "addon1@tests.mozilla.org",
   version: "1.0",
   name: "Test 1",
   targetApplications: [{
     id: "xpcshell@tests.mozilla.org",
@@ -30,43 +31,43 @@ var addon2 = {
   name: "Test 2",
   targetApplications: [{
     id: "xpcshell@tests.mozilla.org",
     minVersion: "2",
     maxVersion: "2"
   }]
 };
 
-// Will get a compatibility update and be enabled
+// Will get a compatibility update and stay enabled
 var addon3 = {
   id: "addon3@tests.mozilla.org",
   version: "1.0",
   name: "Test 3",
   updateURL: "http://localhost:4444/data/test_corrupt.rdf",
   targetApplications: [{
     id: "xpcshell@tests.mozilla.org",
     minVersion: "1",
     maxVersion: "1"
   }]
 };
 
-// Will get a compatibility update and be disabled
+// Will get a compatibility update and be enabled
 var addon4 = {
   id: "addon4@tests.mozilla.org",
   version: "1.0",
   name: "Test 4",
   updateURL: "http://localhost:4444/data/test_corrupt.rdf",
   targetApplications: [{
     id: "xpcshell@tests.mozilla.org",
     minVersion: "1",
     maxVersion: "1"
   }]
 };
 
-// Stays incompatible
+// Would stay incompatible with strict compat
 var addon5 = {
   id: "addon5@tests.mozilla.org",
   version: "1.0",
   name: "Test 5",
   targetApplications: [{
     id: "xpcshell@tests.mozilla.org",
     minVersion: "1",
     maxVersion: "1"
@@ -212,19 +213,19 @@ function run_test_1() {
 
     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_neq(a5, null);
-    do_check_false(a5.isActive);
+    do_check_true(a5.isActive);
     do_check_false(a5.userDisabled);
-    do_check_true(a5.appDisabled);
+    do_check_false(a5.appDisabled);
     do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
 
     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);
 
@@ -280,31 +281,33 @@ function run_test_1() {
       do_check_false(a2.appDisabled);
       do_check_eq(a2.pendingOperations, AddonManager.PENDING_NONE);
 
       // 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_false(a3.appDisabled);
+      do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
 
-      // The compatibility update won't be recovered and it will not have been
-      // able to tell that it was previously userDisabled
+      // 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_false(a4.userDisabled);
-      do_check_true(a4.appDisabled);
+      do_check_true(a4.userDisabled);
+      do_check_false(a4.appDisabled);
       do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE);
 
       do_check_neq(a5, null);
-      do_check_false(a5.isActive);
+      do_check_true(a5.isActive);
       do_check_false(a5.userDisabled);
-      do_check_true(a5.appDisabled);
+      do_check_false(a5.appDisabled);
       do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
 
       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);
 
@@ -352,31 +355,31 @@ function run_test_1() {
 
         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_neq(a3, null);
-        do_check_false(a3.isActive);
+        do_check_true(a3.isActive);
         do_check_false(a3.userDisabled);
-        do_check_true(a3.appDisabled);
+        do_check_false(a3.appDisabled);
         do_check_eq(a3.pendingOperations, AddonManager.PENDING_NONE);
 
         do_check_neq(a4, null);
         do_check_false(a4.isActive);
-        do_check_false(a4.userDisabled);
-        do_check_true(a4.appDisabled);
+        do_check_true(a4.userDisabled);
+        do_check_false(a4.appDisabled);
         do_check_eq(a4.pendingOperations, AddonManager.PENDING_NONE);
 
         do_check_neq(a5, null);
-        do_check_false(a5.isActive);
+        do_check_true(a5.isActive);
         do_check_false(a5.userDisabled);
-        do_check_true(a5.appDisabled);
+        do_check_false(a5.appDisabled);
         do_check_eq(a5.pendingOperations, AddonManager.PENDING_NONE);
 
         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);
 
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_locked_strictcompat.js
@@ -0,0 +1,407 @@
+/* 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
+
+
+do_load_httpd_js();
+var testserver;
+
+// The test extension uses an insecure update url.
+Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
+Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true);
+
+// Will be enabled
+var addon1 = {
+  id: "addon1@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 1",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "2",
+    maxVersion: "2"
+  }]
+};
+
+// Will be disabled
+var addon2 = {
+  id: "addon2@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 2",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "2",
+    maxVersion: "2"
+  }]
+};
+
+// Will get a compatibility update and be enabled
+var addon3 = {
+  id: "addon3@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 3",
+  updateURL: "http://localhost:4444/data/test_corrupt.rdf",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "1",
+    maxVersion: "1"
+  }]
+};
+
+// Will get a compatibility update and be disabled
+var addon4 = {
+  id: "addon4@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 4",
+  updateURL: "http://localhost:4444/data/test_corrupt.rdf",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "1",
+    maxVersion: "1"
+  }]
+};
+
+// Stays incompatible
+var addon5 = {
+  id: "addon5@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 5",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "1",
+    maxVersion: "1"
+  }]
+};
+
+// Enabled bootstrapped
+var addon6 = {
+  id: "addon6@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 6",
+  bootstrap: "true",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "2",
+    maxVersion: "2"
+  }]
+};
+
+// Disabled bootstrapped
+var addon7 = {
+  id: "addon7@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 7",
+  bootstrap: "true",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "2",
+    maxVersion: "2"
+  }]
+};
+
+// The default theme
+var theme1 = {
+  id: "theme1@tests.mozilla.org",
+  version: "1.0",
+  name: "Theme 1",
+  internalName: "classic/1.0",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "2",
+    maxVersion: "2"
+  }]
+};
+
+// The selected theme
+var theme2 = {
+  id: "theme2@tests.mozilla.org",
+  version: "1.0",
+  name: "Theme 2",
+  internalName: "test/1.0",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "2",
+    maxVersion: "2"
+  }]
+};
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+function run_test() {
+  do_test_pending();
+  createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2", "2");
+
+  writeInstallRDFForExtension(addon1, profileDir);
+  writeInstallRDFForExtension(addon2, profileDir);
+  writeInstallRDFForExtension(addon3, profileDir);
+  writeInstallRDFForExtension(addon4, profileDir);
+  writeInstallRDFForExtension(addon5, profileDir);
+  writeInstallRDFForExtension(addon6, profileDir);
+  writeInstallRDFForExtension(addon7, profileDir);
+  writeInstallRDFForExtension(theme1, profileDir);
+  writeInstallRDFForExtension(theme2, profileDir);
+
+  // Create and configure the HTTP server.
+  testserver = new nsHttpServer();
+  testserver.registerDirectory("/addons/", do_get_file("addons"));
+  testserver.registerDirectory("/data/", do_get_file("data"));
+  testserver.start(4444);
+
+  // Startup the profile and setup the initial state
+  startupManager();
+
+  AddonManager.getAddonsByIDs(["addon2@tests.mozilla.org",
+                               "addon3@tests.mozilla.org",
+                               "addon4@tests.mozilla.org",
+                               "addon7@tests.mozilla.org",
+                               "theme2@tests.mozilla.org"], function([a2, a3, a4,
+                                                                      a7, t2]) {
+    // Set up the initial state
+    a2.userDisabled = true;
+    a4.userDisabled = true;
+    a7.userDisabled = true;
+    t2.userDisabled = false;
+    a3.findUpdates({
+      onUpdateFinished: function() {
+        a4.findUpdates({
+          onUpdateFinished: function() {
+            restartManager();
+
+            run_test_1();
+          }
+        }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE);
+      }
+    }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE);
+  });
+}
+
+function end_test() {
+  testserver.stop(do_test_finished);
+}
+
+function run_test_1() {
+  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"], 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_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_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_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_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_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_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);
+
+    // After restarting the database won't be open so lock the file for writing
+    restartManager();
+    var dbfile = gProfD.clone();
+    dbfile.append("extensions.sqlite");
+    var fstream = AM_Cc["@mozilla.org/network/file-output-stream;1"].
+                  createInstance(AM_Ci.nsIFileOutputStream);
+    fstream.init(dbfile, FileUtils.MODE_TRUNCATE | FileUtils.MODE_WRONLY, FileUtils.PERMS_FILE, 0);
+
+    // 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"], 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);
+
+      // 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);
+
+      // 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);
+
+      // 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_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_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);
+
+      // 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);
+
+      // 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();
+
+      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"], 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_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_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_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_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_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_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);
+
+        fstream.close();
+        end_test();
+      });
+    });
+  });
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_strictcompatibility.js
@@ -0,0 +1,105 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// Tests AddonManager.strictCompatibility and it's related preference,
+// extensions.strictCompatibility
+
+
+// Always compatible
+var addon1 = {
+  id: "addon1@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 1",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "1",
+    maxVersion: "1"
+  }]
+};
+
+// Incompatible in strict compatibility mode
+var addon2 = {
+  id: "addon2@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 2",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "0.1",
+    maxVersion: "0.2"
+  }]
+};
+
+// Theme - always uses strict compatibility, so is always incompatible
+var addon3 = {
+  id: "addon3@tests.mozilla.org",
+  version: "1.0",
+  name: "Test 3",
+  internalName: "test-theme-3",
+  targetApplications: [{
+    id: "xpcshell@tests.mozilla.org",
+    minVersion: "0.1",
+    maxVersion: "0.2"
+  }]
+};
+
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+
+function do_check_compat_status(aStrict, aAddonCompat, aCallback) {
+  do_check_eq(AddonManager.strictCompatibility, aStrict);
+  AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+                               "addon2@tests.mozilla.org",
+                               "addon3@tests.mozilla.org"],
+                              function([a1, a2, a3]) {
+    do_check_neq(a1, null);
+    do_check_eq(a1.isCompatible, aAddonCompat[0]);
+    do_check_eq(a1.appDisabled, !aAddonCompat[0]);
+
+    do_check_neq(a2, null);
+    do_check_eq(a2.isCompatible, aAddonCompat[1]);
+    do_check_eq(a2.appDisabled, !aAddonCompat[1]);
+
+    do_check_neq(a3, null);
+    do_check_eq(a3.isCompatible, aAddonCompat[2]);
+    do_check_eq(a3.appDisabled, !aAddonCompat[2]);
+
+    aCallback();
+  });
+}
+
+
+function run_test() {
+  do_test_pending();
+  createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
+  
+  writeInstallRDFForExtension(addon1, profileDir);
+  writeInstallRDFForExtension(addon2, profileDir);
+  writeInstallRDFForExtension(addon3, profileDir);
+
+  startupManager();
+  
+  // Should default to enabling strict compat.
+  do_check_compat_status(true, [true, false, false], run_test_1);
+}
+
+function run_test_1() {
+  Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false);
+  do_check_compat_status(false, [true, true, false], run_test_2);
+}
+
+function run_test_2() {
+  restartManager();
+  do_check_compat_status(false, [true, true, false], run_test_3);
+}
+
+function run_test_3() {
+  Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true);
+  do_check_compat_status(true, [true, false, false], run_test_4);
+}
+
+function run_test_4() {
+  restartManager();
+  do_check_compat_status(true, [true, false, false], do_test_finished);
+}
--- a/toolkit/mozapps/extensions/test/xpcshell/test_update.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_update.js
@@ -3,17 +3,18 @@
  */
 
 // This verifies that add-on update checks work
 
 const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS";
 const PREF_SELECTED_LOCALE = "general.useragent.locale";
 
 // The test extension uses an insecure update url.
-Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false);
+Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
+Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false);
 // This test requires lightweight themes update to be enabled even if the app
 // doesn't support lightweight themes.
 Services.prefs.setBoolPref("lightweightThemes.update.enabled", true);
 
 Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm");
 
 const PARAMS = "?%REQ_VERSION%/%ITEM_ID%/%ITEM_VERSION%/%ITEM_MAXAPPVERSION%/" +
                "%ITEM_STATUS%/%APP_ID%/%APP_VERSION%/%CURRENT_APP_VERSION%/" +
@@ -230,26 +231,26 @@ function check_test_2() {
   });
 }
 
 
 // Check that an update check finds compatibility updates and applies them
 function run_test_3() {
   AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
     do_check_neq(a2, null);
-    do_check_false(a2.isActive);
-    do_check_false(a2.isCompatible);
-    do_check_true(a2.appDisabled);
+    do_check_true(a2.isActive);
+    do_check_true(a2.isCompatible);
+    do_check_false(a2.appDisabled);
     do_check_true(a2.isCompatibleWith("0"));
 
     a2.findUpdates({
       onCompatibilityUpdateAvailable: function(addon) {
         do_check_true(a2.isCompatible);
         do_check_false(a2.appDisabled);
-        do_check_false(a2.isActive);
+        do_check_true(a2.isActive);
       },
 
       onUpdateAvailable: function(addon, install) {
         do_throw("Should not have seen an available update");
       },
 
       onNoUpdateAvailable: function(addon) {
         do_check_eq(addon, a2);
@@ -271,21 +272,21 @@ function check_test_3() {
     run_test_4();
   });
 }
 
 // Checks that we see no compatibility information when there is none.
 function run_test_4() {
   AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) {
     do_check_neq(a3, null);
-    do_check_false(a3.isActive);
-    do_check_false(a3.isCompatible);
-    do_check_true(a3.appDisabled);
+    do_check_true(a3.isActive);
+    do_check_true(a3.isCompatible);
+    do_check_false(a3.appDisabled);
     do_check_true(a3.isCompatibleWith("5"));
-    do_check_false(a3.isCompatibleWith("2"));
+    do_check_true(a3.isCompatibleWith("2"));
 
     a3.findUpdates({
       sawUpdate: false,
       onCompatibilityUpdateAvailable: function(addon) {
         do_throw("Should not have seen compatibility information");
       },
 
       onNoCompatibilityUpdateAvailable: function(addon) {
@@ -304,28 +305,28 @@ function run_test_4() {
   });
 }
 
 // Checks that compatibility info for future apps are detected but don't make
 // the item compatibile.
 function run_test_5() {
   AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) {
     do_check_neq(a3, null);
-    do_check_false(a3.isActive);
-    do_check_false(a3.isCompatible);
-    do_check_true(a3.appDisabled);
+    do_check_true(a3.isActive);
+    do_check_true(a3.isCompatible);
+    do_check_false(a3.appDisabled);
     do_check_true(a3.isCompatibleWith("5"));
-    do_check_false(a3.isCompatibleWith("2"));
+    do_check_true(a3.isCompatibleWith("2"));
 
     a3.findUpdates({
       sawUpdate: false,
       onCompatibilityUpdateAvailable: function(addon) {
-        do_check_false(a3.isCompatible);
-        do_check_true(a3.appDisabled);
-        do_check_false(a3.isActive);
+        do_check_true(a3.isCompatible);
+        do_check_false(a3.appDisabled);
+        do_check_true(a3.isActive);
         this.sawUpdate = true;
       },
 
       onNoCompatibilityUpdateAvailable: function(addon) {
         do_throw("Should have seen some compatibility information");
       },
 
       onUpdateAvailable: function(addon, install) {
@@ -339,19 +340,19 @@ function run_test_5() {
       }
     }, AddonManager.UPDATE_WHEN_USER_REQUESTED, "3.0");
   });
 }
 
 function check_test_5() {
   AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) {
     do_check_neq(a3, null);
-    do_check_false(a3.isActive);
-    do_check_false(a3.isCompatible);
-    do_check_true(a3.appDisabled);
+    do_check_true(a3.isActive);
+    do_check_true(a3.isCompatible);
+    do_check_false(a3.appDisabled);
 
     a3.uninstall();
     restartManager();
 
     run_test_6();
   });
 }
 
@@ -604,17 +605,17 @@ function run_test_8() {
         do_check_eq(item_maxappversion, "3");
         do_check_eq(item_status, "userDisabled");
         do_check_eq(app_version, "1");
         do_check_eq(update_type, "49");
         break;
       case "addon3@tests.mozilla.org":
         do_check_eq(item_version, "1.3+");
         do_check_eq(item_maxappversion, "0");
-        do_check_eq(item_status, "userEnabled,incompatible");
+        do_check_eq(item_status, "userEnabled");
         do_check_eq(app_version, "1");
         do_check_eq(update_type, "112");
         break;
       case "addon4@tests.mozilla.org":
         do_check_eq(item_version, "0.5ab6");
         do_check_eq(item_maxappversion, "5");
         do_check_eq(item_status, "userEnabled");
         do_check_eq(app_version, "2");
@@ -736,31 +737,31 @@ 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);
+        do_check_true(addon.isCompatible);
 
         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();
 
   AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) {
-    do_check_false(a4.isActive);
-    do_check_false(a4.isCompatible);
+    do_check_true(a4.isActive);
+    do_check_true(a4.isCompatible);
 
     a4.uninstall();
     restartManager();
 
     run_test_13();
   });
 }
 
@@ -779,19 +780,19 @@ function run_test_13() {
       maxVersion: "0"
     }],
     name: "Test Addon 7",
   }, profileDir);
   restartManager();
 
   AddonManager.getAddonByID("addon7@tests.mozilla.org", function(a7) {
     do_check_neq(a7, null);
-    do_check_false(a7.isActive);
-    do_check_false(a7.isCompatible);
-    do_check_true(a7.appDisabled);
+    do_check_true(a7.isActive);
+    do_check_true(a7.isCompatible);
+    do_check_false(a7.appDisabled);
     do_check_true(a7.isCompatibleWith("0"));
 
     a7.findUpdates({
       sawUpdate: false,
       onCompatibilityUpdateAvailable: function(addon) {
         do_throw("Should have not have seen compatibility information");
       },
 
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js
@@ -0,0 +1,1021 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// This verifies that add-on update checks work
+
+const PREF_MATCH_OS_LOCALE = "intl.locale.matchOS";
+const PREF_SELECTED_LOCALE = "general.useragent.locale";
+
+// The test extension uses an insecure update url.
+Services.prefs.setBoolPref("extensions.checkUpdateSecurity", false);
+// This test requires lightweight themes update to be enabled even if the app
+// doesn't support lightweight themes.
+Services.prefs.setBoolPref("lightweightThemes.update.enabled", true);
+
+Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm");
+
+const PARAMS = "?%REQ_VERSION%/%ITEM_ID%/%ITEM_VERSION%/%ITEM_MAXAPPVERSION%/" +
+               "%ITEM_STATUS%/%APP_ID%/%APP_VERSION%/%CURRENT_APP_VERSION%/" +
+               "%APP_OS%/%APP_ABI%/%APP_LOCALE%/%UPDATE_TYPE%";
+
+var gInstallDate;
+
+do_load_httpd_js();
+var testserver;
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+function run_test() {
+  createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
+  Services.prefs.setBoolPref(PREF_MATCH_OS_LOCALE, false);
+  Services.prefs.setCharPref(PREF_SELECTED_LOCALE, "fr-FR");
+  Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true);
+
+  // Create and configure the HTTP server.
+  testserver = new nsHttpServer();
+  testserver.registerDirectory("/data/", do_get_file("data"));
+  testserver.registerDirectory("/addons/", do_get_file("addons"));
+  testserver.start(4444);
+
+  writeInstallRDFForExtension({
+    id: "addon1@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_update.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon 1",
+  }, profileDir);
+
+  writeInstallRDFForExtension({
+    id: "addon2@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_update.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "0",
+      maxVersion: "0"
+    }],
+    name: "Test Addon 2",
+  }, profileDir);
+
+  writeInstallRDFForExtension({
+    id: "addon3@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_update.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "5",
+      maxVersion: "5"
+    }],
+    name: "Test Addon 3",
+  }, profileDir);
+
+  startupManager();
+
+  do_test_pending();
+  run_test_1();
+}
+
+function end_test() {
+  Services.prefs.clearUserPref(PREF_EM_STRICT_COMPATIBILITY);
+
+  testserver.stop(do_test_finished);
+}
+
+// Verify that an update is available and can be installed.
+function run_test_1() {
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+    do_check_neq(a1, null);
+    do_check_eq(a1.version, "1.0");
+    do_check_eq(a1.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DEFAULT);
+    do_check_eq(a1.releaseNotesURI, null);
+
+    a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT;
+
+    prepare_test({
+      "addon1@tests.mozilla.org": [
+        ["onPropertyChanged", ["applyBackgroundUpdates"]]
+      ]
+    });
+    a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE;
+    check_test_completed();
+
+    a1.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE;
+
+    prepare_test({}, [
+      "onNewInstall",
+    ]);
+
+    a1.findUpdates({
+      onNoCompatibilityUpdateAvailable: function(addon) {
+        do_throw("Should not have seen onNoCompatibilityUpdateAvailable notification");
+      },
+
+      onUpdateAvailable: function(addon, install) {
+        ensure_test_completed();
+
+        AddonManager.getAllInstalls(function(aInstalls) {
+          do_check_eq(aInstalls.length, 1);
+          do_check_eq(aInstalls[0], install);
+
+          do_check_eq(addon, a1);
+          do_check_eq(install.name, addon.name);
+          do_check_eq(install.version, "2.0");
+          do_check_eq(install.state, AddonManager.STATE_AVAILABLE);
+          do_check_eq(install.existingAddon, addon);
+          do_check_eq(install.releaseNotesURI.spec, "http://example.com/updateInfo.xhtml");
+
+          // Verify that another update check returns the same AddonInstall
+          a1.findUpdates({
+            onNoCompatibilityUpdateAvailable: function(addon) {
+              do_throw("Should not have seen onNoCompatibilityUpdateAvailable notification");
+            },
+
+            onUpdateAvailable: function(newAddon, newInstall) {
+              AddonManager.getAllInstalls(function(aInstalls) {
+                do_check_eq(aInstalls.length, 1);
+                do_check_eq(aInstalls[0], install);
+                do_check_eq(newAddon, addon);
+                do_check_eq(newInstall, install);
+
+                prepare_test({}, [
+                  "onDownloadStarted",
+                  "onDownloadEnded",
+                ], check_test_1);
+                install.install();
+              });
+            },
+
+            onNoUpdateAvailable: function(addon) {
+              do_throw("Should not have seen onNoUpdateAvailable notification");
+            }
+          }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
+        });
+      },
+
+      onNoUpdateAvailable: function(addon) {
+        do_throw("Should not have seen onNoUpdateAvailable notification");
+      }
+    }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
+  });
+}
+
+function check_test_1(install) {
+  ensure_test_completed();
+  do_check_eq(install.state, AddonManager.STATE_DOWNLOADED);
+  run_test_2(install);
+  return false;
+}
+
+// Continue installing the update.
+function run_test_2(install) {
+  // Verify that another update check returns no new update
+  install.existingAddon.findUpdates({
+    onNoCompatibilityUpdateAvailable: function(addon) {
+      do_throw("Should not have seen onNoCompatibilityUpdateAvailable notification");
+    },
+
+    onUpdateAvailable: function(addon, install) {
+      do_throw("Should find no available update when one is already downloading");
+    },
+
+    onNoUpdateAvailable: function(addon) {
+      AddonManager.getAllInstalls(function(aInstalls) {
+        do_check_eq(aInstalls.length, 1);
+        do_check_eq(aInstalls[0], install);
+
+        prepare_test({
+          "addon1@tests.mozilla.org": [
+            "onInstalling"
+          ]
+        }, [
+          "onInstallStarted",
+          "onInstallEnded",
+        ], check_test_2);
+        install.install();
+      });
+    }
+  }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
+}
+
+function check_test_2() {
+  ensure_test_completed();
+
+  AddonManager.getAddonByID("addon1@tests.mozilla.org", function(olda1) {
+    do_check_neq(olda1, null);
+    do_check_eq(olda1.version, "1.0");
+    do_check_true(isExtensionInAddonsList(profileDir, olda1.id));
+
+    shutdownManager();
+
+    startupManager();
+
+    do_check_true(isExtensionInAddonsList(profileDir, olda1.id));
+
+    AddonManager.getAddonByID("addon1@tests.mozilla.org", function(a1) {
+      do_check_neq(a1, null);
+      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();
+      restartManager();
+
+      run_test_3();
+    });
+  });
+}
+
+
+// Check that an update check finds compatibility updates and applies them
+function run_test_3() {
+  AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
+    do_check_neq(a2, null);
+    do_check_false(a2.isActive);
+    do_check_false(a2.isCompatible);
+    do_check_true(a2.appDisabled);
+    do_check_true(a2.isCompatibleWith("0"));
+
+    a2.findUpdates({
+      onCompatibilityUpdateAvailable: function(addon) {
+        do_check_true(a2.isCompatible);
+        do_check_false(a2.appDisabled);
+        do_check_false(a2.isActive);
+      },
+
+      onUpdateAvailable: function(addon, install) {
+        do_throw("Should not have seen an available update");
+      },
+
+      onNoUpdateAvailable: function(addon) {
+        do_check_eq(addon, a2);
+        restartManager();
+        check_test_3();
+      }
+    }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
+  });
+}
+
+function check_test_3() {
+  AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
+    do_check_neq(a2, null);
+    do_check_true(a2.isActive);
+    do_check_true(a2.isCompatible);
+    do_check_false(a2.appDisabled);
+    a2.uninstall();
+
+    run_test_4();
+  });
+}
+
+// Checks that we see no compatibility information when there is none.
+function run_test_4() {
+  AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) {
+    do_check_neq(a3, null);
+    do_check_false(a3.isActive);
+    do_check_false(a3.isCompatible);
+    do_check_true(a3.appDisabled);
+    do_check_true(a3.isCompatibleWith("5"));
+    do_check_false(a3.isCompatibleWith("2"));
+
+    a3.findUpdates({
+      sawUpdate: false,
+      onCompatibilityUpdateAvailable: function(addon) {
+        do_throw("Should not have seen compatibility information");
+      },
+
+      onNoCompatibilityUpdateAvailable: function(addon) {
+        this.sawUpdate = true;
+      },
+
+      onUpdateAvailable: function(addon, install) {
+        do_throw("Should not have seen an available update");
+      },
+
+      onNoUpdateAvailable: function(addon) {
+        do_check_true(this.sawUpdate);
+        run_test_5();
+      }
+    }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
+  });
+}
+
+// Checks that compatibility info for future apps are detected but don't make
+// the item compatibile.
+function run_test_5() {
+  AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) {
+    do_check_neq(a3, null);
+    do_check_false(a3.isActive);
+    do_check_false(a3.isCompatible);
+    do_check_true(a3.appDisabled);
+    do_check_true(a3.isCompatibleWith("5"));
+    do_check_false(a3.isCompatibleWith("2"));
+
+    a3.findUpdates({
+      sawUpdate: false,
+      onCompatibilityUpdateAvailable: function(addon) {
+        do_check_false(a3.isCompatible);
+        do_check_true(a3.appDisabled);
+        do_check_false(a3.isActive);
+        this.sawUpdate = true;
+      },
+
+      onNoCompatibilityUpdateAvailable: function(addon) {
+        do_throw("Should have seen some compatibility information");
+      },
+
+      onUpdateAvailable: function(addon, install) {
+        do_throw("Should not have seen an available update");
+      },
+
+      onNoUpdateAvailable: function(addon) {
+        do_check_true(this.sawUpdate);
+        restartManager();
+        check_test_5();
+      }
+    }, AddonManager.UPDATE_WHEN_USER_REQUESTED, "3.0");
+  });
+}
+
+function check_test_5() {
+  AddonManager.getAddonByID("addon3@tests.mozilla.org", function(a3) {
+    do_check_neq(a3, null);
+    do_check_false(a3.isActive);
+    do_check_false(a3.isCompatible);
+    do_check_true(a3.appDisabled);
+
+    a3.uninstall();
+    restartManager();
+
+    run_test_6();
+  });
+}
+
+// Test that background update checks work
+function run_test_6() {
+  writeInstallRDFForExtension({
+    id: "addon1@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_update.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon 1",
+  }, profileDir);
+  restartManager();
+
+  prepare_test({}, [
+    "onNewInstall",
+    "onDownloadStarted",
+    "onDownloadEnded"
+  ], continue_test_6);
+
+  // Fake a timer event to cause a background update and wait for the magic to
+  // happen
+  gInternalManager.notify(null);
+}
+
+function continue_test_6(install) {
+  do_check_neq(install.existingAddon, null);
+  do_check_eq(install.existingAddon.id, "addon1@tests.mozilla.org");
+
+  prepare_test({
+    "addon1@tests.mozilla.org": [
+      "onInstalling"
+    ]
+  }, [
+    "onInstallStarted",
+    "onInstallEnded",
+  ], 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();
+  });
+}
+
+// Test that background update checks work for lightweight themes
+function run_test_7() {
+  LightweightThemeManager.currentTheme = {
+    id: "1",
+    version: "1",
+    name: "Test LW Theme",
+    description: "A test theme",
+    author: "Mozilla",
+    homepageURL: "http://localhost:4444/data/index.html",
+    headerURL: "http://localhost:4444/data/header.png",
+    footerURL: "http://localhost:4444/data/footer.png",
+    previewURL: "http://localhost:4444/data/preview.png",
+    iconURL: "http://localhost:4444/data/icon.png",
+    updateURL: "http://localhost:4444/data/lwtheme.js"
+  };
+
+  // XXX The lightweight theme manager strips non-https updateURLs so hack it
+  // back in.
+  let themes = JSON.parse(Services.prefs.getCharPref("lightweightThemes.usedThemes"));
+  do_check_eq(themes.length, 1);
+  themes[0].updateURL = "http://localhost:4444/data/lwtheme.js";
+  Services.prefs.setCharPref("lightweightThemes.usedThemes", JSON.stringify(themes));
+
+  testserver.registerPathHandler("/data/lwtheme.js", function(request, response) {
+    response.write(JSON.stringify({
+      id: "1",
+      version: "2",
+      name: "Updated Theme",
+      description: "A test theme",
+      author: "Mozilla",
+      homepageURL: "http://localhost:4444/data/index2.html",
+      headerURL: "http://localhost:4444/data/header.png",
+      footerURL: "http://localhost:4444/data/footer.png",
+      previewURL: "http://localhost:4444/data/preview.png",
+      iconURL: "http://localhost:4444/data/icon2.png",
+      updateURL: "http://localhost:4444/data/lwtheme.js"
+    }));
+  });
+
+  AddonManager.getAddonByID("1@personas.mozilla.org", function(p1) {
+    do_check_neq(p1, null);
+    do_check_eq(p1.version, "1");
+    do_check_eq(p1.name, "Test LW Theme");
+    do_check_true(p1.isActive);
+    do_check_eq(p1.installDate.getTime(), p1.updateDate.getTime());
+
+    // 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.installDate.getTime()) < 5000);
+
+    gInstallDate = p1.installDate.getTime();
+
+    prepare_test({
+      "1@personas.mozilla.org": [
+        ["onInstalling", false],
+        "onInstalled"
+      ]
+    }, [
+      "onExternalInstall"
+    ], check_test_7);
+
+    // Fake a timer event to cause a background update and wait for the magic to
+    // happen
+    gInternalManager.notify(null);
+  });
+}
+
+function check_test_7() {
+  AddonManager.getAddonByID("1@personas.mozilla.org", function(p1) {
+    do_check_neq(p1, null);
+    do_check_eq(p1.version, "2");
+    do_check_eq(p1.name, "Updated Theme");
+    do_check_eq(p1.installDate.getTime(), gInstallDate);
+    do_check_true(p1.installDate.getTime() < p1.updateDate.getTime());
+
+    // 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();
+  });
+}
+
+// Verify the parameter escaping in update urls.
+function run_test_8() {
+  writeInstallRDFForExtension({
+    id: "addon1@tests.mozilla.org",
+    version: "5.0",
+    updateURL: "http://localhost:4444/data/param_test.rdf" + PARAMS,
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "2"
+    }],
+    name: "Test Addon 1",
+  }, profileDir);
+
+  writeInstallRDFForExtension({
+    id: "addon2@tests.mozilla.org",
+    version: "67.0.5b1",
+    updateURL: "http://localhost:4444/data/param_test.rdf" + PARAMS,
+    targetApplications: [{
+      id: "toolkit@mozilla.org",
+      minVersion: "0",
+      maxVersion: "3"
+    }],
+    name: "Test Addon 2",
+  }, profileDir);
+
+  writeInstallRDFForExtension({
+    id: "addon3@tests.mozilla.org",
+    version: "1.3+",
+    updateURL: "http://localhost:4444/data/param_test.rdf" + PARAMS,
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "0",
+      maxVersion: "0"
+    }, {
+      id: "toolkit@mozilla.org",
+      minVersion: "0",
+      maxVersion: "3"
+    }],
+    name: "Test Addon 3",
+  }, profileDir);
+
+  writeInstallRDFForExtension({
+    id: "addon4@tests.mozilla.org",
+    version: "0.5ab6",
+    updateURL: "http://localhost:4444/data/param_test.rdf" + PARAMS,
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "5"
+    }],
+    name: "Test Addon 4",
+  }, profileDir);
+
+  writeInstallRDFForExtension({
+    id: "addon5@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/param_test.rdf" + PARAMS,
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon 5",
+  }, profileDir);
+
+  writeInstallRDFForExtension({
+    id: "addon6@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/param_test.rdf" + PARAMS,
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon 6",
+  }, profileDir);
+
+  restartManager();
+
+  AddonManager.getAddonByID("addon2@tests.mozilla.org", 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,
+           app_os, app_abi, app_locale, update_type] =
+           [decodeURIComponent(a) for each (a in request.queryString.split("/"))];
+
+      do_check_eq(req_version, "2");
+
+      switch(item_id) {
+      case "addon1@tests.mozilla.org":
+        do_check_eq(item_version, "5.0");
+        do_check_eq(item_maxappversion, "2");
+        do_check_eq(item_status, "userEnabled");
+        do_check_eq(app_version, "1");
+        do_check_eq(update_type, "97");
+        break;
+      case "addon2@tests.mozilla.org":
+        do_check_eq(item_version, "67.0.5b1");
+        do_check_eq(item_maxappversion, "3");
+        do_check_eq(item_status, "userDisabled");
+        do_check_eq(app_version, "1");
+        do_check_eq(update_type, "49");
+        break;
+      case "addon3@tests.mozilla.org":
+        do_check_eq(item_version, "1.3+");
+        do_check_eq(item_maxappversion, "0");
+        do_check_eq(item_status, "userEnabled,incompatible");
+        do_check_eq(app_version, "1");
+        do_check_eq(update_type, "112");
+        break;
+      case "addon4@tests.mozilla.org":
+        do_check_eq(item_version, "0.5ab6");
+        do_check_eq(item_maxappversion, "5");
+        do_check_eq(item_status, "userEnabled");
+        do_check_eq(app_version, "2");
+        do_check_eq(update_type, "98");
+        break;
+      case "addon5@tests.mozilla.org":
+        do_check_eq(item_version, "1.0");
+        do_check_eq(item_maxappversion, "1");
+        do_check_eq(item_status, "userEnabled");
+        do_check_eq(app_version, "1");
+        do_check_eq(update_type, "35");
+        break;
+      case "addon6@tests.mozilla.org":
+        do_check_eq(item_version, "1.0");
+        do_check_eq(item_maxappversion, "1");
+        do_check_eq(item_status, "userEnabled");
+        do_check_eq(app_version, "1");
+        do_check_eq(update_type, "99");
+        break;
+      default:
+        do_throw("Update request for unexpected add-on " + item_id);
+      }
+
+      do_check_eq(app_id, "xpcshell@tests.mozilla.org");
+      do_check_eq(current_app_version, "1");
+      do_check_eq(app_os, "XPCShell");
+      do_check_eq(app_abi, "noarch-spidermonkey");
+      do_check_eq(app_locale, "fr-FR");
+
+      request.setStatusLine(null, 500, "Server Error");
+    });
+
+    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]) {
+      let count = 6;
+
+      function run_next_test() {
+        a1.uninstall();
+        a2.uninstall();
+        a3.uninstall();
+        a4.uninstall();
+        a5.uninstall();
+        a6.uninstall();
+
+        restartManager();
+        run_test_9();
+      }
+
+      let compatListener = {
+        onUpdateFinished: function(addon, error) {
+          if (--count == 0)
+            run_next_test();
+        }
+      };
+
+      let updateListener = {
+        onUpdateAvailable: function(addon, update) {
+          // Dummy so the update checker knows we care about new versions
+        },
+
+        onUpdateFinished: function(addon, error) {
+          if (--count == 0)
+            run_next_test();
+        }
+      };
+
+      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",
+    updateURL: "http://localhost:4444/data/test_update.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "0",
+      maxVersion: "1"
+    }],
+    name: "Test Addon 1",
+  }, profileDir);
+
+  restartManager();
+
+  AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) {
+    do_check_true(a4.isActive);
+    do_check_true(a4.isCompatible);
+
+    run_test_10();
+  });
+}
+
+// Tests that a normal update check won't decrease a targetApplication's
+// maxVersion.
+function run_test_10() {
+  AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) {
+    a4.findUpdates({
+      onUpdateFinished: function(addon) {
+        do_check_true(addon.isCompatible);
+
+        run_test_11();
+      }
+    }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE);
+  });
+}
+
+// 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();
+      }
+    }, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED);
+  });
+}
+
+// Check that the decreased maxVersion applied and disables the add-on
+function run_test_12() {
+  restartManager();
+
+  AddonManager.getAddonByID("addon4@tests.mozilla.org", function(a4) {
+    do_check_false(a4.isActive);
+    do_check_false(a4.isCompatible);
+
+    a4.uninstall();
+    restartManager();
+
+    run_test_13();
+  });
+}
+
+// Tests that no compatibility update is passed to the listener when there is
+// compatibility info for the current version of the app but not for the
+// version of the app that the caller requested an update check for.
+function run_test_13() {
+  // Not initially compatible but the update check will make it compatible
+  writeInstallRDFForExtension({
+    id: "addon7@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_update.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "0",
+      maxVersion: "0"
+    }],
+    name: "Test Addon 7",
+  }, profileDir);
+  restartManager();
+
+  AddonManager.getAddonByID("addon7@tests.mozilla.org", function(a7) {
+    do_check_neq(a7, null);
+    do_check_false(a7.isActive);
+    do_check_false(a7.isCompatible);
+    do_check_true(a7.appDisabled);
+    do_check_true(a7.isCompatibleWith("0"));
+
+    a7.findUpdates({
+      sawUpdate: false,
+      onCompatibilityUpdateAvailable: function(addon) {
+        do_throw("Should have not have seen compatibility information");
+      },
+
+      onUpdateAvailable: function(addon, install) {
+        do_throw("Should not have seen an available update");
+      },
+
+      onUpdateFinished: function(addon) {
+        do_check_true(addon.isCompatible);
+        restartManager();
+        check_test_13();
+      }
+    }, AddonManager.UPDATE_WHEN_NEW_APP_DETECTED, "3.0");
+  });
+}
+
+function check_test_13() {
+  AddonManager.getAddonByID("addon7@tests.mozilla.org", function(a7) {
+    do_check_neq(a7, null);
+    do_check_true(a7.isActive);
+    do_check_true(a7.isCompatible);
+    do_check_false(a7.appDisabled);
+
+    a7.uninstall();
+    restartManager();
+
+    run_test_14();
+  });
+}
+
+// Test that background update checks doesn't update an add-on that isn't
+// allowed to update automatically.
+function run_test_14() {
+  // Have an add-on there that will be updated so we see some events from it
+  writeInstallRDFForExtension({
+    id: "addon1@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_update.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon 1",
+  }, profileDir);
+
+  writeInstallRDFForExtension({
+    id: "addon8@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_update.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon 8",
+  }, profileDir);
+  restartManager();
+
+  AddonManager.getAddonByID("addon8@tests.mozilla.org", function(a8) {
+    a8.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE;
+
+    // The background update check will find updates for both add-ons but only
+    // proceed to install one of them.
+    AddonManager.addInstallListener({
+      onNewInstall: function(aInstall) {
+        if (aInstall.existingAddon.id != "addon1@tests.mozilla.org" &&
+            aInstall.existingAddon.id != "addon8@tests.mozilla.org")
+          do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id);
+      },
+
+      onDownloadStarted: function(aInstall) {
+        do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org");
+      },
+
+      onDownloadEnded: function(aInstall) {
+        do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org");
+      },
+
+      onDownloadFailed: function(aInstall) {
+        do_throw("Should not have seen onDownloadFailed event");
+      },
+
+      onDownloadCancelled: function(aInstall) {
+        do_throw("Should not have seen onDownloadCancelled event");
+      },
+
+      onInstallStarted: function(aInstall) {
+        do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org");
+      },
+
+      onInstallEnded: function(aInstall) {
+        do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org");
+        check_test_14(aInstall);
+      },
+
+      onInstallFailed: function(aInstall) {
+        do_throw("Should not have seen onInstallFailed event");
+      },
+
+      onInstallCancelled: function(aInstall) {
+        do_throw("Should not have seen onInstallCancelled event");
+      },
+    });
+
+    // Fake a timer event
+    gInternalManager.notify(null);
+  });
+}
+
+function check_test_14(install) {
+  do_check_eq(install.existingAddon.pendingUpgrade.install, install);
+
+  restartManager();
+  AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+                               "addon8@tests.mozilla.org"], function([a1, a8]) {
+    do_check_neq(a1, null);
+    do_check_eq(a1.version, "2.0");
+    a1.uninstall();
+
+    do_check_neq(a8, null);
+    do_check_eq(a8.version, "1.0");
+    a8.uninstall();
+
+    restartManager();
+
+    run_test_15();
+  });
+}
+
+// Test that background update checks doesn't update an add-on that is
+// pending uninstall
+function run_test_15() {
+  // Have an add-on there that will be updated so we see some events from it
+  writeInstallRDFForExtension({
+    id: "addon1@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_update.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon 1",
+  }, profileDir);
+
+  writeInstallRDFForExtension({
+    id: "addon8@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_update.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon 8",
+  }, profileDir);
+  restartManager();
+
+  AddonManager.getAddonByID("addon8@tests.mozilla.org", function(a8) {
+    a8.uninstall();
+    do_check_false(hasFlag(a8.permissions, AddonManager.PERM_CAN_UPGRADE));
+
+    // The background update check will find updates for both add-ons but only
+    // proceed to install one of them.
+    AddonManager.addInstallListener({
+      onNewInstall: function(aInstall) {
+        if (aInstall.existingAddon.id != "addon1@tests.mozilla.org" &&
+            aInstall.existingAddon.id != "addon8@tests.mozilla.org")
+          do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id);
+      },
+
+      onDownloadStarted: function(aInstall) {
+        do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org");
+      },
+
+      onDownloadEnded: function(aInstall) {
+        do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org");
+      },
+
+      onDownloadFailed: function(aInstall) {
+        do_throw("Should not have seen onDownloadFailed event");
+      },
+
+      onDownloadCancelled: function(aInstall) {
+        do_throw("Should not have seen onDownloadCancelled event");
+      },
+
+      onInstallStarted: function(aInstall) {
+        do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org");
+      },
+
+      onInstallEnded: function(aInstall) {
+        do_check_eq(aInstall.existingAddon.id, "addon1@tests.mozilla.org");
+        check_test_15(aInstall);
+      },
+
+      onInstallFailed: function(aInstall) {
+        do_throw("Should not have seen onInstallFailed event");
+      },
+
+      onInstallCancelled: function(aInstall) {
+        do_throw("Should not have seen onInstallCancelled event");
+      },
+    });
+
+    // Fake a timer event
+    gInternalManager.notify(null);
+  });
+}
+
+function check_test_15(aInstall) {
+  restartManager();
+  AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+                               "addon8@tests.mozilla.org"], function([a1, a8]) {
+    do_check_neq(a1, null);
+    do_check_eq(a1.version, "2.0");
+    a1.uninstall();
+
+    do_check_eq(a8, null);
+
+    restartManager();
+
+    end_test();
+  });
+}
--- a/toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade.js
@@ -1,13 +1,16 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
-// This verifies that app upgrades produce the expected behaviours.
+// This verifies that app upgrades produce the expected behaviours,
+// with strict compatibility checking disabled.
+
+Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false);
 
 // Enable loading extensions from the application scope
 Services.prefs.setIntPref("extensions.enabledScopes",
                           AddonManager.SCOPE_PROFILE +
                           AddonManager.SCOPE_APPLICATION);
 
 const profileDir = gProfD.clone();
 profileDir.append("extensions");
@@ -16,17 +19,17 @@ const globalDir = Services.dirsvc.get("X
 globalDir.append("extensions");
 
 var gGlobalExisted = globalDir.exists();
 var gInstallTime = Date.now();
 
 function run_test() {
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
 
-  // Will be enabled in the first version and disabled in subsequent versions
+  // Will be compatible in the first version and incompatible in subsequent versions
   writeInstallRDFForExtension({
     id: "addon1@tests.mozilla.org",
     version: "1.0",
     targetApplications: [{
       id: "xpcshell@tests.mozilla.org",
       minVersion: "1",
       maxVersion: "1"
     }],
@@ -47,29 +50,29 @@ function run_test() {
       maxVersion: "2"
     }],
     name: "Test Addon 2",
     targetPlatforms: [
       "XPCShell_noarch-spidermonkey"
     ]
   }, profileDir);
 
-  // Will be disabled in the first version and enabled in the second.
+  // Will be incompatible in the first version and enabled in the second.
   writeInstallRDFForExtension({
     id: "addon3@tests.mozilla.org",
     version: "1.0",
     targetApplications: [{
       id: "xpcshell@tests.mozilla.org",
       minVersion: "2",
       maxVersion: "2"
     }],
     name: "Test Addon 3",
   }, profileDir);
 
-  // Will be enabled in both versions but will change version in between
+  // Will be compatible in both versions but will change version in between
   var dest = writeInstallRDFForExtension({
     id: "addon4@tests.mozilla.org",
     version: "1.0",
     targetApplications: [{
       id: "xpcshell@tests.mozilla.org",
       minVersion: "1",
       maxVersion: "1"
     }],
@@ -105,27 +108,27 @@ function run_test_1() {
 
     do_check_neq(a1, null);
     do_check_true(isExtensionInAddonsList(profileDir, a1.id));
 
     do_check_neq(a2, null);
     do_check_true(isExtensionInAddonsList(profileDir, a2.id));
 
     do_check_neq(a3, null);
-    do_check_false(isExtensionInAddonsList(profileDir, a3.id));
+    do_check_true(isExtensionInAddonsList(profileDir, a3.id));
 
     do_check_neq(a4, null);
     do_check_true(isExtensionInAddonsList(globalDir, a4.id));
     do_check_eq(a4.version, "1.0");
 
     run_test_2();
   });
 }
 
-// Test that upgrading the application disables now incompatible add-ons
+// Test that upgrading the application doesn't disable now incompatible add-ons
 function run_test_2() {
   // Upgrade the extension
   var dest = writeInstallRDFForExtension({
     id: "addon4@tests.mozilla.org",
     version: "2.0",
     targetApplications: [{
       id: "xpcshell@tests.mozilla.org",
       minVersion: "2",
@@ -138,17 +141,17 @@ function run_test_2() {
   restartManager("2");
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                "addon2@tests.mozilla.org",
                                "addon3@tests.mozilla.org",
                                "addon4@tests.mozilla.org"],
                                function([a1, a2, a3, a4]) {
 
     do_check_neq(a1, null);
-    do_check_false(isExtensionInAddonsList(profileDir, a1.id));
+    do_check_true(isExtensionInAddonsList(profileDir, a1.id));
 
     do_check_neq(a2, null);
     do_check_true(isExtensionInAddonsList(profileDir, a2.id));
 
     do_check_neq(a3, null);
     do_check_true(isExtensionInAddonsList(profileDir, a3.id));
 
     do_check_neq(a4, null);
@@ -183,17 +186,17 @@ function run_test_3() {
 
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                "addon2@tests.mozilla.org",
                                "addon3@tests.mozilla.org",
                                "addon4@tests.mozilla.org"],
                                function([a1, a2, a3, a4]) {
 
     do_check_neq(a1, null);
-    do_check_false(isExtensionInAddonsList(profileDir, a1.id));
+    do_check_true(isExtensionInAddonsList(profileDir, a1.id));
 
     do_check_neq(a2, null);
     do_check_true(isExtensionInAddonsList(profileDir, a2.id));
 
     do_check_neq(a3, null);
     do_check_true(isExtensionInAddonsList(profileDir, a3.id));
 
     do_check_neq(a4, null);
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_upgrade_strictcompat.js
@@ -0,0 +1,211 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// This verifies that app upgrades produce the expected behaviours,
+// with strict compatibility checking enabled.
+
+// Enable loading extensions from the application scope
+Services.prefs.setIntPref("extensions.enabledScopes",
+                          AddonManager.SCOPE_PROFILE +
+                          AddonManager.SCOPE_APPLICATION);
+
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+const globalDir = Services.dirsvc.get("XCurProcD", AM_Ci.nsILocalFile);
+globalDir.append("extensions");
+
+var gGlobalExisted = globalDir.exists();
+var gInstallTime = Date.now();
+
+function run_test() {
+  createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
+
+  // Will be enabled in the first version and disabled in subsequent versions
+  writeInstallRDFForExtension({
+    id: "addon1@tests.mozilla.org",
+    version: "1.0",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon 1",
+    targetPlatforms: [
+      "XPCShell",
+      "WINNT_x86",
+    ]
+  }, profileDir);
+
+  // Works in all tested versions
+  writeInstallRDFForExtension({
+    id: "addon2@tests.mozilla.org",
+    version: "1.0",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "2"
+    }],
+    name: "Test Addon 2",
+    targetPlatforms: [
+      "XPCShell_noarch-spidermonkey"
+    ]
+  }, profileDir);
+
+  // Will be disabled in the first version and enabled in the second.
+  writeInstallRDFForExtension({
+    id: "addon3@tests.mozilla.org",
+    version: "1.0",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "2",
+      maxVersion: "2"
+    }],
+    name: "Test Addon 3",
+  }, profileDir);
+
+  // Will be enabled in both versions but will change version in between
+  var dest = writeInstallRDFForExtension({
+    id: "addon4@tests.mozilla.org",
+    version: "1.0",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon 4",
+  }, globalDir);
+  setExtensionModifiedTime(dest, gInstallTime);
+
+  do_test_pending();
+
+  Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true);
+
+  run_test_1();
+}
+
+function end_test() {
+  if (!gGlobalExisted) {
+    globalDir.remove(true);
+  }
+  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();
+}
+
+// Test that the test extensions are all installed
+function run_test_1() {
+  startupManager();
+
+  AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+                               "addon2@tests.mozilla.org",
+                               "addon3@tests.mozilla.org",
+                               "addon4@tests.mozilla.org"],
+                               function([a1, a2, a3, a4]) {
+
+    do_check_neq(a1, null);
+    do_check_true(isExtensionInAddonsList(profileDir, a1.id));
+
+    do_check_neq(a2, null);
+    do_check_true(isExtensionInAddonsList(profileDir, a2.id));
+
+    do_check_neq(a3, null);
+    do_check_false(isExtensionInAddonsList(profileDir, a3.id));
+
+    do_check_neq(a4, null);
+    do_check_true(isExtensionInAddonsList(globalDir, a4.id));
+    do_check_eq(a4.version, "1.0");
+
+    run_test_2();
+  });
+}
+
+// Test that upgrading the application disables now incompatible add-ons
+function run_test_2() {
+  // Upgrade the extension
+  var dest = writeInstallRDFForExtension({
+    id: "addon4@tests.mozilla.org",
+    version: "2.0",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "2",
+      maxVersion: "2"
+    }],
+    name: "Test Addon 4",
+  }, globalDir);
+  setExtensionModifiedTime(dest, gInstallTime);
+
+  restartManager("2");
+  AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+                               "addon2@tests.mozilla.org",
+                               "addon3@tests.mozilla.org",
+                               "addon4@tests.mozilla.org"],
+                               function([a1, a2, a3, a4]) {
+
+    do_check_neq(a1, null);
+    do_check_false(isExtensionInAddonsList(profileDir, a1.id));
+
+    do_check_neq(a2, null);
+    do_check_true(isExtensionInAddonsList(profileDir, a2.id));
+
+    do_check_neq(a3, null);
+    do_check_true(isExtensionInAddonsList(profileDir, a3.id));
+
+    do_check_neq(a4, null);
+    do_check_true(isExtensionInAddonsList(globalDir, a4.id));
+    do_check_eq(a4.version, "2.0");
+
+    run_test_3();
+  });
+}
+
+// Test that nothing changes when only the build ID changes.
+function run_test_3() {
+  // Upgrade the extension
+  var dest = writeInstallRDFForExtension({
+    id: "addon4@tests.mozilla.org",
+    version: "3.0",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "3",
+      maxVersion: "3"
+    }],
+    name: "Test Addon 4",
+  }, globalDir);
+  setExtensionModifiedTime(dest, gInstallTime);
+
+  // Simulates a simple Build ID change, the platform deletes extensions.ini
+  // whenever the application is changed.
+  var file = gProfD.clone();
+  file.append("extensions.ini");
+  file.remove(true);
+  restartManager();
+
+  AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
+                               "addon2@tests.mozilla.org",
+                               "addon3@tests.mozilla.org",
+                               "addon4@tests.mozilla.org"],
+                               function([a1, a2, a3, a4]) {
+
+    do_check_neq(a1, null);
+    do_check_false(isExtensionInAddonsList(profileDir, a1.id));
+
+    do_check_neq(a2, null);
+    do_check_true(isExtensionInAddonsList(profileDir, a2.id));
+
+    do_check_neq(a3, null);
+    do_check_true(isExtensionInAddonsList(profileDir, a3.id));
+
+    do_check_neq(a4, null);
+    do_check_true(isExtensionInAddonsList(globalDir, a4.id));
+    do_check_eq(a4.version, "2.0");
+
+    end_test();
+  });
+}
--- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
+++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
@@ -65,22 +65,28 @@ skip-if = os == "android"
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
 [test_bug468528.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
 [test_bug470377_1.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
+[test_bug470377_1_strictcompat.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug470377_2.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
 [test_bug470377_3.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
+[test_bug470377_3_strictcompat.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_bug470377_4.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
 [test_bug514327_1.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
 [test_bug514327_2.js]
 # Bug 676992: test consistently hangs on Android
@@ -116,16 +122,17 @@ fail-if = os == "android"
 [test_bug619730.js]
 [test_bug620837.js]
 [test_bug655254.js]
 [test_bug659772.js]
 [test_bug675371.js]
 [test_cacheflush.js]
 [test_checkcompatibility.js]
 [test_corrupt.js]
+[test_corrupt_strictcompat.js]
 [test_dictionary.js]
 [test_disable.js]
 [test_distribution.js]
 [test_dss.js]
 # Bug 676992: test consistently fails on Android
 fail-if = os == "android"
 [test_duplicateplugins.js]
 # Bug 676992: test consistently hangs on Android
@@ -148,44 +155,54 @@ skip-if = os == "android"
 [test_gfxBlacklist_GTE_OK.js]
 [test_gfxBlacklist_OK.js]
 [test_gfxBlacklist_OS.js]
 [test_gfxBlacklist_Vendor.js]
 [test_gfxBlacklist_prefs.js]
 [test_install.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
+[test_install_strictcompat.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_locale.js]
 [test_locked.js]
+[test_locked_strictcompat.js]
 [test_manifest.js]
 [test_migrate1.js]
 [test_migrate2.js]
 [test_migrate3.js]
 [test_migrate4.js]
 [test_migrateAddonRepository.js]
 [test_permissions.js]
 [test_plugins.js]
 # Bug 676992: test consistently fails on Android
 fail-if = os == "android"
 [test_registry.js]
 [test_safemode.js]
 [test_startup.js]
 # Bug 676992: test consistently fails on Android
 fail-if = os == "android"
+[test_strictcompatibility.js]
 [test_targetPlatforms.js]
 [test_theme.js]
 # Bug 676992: test consistently fails on Android
 fail-if = os == "android"
 [test_types.js]
 [test_uninstall.js]
 [test_update.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
+[test_update_strictcompat.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
 [test_updatecheck.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
 [test_updateid.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
 [test_upgrade.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
-
+[test_upgrade_strictcompat.js]
+# Bug 676992: test consistently hangs on Android
+skip-if = os == "android"
--- a/toolkit/mozapps/update/test/chrome/utils.js
+++ b/toolkit/mozapps/update/test/chrome/utils.js
@@ -811,16 +811,17 @@ function setupPrefs() {
   }
   let extUpdateUrl = URL_UPDATE + "?addonID=%ITEM_ID%&platformVersion=" +
                      getNewerPlatformVersion();
   Services.prefs.setCharPref(PREF_EXTENSIONS_UPDATE_URL, extUpdateUrl);
   debugDump("extensions.update.url: " + extUpdateUrl);
 
   Services.prefs.setIntPref(PREF_APP_UPDATE_IDLETIME, 0);
   Services.prefs.setIntPref(PREF_APP_UPDATE_PROMPTWAITTIME, 0);
+  Services.prefs.setBoolPref(PREF_EXTENSIONS_STRICT_COMPAT, true);
 }
 
 /**
  * Resets the most common preferences used by tests to their original values.
  */
 function resetPrefs() {
   if (gAppUpdateURL !== undefined) {
     Services.prefs.setCharPref(PREF_APP_UPDATE_URL_OVERRIDE, gAppUpdateURL);
@@ -908,16 +909,20 @@ function resetPrefs() {
   catch (e) {
   }
 
   try {
     Services.prefs.deleteBranch(PREF_APP_UPDATE_NEVER_BRANCH);
   }
   catch(e) {
   }
+
+  if (Services.prefs.prefHasUserValue(PREF_EXTENSIONS_STRICT_COMPAT)) {
+		Services.prefs.clearUserPref(PREF_EXTENSIONS_STRICT_COMPAT);
+  }
 }
 
 /**
  * Disables pre-existing add-ons so they don't interfere with the tests,
  * installs the test add-ons, sets the noupdate test add-ons' userDisabled value
  * for the test, and calls the callback specified in the aCallback parameter. If
  * the app.update.test.disabledAddons has a user value then setting the noupdate
  * test add-ons' userDisabled value for the test is the only thing that is done.
--- a/toolkit/mozapps/update/test/shared.js
+++ b/toolkit/mozapps/update/test/shared.js
@@ -68,16 +68,17 @@ const PREF_APP_UPDATE_URL_OVERRIDE      
 const PREF_APP_UPDATE_CERT_INVALID_ATTR_NAME = PREF_APP_UPDATE_CERTS_BRANCH +
                                                "1.invalidName";
 
 const PREF_APP_PARTNER_BRANCH             = "app.partner.";
 const PREF_DISTRIBUTION_ID                = "distribution.id";
 const PREF_DISTRIBUTION_VERSION           = "distribution.version";
 
 const PREF_EXTENSIONS_UPDATE_URL          = "extensions.update.url";
+const PREF_EXTENSIONS_STRICT_COMPAT       = "extensions.strictCompatibility";
 
 const NS_APP_PROFILE_DIR_STARTUP   = "ProfDS";
 const NS_APP_USER_PROFILE_50_DIR   = "ProfD";
 const NS_GRE_DIR                   = "GreD";
 const NS_XPCOM_CURRENT_PROCESS_DIR = "XCurProcD";
 const XRE_UPDATE_ROOT_DIR          = "UpdRootD";
 
 const CRC_ERROR   = 4;