Bug 527141 - Addon update check should take into account compatibility preferences. r=dtownsend
authorBlair McBride <bmcbride@mozilla.com>
Fri, 02 Dec 2011 15:28:16 +1300
changeset 81946 b31691b620ba4d7accd787e3f48bc0bf9e2566b1
parent 81945 29879af41d58d7d3a5e36fd02b04a14aceb69aa6
child 81947 ac0b6507910646934c70e4b3007b4079ea05fb54
push idunknown
push userunknown
push dateunknown
reviewersdtownsend
bugs527141
milestone11.0a1
Bug 527141 - Addon update check should take into account compatibility preferences. r=dtownsend
browser/app/profile/firefox.js
toolkit/mozapps/extensions/AddonManager.jsm
toolkit/mozapps/extensions/AddonRepository.jsm
toolkit/mozapps/extensions/AddonUpdateChecker.jsm
toolkit/mozapps/extensions/XPIProvider.jsm
toolkit/mozapps/extensions/test/xpcshell/data/test_update.rdf
toolkit/mozapps/extensions/test/xpcshell/data/test_update.xml
toolkit/mozapps/extensions/test/xpcshell/data/test_updatecheck.rdf
toolkit/mozapps/extensions/test/xpcshell/data/test_updatecompatmode_ignore.rdf
toolkit/mozapps/extensions/test/xpcshell/data/test_updatecompatmode_normal.rdf
toolkit/mozapps/extensions/test/xpcshell/data/test_updatecompatmode_strict.rdf
toolkit/mozapps/extensions/test/xpcshell/test_update.js
toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js
toolkit/mozapps/extensions/test/xpcshell/test_update_ignorecompat.js
toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js
toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js
toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -198,17 +198,17 @@ pref("app.update.incompatible.mode", 0);
 
 // Symmetric (can be overridden by individual extensions) update preferences.
 // e.g.
 //  extensions.{GUID}.update.enabled
 //  extensions.{GUID}.update.url
 //  .. etc ..
 //
 pref("extensions.update.enabled", true);
-pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%&currentAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%");
+pref("extensions.update.url", "https://versioncheck.addons.mozilla.org/update/VersionCheck.php?reqVersion=%REQ_VERSION%&id=%ITEM_ID%&version=%ITEM_VERSION%&maxAppVersion=%ITEM_MAXAPPVERSION%&status=%ITEM_STATUS%&appID=%APP_ID%&appVersion=%APP_VERSION%&appOS=%APP_OS%&appABI=%APP_ABI%&locale=%APP_LOCALE%&currentAppVersion=%CURRENT_APP_VERSION%&updateType=%UPDATE_TYPE%&compatMode=%COMPATIBILITY_MODE%");
 pref("extensions.update.interval", 86400);  // Check for updates to Extensions and 
                                             // Themes every day
 // Non-symmetric (not shared by extensions) extension-specific [update] preferences
 pref("extensions.getMoreThemesURL", "https://addons.mozilla.org/%LOCALE%/firefox/getpersonas");
 pref("extensions.dss.enabled", false);          // Dynamic Skin Switching                                               
 pref("extensions.dss.switchPending", false);    // Non-dynamic switch pending after next
                                                 // restart.
 
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -16,16 +16,17 @@
 #
 # The Initial Developer of the Original Code is
 # the Mozilla Foundation.
 # Portions created by the Initial Developer are Copyright (C) 2009
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #   Dave Townsend <dtownsend@oxymoronical.com>
+#   Blair McBride <bmcbride@mozilla.com>
 #
 # 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
@@ -611,58 +612,60 @@ var AddonManagerInternal = {
    * 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);
-    let pendingUpdates = 1;
+    let pendingUpdates = 0;
 
     function notifyComplete() {
       if (--pendingUpdates == 0) {
-        AddonManagerInternal.updateAddonRepositoryData(function BUC_updateAddonCallback() {
-          Services.obs.notifyObservers(null,
-                                       "addons-background-update-complete",
-                                       null);
-        });
+        Services.obs.notifyObservers(null,
+                                     "addons-background-update-complete",
+                                     null);
       }
     }
 
     let scope = {};
     Components.utils.import("resource://gre/modules/AddonRepository.jsm", scope);
     Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", scope);
     scope.LightweightThemeManager.updateCurrentTheme();
 
     this.getAllAddons(function getAddonsCallback(aAddons) {
-      pendingUpdates++;
+      // Repopulate repository cache first, to ensure compatibility overrides
+      // are up to date before checking for addon updates.
       var ids = [a.id for each (a in aAddons)];
-      scope.AddonRepository.repopulateCache(ids, notifyComplete);
+      scope.AddonRepository.repopulateCache(ids, function BUC_repopulateCacheCallback() {
+        AddonManagerInternal.updateAddonRepositoryData(function BUC_updateAddonCallback() {
 
-      pendingUpdates += aAddons.length;
+          pendingUpdates += aAddons.length;
 
-      aAddons.forEach(function BUC_forEachCallback(aAddon) {
-        // Check all add-ons for updates so that any compatibility updates will
-        // be applied
-        aAddon.findUpdates({
-          onUpdateAvailable: function BUC_onUpdateAvailable(aAddon, aInstall) {
-            // Start installing updates when the add-on can be updated and
-            // background updates should be applied.
-            if (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE &&
-                AddonManager.shouldAutoUpdate(aAddon)) {
-              aInstall.install();
-            }
-          },
-
-          onUpdateFinished: notifyComplete
-        }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE);
+          aAddons.forEach(function BUC_forEachCallback(aAddon) {
+            // Check all add-ons for updates so that any compatibility updates will
+            // be applied
+            aAddon.findUpdates({
+              onUpdateAvailable: function BUC_onUpdateAvailable(aAddon, aInstall) {
+                // Start installing updates when the add-on can be updated and
+                // background updates should be applied.
+                if (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE &&
+                    AddonManager.shouldAutoUpdate(aAddon)) {
+                  aInstall.install();
+                }
+              },
+    
+              onUpdateFinished: notifyComplete
+            }, AddonManager.UPDATE_WHEN_PERIODIC_UPDATE);
+          });
+    
+          notifyComplete();
+        });
       });
-
-      notifyComplete();
     });
   },
 
   /**
    * Adds a add-on to the list of detected changes for this startup. If
    * addStartupChange is called multiple times for the same add-on in the same
    * startup then only the most recent change will be remembered.
    *
--- a/toolkit/mozapps/extensions/AddonRepository.jsm
+++ b/toolkit/mozapps/extensions/AddonRepository.jsm
@@ -1412,25 +1412,27 @@ var AddonRepository = {
     });
 
     return Services.urlFormatter.formatURL(url);
   },
 
   // Find a AddonCompatibilityOverride that matches a given aAddonVersion and
   // application/platform version.
   findMatchingCompatOverride: function AR_findMatchingCompatOverride(aAddonVersion,
-                                                                     aCompatOverrides) {
+                                                                     aCompatOverrides,
+                                                                     aAppVersion,
+                                                                     aPlatformVersion) {
     for (let i = 0; i < aCompatOverrides.length; i++) {
       let override = aCompatOverrides[i];
 
       let appVersion = null;
       if (override.appID == TOOLKIT_ID)
-        appVersion = Services.appinfo.platformVersion;
+        appVersion = aPlatformVersion || Services.appinfo.platformVersion;
       else
-        appVersion = Services.appinfo.version;
+        appVersion = aAppVersion || Services.appinfo.version;
 
       if (Services.vc.compare(override.minVersion, aAddonVersion) <= 0 &&
           Services.vc.compare(aAddonVersion, override.maxVersion) <= 0 &&
           Services.vc.compare(override.appMinVersion, appVersion) <= 0 &&
           Services.vc.compare(appVersion, override.appMaxVersion) <= 0) {
         return override;
       }
     }
--- a/toolkit/mozapps/extensions/AddonUpdateChecker.jsm
+++ b/toolkit/mozapps/extensions/AddonUpdateChecker.jsm
@@ -16,16 +16,17 @@
 #
 # The Initial Developer of the Original Code is
 # the Mozilla Foundation.
 # Portions created by the Initial Developer are Copyright (C) 2009
 # the Initial Developer. All Rights Reserved.
 #
 # Contributor(s):
 #   Dave Townsend <dtownsend@oxymoronical.com>
+#   Blair McBride <bmcbride@mozilla.com>
 #
 # 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
@@ -56,16 +57,17 @@ const PREFIX_ITEM           = "urn:mozil
 const PREFIX_EXTENSION      = "urn:mozilla:extension:";
 const PREFIX_THEME          = "urn:mozilla:theme:";
 const TOOLKIT_ID            = "toolkit@mozilla.org"
 const XMLURI_PARSE_ERROR    = "http://www.mozilla.org/newlayout/xml/parsererror.xml"
 
 const PREF_UPDATE_REQUIREBUILTINCERTS = "extensions.update.requireBuiltInCerts";
 
 Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource://gre/modules/AddonRepository.jsm");
 // shared code for suppressing bad cert dialogs
 Components.utils.import("resource://gre/modules/CertUtils.jsm");
 
 var gRDF = Cc["@mozilla.org/rdf/rdf-service;1"].
            getService(Ci.nsIRDFService);
 
 ["LOG", "WARN", "ERROR"].forEach(function(aName) {
   this.__defineGetter__(aName, function() {
@@ -589,29 +591,43 @@ UpdateParser.prototype = {
  * Tests if an update matches a version of the application or platform
  *
  * @param  aUpdate
  *         The available update
  * @param  aAppVersion
  *         The application version to use
  * @param  aPlatformVersion
  *         The platform version to use
+ * @param  aIgnoreMaxVersion
+ *         Ignore maxVersion when testing if an update matches. Optional.
+ * @param  aCompatOverrides
+ *         AddonCompatibilityOverride objects to match against. Optional.
  * @return true if the update is compatible with the application/platform
  */
-function matchesVersions(aUpdate, aAppVersion, aPlatformVersion) {
+function matchesVersions(aUpdate, aAppVersion, aPlatformVersion,
+                         aIgnoreMaxVersion, aCompatOverrides) {
+  if (aCompatOverrides) {
+    let override = AddonRepository.findMatchingCompatOverride(aUpdate.version,
+                                                              aCompatOverrides,
+                                                              aAppVersion,
+                                                              aPlatformVersion);
+    if (override && override.type == "incompatible")
+      return false;
+  }
+
   let result = false;
   for (let i = 0; i < aUpdate.targetApplications.length; i++) {
     let app = aUpdate.targetApplications[i];
     if (app.id == Services.appinfo.ID) {
       return (Services.vc.compare(aAppVersion, app.minVersion) >= 0) &&
-             (Services.vc.compare(aAppVersion, app.maxVersion) <= 0);
+             (aIgnoreMaxVersion || (Services.vc.compare(aAppVersion, app.maxVersion) <= 0));
     }
     if (app.id == TOOLKIT_ID) {
       result = (Services.vc.compare(aPlatformVersion, app.minVersion) >= 0) &&
-               (Services.vc.compare(aPlatformVersion, app.maxVersion) <= 0);
+               (aIgnoreMaxVersion || (Services.vc.compare(aPlatformVersion, app.maxVersion) <= 0));
     }
   }
   return result;
 }
 
 var AddonUpdateChecker = {
   // These must be kept in sync with AddonManager
   // The update check timed out
@@ -635,58 +651,68 @@ var AddonUpdateChecker = {
    *         The version of the add-on to get new compatibility information for
    * @param  aIgnoreCompatibility
    *         An optional parameter to get the first compatibility update that
    *         is compatible with any version of the application or toolkit
    * @param  aAppVersion
    *         The version of the application or null to use the current version
    * @param  aPlatformVersion
    *         The version of the platform or null to use the current version
+   * @param  aIgnoreMaxVersion
+   *         Ignore maxVersion when testing if an update matches. Optional.
    * @return an update object if one matches or null if not
    */
   getCompatibilityUpdate: function AUC_getCompatibilityUpdate(aUpdates, aVersion,
                                                               aIgnoreCompatibility,
                                                               aAppVersion,
-                                                              aPlatformVersion) {
+                                                              aPlatformVersion,
+                                                              aIgnoreMaxVersion) {
     if (!aAppVersion)
       aAppVersion = Services.appinfo.version;
     if (!aPlatformVersion)
       aPlatformVersion = Services.appinfo.platformVersion;
 
     for (let i = 0; i < aUpdates.length; i++) {
       if (Services.vc.compare(aUpdates[i].version, aVersion) == 0) {
         if (aIgnoreCompatibility) {
           for (let j = 0; j < aUpdates[i].targetApplications.length; j++) {
             let id = aUpdates[i].targetApplications[j].id;
             if (id == Services.appinfo.ID || id == TOOLKIT_ID)
               return aUpdates[i];
           }
         }
-        else if (matchesVersions(aUpdates[i], aAppVersion, aPlatformVersion)) {
+        else if (matchesVersions(aUpdates[i], aAppVersion, aPlatformVersion,
+                                 aIgnoreMaxVersion)) {
           return aUpdates[i];
         }
       }
     }
     return null;
   },
 
   /**
    * Returns the newest available update from a list of update objects.
    *
    * @param  aUpdates
    *         An array of update objects
    * @param  aAppVersion
    *         The version of the application or null to use the current version
    * @param  aPlatformVersion
    *         The version of the platform or null to use the current version
+   * @param  aIgnoreMaxVersion
+   *         When determining compatible updates, ignore maxVersion. Optional.
+   * @param  aCompatOverrides
+   *         Array of AddonCompatibilityOverride to take into account. Optional.
    * @return an update object if one matches or null if not
    */
   getNewestCompatibleUpdate: function AUC_getNewestCompatibleUpdate(aUpdates,
                                                                     aAppVersion,
-                                                                    aPlatformVersion) {
+                                                                    aPlatformVersion,
+                                                                    aIgnoreMaxVersion,
+                                                                    aCompatOverrides) {
     if (!aAppVersion)
       aAppVersion = Services.appinfo.version;
     if (!aPlatformVersion)
       aPlatformVersion = Services.appinfo.platformVersion;
 
     let blocklist = Cc["@mozilla.org/extensions/blocklist;1"].
                     getService(Ci.nsIBlocklistService);
 
@@ -694,18 +720,20 @@ var AddonUpdateChecker = {
     for (let i = 0; i < aUpdates.length; i++) {
       if (!aUpdates[i].updateURL)
         continue;
       let state = blocklist.getAddonBlocklistState(aUpdates[i].id, aUpdates[i].version,
                                                    aAppVersion, aPlatformVersion);
       if (state != Ci.nsIBlocklistService.STATE_NOT_BLOCKED)
         continue;
       if ((newest == null || (Services.vc.compare(newest.version, aUpdates[i].version) < 0)) &&
-          matchesVersions(aUpdates[i], aAppVersion, aPlatformVersion))
+          matchesVersions(aUpdates[i], aAppVersion, aPlatformVersion,
+                          aIgnoreMaxVersion, aCompatOverrides)) {
         newest = aUpdates[i];
+      }
     }
     return newest;
   },
 
   /**
    * Starts an update check.
    *
    * @param  aId
--- a/toolkit/mozapps/extensions/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/XPIProvider.jsm
@@ -1169,16 +1169,23 @@ function escapeAddonURI(aAddon, aUri, aU
   // maxVersion
   let app = aAddon.matchingTargetApplication;
   if (app)
     var maxVersion = app.maxVersion;
   else
     maxVersion = "";
   uri = uri.replace(/%ITEM_MAXAPPVERSION%/g, maxVersion);
 
+  let compatMode = "normal";
+  if (!XPIProvider.checkCompatibility)
+    compatMode = "ignore";
+  else if (AddonManager.strictCompatibility)
+    compatMode = "strict";
+  uri = uri.replace(/%COMPATIBILITY_MODE%/g, compatMode);
+
   // Replace custom parameters (names of custom parameters must have at
   // least 3 characters to prevent lookups for something like %D0%C8)
   var catMan = null;
   uri = uri.replace(/%(\w{3,})%/g, function(aMatch, aParam) {
     if (!catMan) {
       catMan = Cc["@mozilla.org/categorymanager;1"].
                getService(Ci.nsICategoryManager);
     }
@@ -7002,34 +7009,46 @@ UpdateChecker.prototype = {
    * Called when AddonUpdateChecker completes the update check
    *
    * @param  updates
    *         The list of update details for the add-on
    */
   onUpdateCheckComplete: function UC_onUpdateCheckComplete(aUpdates) {
     let AUC = AddonUpdateChecker;
 
+    let ignoreMaxVersion = false;
+    if (!XPIProvider.checkCompatibility) {
+      ignoreMaxVersion = true;
+    } else if (this.addon.type == "extension" &&
+               !AddonManager.strictCompatibility &&
+               !this.addon.strictCompatibility &&
+               !this.addon.hasBinaryComponents) {
+      ignoreMaxVersion = true;
+    }
+
     // Always apply any compatibility update for the current version
     let compatUpdate = AUC.getCompatibilityUpdate(aUpdates, this.addon.version,
-                                                  this.syncCompatibility);
-
+                                                  this.syncCompatibility,
+                                                  null, null,
+                                                  ignoreMaxVersion);
     // Apply the compatibility update to the database
     if (compatUpdate)
       this.addon.applyCompatibilityUpdate(compatUpdate, this.syncCompatibility);
 
     // If the request is for an application or platform version that is
     // different to the current application or platform version then look for a
     // compatibility update for those versions.
     if ((this.appVersion &&
          Services.vc.compare(this.appVersion, Services.appinfo.version) != 0) ||
         (this.platformVersion &&
          Services.vc.compare(this.platformVersion, Services.appinfo.platformVersion) != 0)) {
       compatUpdate = AUC.getCompatibilityUpdate(aUpdates, this.addon.version,
                                                 false, this.appVersion,
-                                                this.platformVersion);
+                                                this.platformVersion,
+                                                ignoreMaxVersion);
     }
 
     if (compatUpdate)
       this.callListener("onCompatibilityUpdateAvailable", createWrapper(this.addon));
     else
       this.callListener("onNoCompatibilityUpdateAvailable", createWrapper(this.addon));
 
     function sendUpdateAvailableMessages(aSelf, aInstall) {
@@ -7039,19 +7058,25 @@ UpdateChecker.prototype = {
       }
       else {
         aSelf.callListener("onNoUpdateAvailable", createWrapper(aSelf.addon));
       }
       aSelf.callListener("onUpdateFinished", createWrapper(aSelf.addon),
                          AddonManager.UPDATE_STATUS_NO_ERROR);
     }
 
+    let compatOverrides = AddonManager.strictCompatibility ?
+                            null :
+                            this.addon.compatibilityOverrides;
+
     let update = AUC.getNewestCompatibleUpdate(aUpdates,
                                                this.appVersion,
-                                               this.platformVersion);
+                                               this.platformVersion,
+                                               ignoreMaxVersion,
+                                               compatOverrides);
 
     if (update && Services.vc.compare(this.addon.version, update.version) < 0) {
       for (let i = 0; i < XPIProvider.installs.length; i++) {
         // Skip installs that don't match the available update
         if (XPIProvider.installs[i].existingAddon != this.addon ||
             XPIProvider.installs[i].version != update.version)
           continue;
 
--- a/toolkit/mozapps/extensions/test/xpcshell/data/test_update.rdf
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_update.rdf
@@ -139,9 +139,91 @@
                 <em:updateLink>http://localhost:4444/addons/test_update8.xpi</em:updateLink>
               </Description>
             </em:targetApplication>
           </Description>
         </li>
       </Seq>
     </em:updates>
   </Description>
+
+  <Description about="urn:mozilla:extension:addon9@tests.mozilla.org">
+    <em:updates>
+      <Seq>
+        <li>
+          <Description>
+            <em:version>2.0</em:version>
+            <em:targetApplication>
+              <Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>1</em:minVersion>
+                <em:maxVersion>1</em:maxVersion>
+                <em:updateLink>http://localhost:4444/addons/test_update9_2.xpi</em:updateLink>
+              </Description>
+            </em:targetApplication>
+          </Description>
+        </li>
+        <!-- Incompatible when strict compatibility is enabled -->
+        <li>
+          <Description>
+            <em:version>3.0</em:version>
+            <em:targetApplication>
+              <Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>0.9</em:minVersion>
+                <em:maxVersion>0.9</em:maxVersion>
+                <em:updateLink>http://localhost:4444/addons/test_update9_3.xpi</em:updateLink>
+              </Description>
+            </em:targetApplication>
+          </Description>
+        </li>
+        <!-- Incompatible due to compatibility override -->
+        <li>
+          <Description>
+            <em:version>4.0</em:version>
+            <em:targetApplication>
+              <Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>0.9</em:minVersion>
+                <em:maxVersion>0.9</em:maxVersion>
+                <em:updateLink>http://localhost:4444/addons/test_update9_4.xpi</em:updateLink>
+              </Description>
+            </em:targetApplication>
+          </Description>
+        </li>
+        <!-- Addon for future version of app -->
+        <li>
+          <Description>
+            <em:version>5.0</em:version>
+            <em:targetApplication>
+              <Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>5</em:minVersion>
+                <em:maxVersion>6</em:maxVersion>
+                <em:updateLink>http://localhost:4444/addons/test_update9_5.xpi</em:updateLink>
+              </Description>
+            </em:targetApplication>
+          </Description>
+        </li>
+      </Seq>
+    </em:updates>
+  </Description>
+
+  <Description about="urn:mozilla:extension:addon10@tests.mozilla.org">
+    <em:updates>
+      <Seq>
+        <li>
+          <Description>
+            <em:version>1.0</em:version>
+            <em:targetApplication>
+              <Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>0.1</em:minVersion>
+                <em:maxVersion>0.4</em:maxVersion>
+                <em:updateLink>http://localhost:4444/addons/test_update10.xpi</em:updateLink>
+              </Description>
+            </em:targetApplication>
+          </Description>
+        </li>
+      </Seq>
+    </em:updates>
+  </Description>
 </RDF>
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_update.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<searchresults total_results="11">
+  <addon>
+    <name>Test Addon 9</name>
+    <type id="1">Extension</type>
+    <guid>addon9@tests.mozilla.org</guid>
+  </addon>
+  <addon_compatibility hosted="true">
+    <guid>addon9@tests.mozilla.org</guid>
+    <name>Test Addon 9</name>
+    <version_ranges>
+      <version_range type="incompatible">
+        <min_version>4</min_version>
+        <max_version>4</max_version>
+        <compatible_applications>
+          <application>
+            <name>XPCShell</name>
+            <min_version>1</min_version>
+            <max_version>1</max_version>
+            <appID>xpcshell@tests.mozilla.org</appID>
+          </application>
+        </compatible_applications>
+      </version_range>
+    </version_ranges>
+  </addon_compatibility>
+</searchresults>
--- a/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecheck.rdf
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecheck.rdf
@@ -291,9 +291,107 @@
   </RDF:Description>
 
   <!-- There should be no information present for test_bug378216_14 -->
 
   <!-- Invalid update RDF -->
   <RDF:Description about="urn:mozilla:extension:test_bug378216_15@tests.mozilla.org">
     <em:updates>Foo</em:updates>
   </RDF:Description>
+
+  <!-- Various updates available - one is not compatible, but compatibility checking is disabled -->
+  <Description about="urn:mozilla:extension:ignore-compat@tests.mozilla.org">
+    <em:updates>
+      <Seq>
+        <li>
+          <Description>
+            <em:version>1.0</em:version>
+            <em:targetApplication>
+              <Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>0.1</em:minVersion>
+                <em:maxVersion>0.2</em:maxVersion>
+                <em:updateLink>https://localhost:4444/addons/test1.xpi</em:updateLink>
+              </Description>
+            </em:targetApplication>
+          </Description>
+        </li>
+        <li>
+          <Description>
+            <em:version>2.0</em:version>
+            <em:targetApplication>
+              <Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>0.5</em:minVersion>
+                <em:maxVersion>0.6</em:maxVersion>
+                <em:updateLink>https://localhost:4444/addons/test2.xpi</em:updateLink>
+              </Description>
+            </em:targetApplication>
+          </Description>
+        </li>
+        <!-- Update for future app versions - should never be compatible -->
+        <li>
+          <Description>
+            <em:version>3.0</em:version>
+            <em:targetApplication>
+              <Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>2</em:minVersion>
+                <em:maxVersion>3</em:maxVersion>
+                <em:updateLink>https://localhost:4444/addons/test3.xpi</em:updateLink>
+              </Description>
+            </em:targetApplication>
+          </Description>
+        </li>
+      </Seq>
+    </em:updates>
+  </Description>
+
+  <!-- Various updates available - one is not compatible, but compatibility checking is disabled -->
+  <Description about="urn:mozilla:extension:compat-override@tests.mozilla.org">
+    <em:updates>
+      <Seq>
+        <!-- Has compatibility override, but it doesn't match this app version -->
+        <li>
+          <Description>
+            <em:version>1.0</em:version>
+            <em:targetApplication>
+              <Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>0.1</em:minVersion>
+                <em:maxVersion>0.2</em:maxVersion>
+                <em:updateLink>https://localhost:4444/addons/test1.xpi</em:updateLink>
+              </Description>
+            </em:targetApplication>
+          </Description>
+        </li>
+        <!-- Has compatibility override, so is incompaible -->
+        <li>
+          <Description>
+            <em:version>2.0</em:version>
+            <em:targetApplication>
+              <Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>0.5</em:minVersion>
+                <em:maxVersion>0.6</em:maxVersion>
+                <em:updateLink>https://localhost:4444/addons/test2.xpi</em:updateLink>
+              </Description>
+            </em:targetApplication>
+          </Description>
+        </li>
+        <!-- Update for future app versions - should never be compatible -->
+        <li>
+          <Description>
+            <em:version>3.0</em:version>
+            <em:targetApplication>
+              <Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>2</em:minVersion>
+                <em:maxVersion>3</em:maxVersion>
+                <em:updateLink>https://localhost:4444/addons/test3.xpi</em:updateLink>
+              </Description>
+            </em:targetApplication>
+          </Description>
+        </li>
+      </Seq>
+    </em:updates>
+  </Description>
 </RDF>
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecompatmode_ignore.rdf
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+
+  <Description about="urn:mozilla:extension:compatmode-ignore@tests.mozilla.org">
+    <em:updates>
+      <Seq>
+        <li>
+          <Description>
+            <em:version>2.0</em:version>
+            <em:targetApplication>
+              <Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>1</em:minVersion>
+                <em:maxVersion>2</em:maxVersion>
+                <em:updateLink>https://localhost:4444/addons/test1.xpi</em:updateLink>
+              </Description>
+            </em:targetApplication>
+          </Description>
+        </li>
+      </Seq>
+    </em:updates>
+  </Description>
+</RDF>
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecompatmode_normal.rdf
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+
+  <Description about="urn:mozilla:extension:compatmode-normal@tests.mozilla.org">
+    <em:updates>
+      <Seq>
+        <li>
+          <Description>
+            <em:version>2.0</em:version>
+            <em:targetApplication>
+              <Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>1</em:minVersion>
+                <em:maxVersion>2</em:maxVersion>
+                <em:updateLink>https://localhost:4444/addons/test1.xpi</em:updateLink>
+              </Description>
+            </em:targetApplication>
+          </Description>
+        </li>
+      </Seq>
+    </em:updates>
+  </Description>
+</RDF>
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_updatecompatmode_strict.rdf
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+
+  <Description about="urn:mozilla:extension:compatmode-strict@tests.mozilla.org">
+    <em:updates>
+      <Seq>
+        <li>
+          <Description>
+            <em:version>2.0</em:version>
+            <em:targetApplication>
+              <Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>1</em:minVersion>
+                <em:maxVersion>2</em:maxVersion>
+                <em:updateLink>https://localhost:4444/addons/test1.xpi</em:updateLink>
+              </Description>
+            </em:targetApplication>
+          </Description>
+        </li>
+      </Seq>
+    </em:updates>
+  </Description>
+</RDF>
--- a/toolkit/mozapps/extensions/test/xpcshell/test_update.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_update.js
@@ -1,16 +1,18 @@
 /* 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";
+const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url";
+const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled";
 
 // The test extension uses an insecure update url.
 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);
 
@@ -766,19 +768,20 @@ function run_test_12() {
 
     a4.uninstall();
     restartManager();
 
     run_test_13();
   });
 }
 
-// Tests that no compatibility update is passed to the listener when there is
+// Tests that a 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.
+// version of the app that the caller requested an update check for, when
+// strict compatibility checking is disabled.
 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",
@@ -793,18 +796,18 @@ function run_test_13() {
     do_check_neq(a7, null);
     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");
+      onNoCompatibilityUpdateAvailable: function(addon) {
+        do_throw("Should 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);
@@ -1047,20 +1050,88 @@ function run_test_16() {
 
                 AddonManager.getAddonByID("addon2@tests.mozilla.org", function(a2) {
                   do_check_neq(a2.syncGUID, null);
                   do_check_eq(oldGUID, a2.syncGUID);
 
                   a2.uninstall();
                   restartManager();
 
-                  end_test();
+                  run_test_17();
                 });
               }
             });
             aInstall.install();
           }, "application/x-xpinstall");
         });
       }
     });
     aInstall.install();
   }, "application/x-xpinstall");
 }
+
+// Test that the update check correctly observes the
+// extensions.strictCompatibility pref and compatibility overrides.
+function run_test_17() {
+  writeInstallRDFForExtension({
+    id: "addon9@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_update.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "0.1",
+      maxVersion: "0.2"
+    }],
+    name: "Test Addon 9",
+  }, profileDir);
+  restartManager();
+
+  AddonManager.addInstallListener({
+    onNewInstall: function(aInstall) {
+      if (aInstall.existingAddon.id != "addon9@tests.mozilla.org")
+        do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id);
+      do_check_eq(aInstall.version, "3.0");
+    },
+    onDownloadFailed: function(aInstall) {
+      do_execute_soon(run_test_18);
+    }
+  });
+
+  Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, "http://localhost:4444/data/test_update.xml");
+  Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true);
+  // Fake a timer event
+  gInternalManager.notify(null);
+}
+
+// Tests that compatibility updates are applied to addons when the updated
+// compatibility data wouldn't match with strict compatibility enabled.
+function run_test_18() {
+  writeInstallRDFForExtension({
+    id: "addon10@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_update.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "0.1",
+      maxVersion: "0.2"
+    }],
+    name: "Test Addon 10",
+  }, profileDir);
+  restartManager();
+
+  AddonManager.getAddonByID("addon10@tests.mozilla.org", function(a10) {
+    do_check_neq(a10, null);
+
+    a10.findUpdates({
+      onNoCompatibilityUpdateAvailable: function() {
+        do_throw("Should have seen compatibility information");
+      },
+
+      onUpdateAvailable: function() {
+        do_throw("Should not have seen an available update");
+      },
+
+      onUpdateFinished: function() {
+        end_test();
+      }
+    }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
+  });
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_compatmode.js
@@ -0,0 +1,173 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// This verifies that add-on update check correctly fills in the
+// %COMPATIBILITY_MODE% token in the update URL.
+
+
+// The test extension uses an insecure update url.
+Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
+
+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");
+
+  // 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: "compatmode-normal@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_updatecompatmode_%COMPATIBILITY_MODE%.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon - normal"
+  }, profileDir);
+
+  writeInstallRDFForExtension({
+    id: "compatmode-strict@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_updatecompatmode_%COMPATIBILITY_MODE%.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon - strict"
+  }, profileDir);
+
+  writeInstallRDFForExtension({
+    id: "compatmode-strict-optin@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_updatecompatmode_%COMPATIBILITY_MODE%.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon - strict opt-in",
+    strictCompatibility: true
+  }, profileDir);
+
+  writeInstallRDFForExtension({
+    id: "compatmode-ignore@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_updatecompatmode_%COMPATIBILITY_MODE%.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon - ignore",
+  }, profileDir);
+
+  restartManager();
+  run_test_1();
+}
+
+// Strict compatibility checking disabled.
+function run_test_1() {
+  Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false);
+  AddonManager.getAddonByID("compatmode-normal@tests.mozilla.org", function(addon) {
+    do_check_neq(addon, null);
+    addon.findUpdates({
+      onCompatibilityUpdateAvailable: function() {
+        do_throw("Should have not have seen compatibility information");
+      },
+
+      onNoUpdateAvailable: function() {
+        do_throw("Should have seen an available update");
+      },
+
+      onUpdateAvailable: function(addon, install) {
+        do_check_eq(install.version, "2.0")
+      },
+
+      onUpdateFinished: function() {
+        run_test_2();
+      }
+    }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
+  });
+}
+
+// Strict compatibility checking enabled.
+function run_test_2() {
+  Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, true);
+  AddonManager.getAddonByID("compatmode-strict@tests.mozilla.org", function(addon) {
+    do_check_neq(addon, null);
+    addon.findUpdates({
+      onCompatibilityUpdateAvailable: function() {
+        do_throw("Should have not have seen compatibility information");
+      },
+
+      onNoUpdateAvailable: function() {
+        do_throw("Should have seen an available update");
+      },
+
+      onUpdateAvailable: function(addon, install) {
+        do_check_eq(install.version, "2.0")
+      },
+
+      onUpdateFinished: function() {
+        run_test_3();
+      }
+    }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
+  });
+}
+
+// Strict compatibility checking opt-in.
+function run_test_3() {
+  Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, false);
+  AddonManager.getAddonByID("compatmode-strict-optin@tests.mozilla.org", function(addon) {
+    do_check_neq(addon, null);
+    addon.findUpdates({
+      onCompatibilityUpdateAvailable: function() {
+        do_throw("Should have not have seen compatibility information");
+      },
+
+      onUpdateAvailable: function(addon, install) {
+        do_throw("Should not have seen an available update");
+      },
+
+      onUpdateFinished: function() {
+        run_test_4();
+      }
+    }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
+  });
+}
+
+// Compatibility checking disabled.
+function run_test_4() {
+  Services.prefs.setBoolPref(COMPATIBILITY_PREF, false);
+  AddonManager.getAddonByID("compatmode-ignore@tests.mozilla.org", function(addon) {
+    do_check_neq(addon, null);
+    addon.findUpdates({
+      onCompatibilityUpdateAvailable: function() {
+        do_throw("Should have not have seen compatibility information");
+      },
+
+      onNoUpdateAvailable: function() {
+        do_throw("Should have seen an available update");
+      },
+
+      onUpdateAvailable: function(addon, install) {
+        do_check_eq(install.version, "2.0")
+      },
+
+      onUpdateFinished: function() {
+        end_test();
+      }
+    }, AddonManager.UPDATE_WHEN_USER_REQUESTED);
+  });
+}
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_ignorecompat.js
@@ -0,0 +1,65 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// This verifies that add-on update checks work correctly when compatibility
+// check is disabled.
+
+
+const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url";
+const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled";
+
+// The test extension uses an insecure update url.
+Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
+
+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");
+
+  // 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);
+
+  run_test_1();
+}
+
+// Test that the update check correctly observes the
+// extensions.strictCompatibility pref and compatibility overrides.
+function run_test_1() {
+  writeInstallRDFForExtension({
+    id: "addon9@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_update.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "0.1",
+      maxVersion: "0.2"
+    }],
+    name: "Test Addon 9",
+  }, profileDir);
+  restartManager();
+
+  AddonManager.addInstallListener({
+    onNewInstall: function(aInstall) {
+      if (aInstall.existingAddon.id != "addon9@tests.mozilla.org")
+        do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id);
+      do_check_eq(aInstall.version, "4.0");
+    },
+    onDownloadFailed: function(aInstall) {
+      end_test();
+    }
+  });
+
+  Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, "http://localhost:4444/data/test_update.xml");
+  Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true);
+  // Fake a timer event
+  gInternalManager.notify(null);
+}
+
--- a/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_update_strictcompat.js
@@ -1,16 +1,18 @@
 /* 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";
+const PREF_GETADDONS_BYIDS = "extensions.getAddons.get.url";
+const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled";
 
 // 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");
@@ -1011,11 +1013,45 @@ function check_test_15(aInstall) {
     do_check_neq(a1, null);
     do_check_eq(a1.version, "2.0");
     a1.uninstall();
 
     do_check_eq(a8, null);
 
     restartManager();
 
-    end_test();
+    run_test_16();
   });
 }
+
+// Test that the update check correctly observes the
+// extensions.strictCompatibility pref and compatibility overrides.
+function run_test_16() {
+  writeInstallRDFForExtension({
+    id: "addon9@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_update.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "0.1",
+      maxVersion: "0.2"
+    }],
+    name: "Test Addon 9",
+  }, profileDir);
+  restartManager();
+
+  AddonManager.addInstallListener({
+    onNewInstall: function(aInstall) {
+      if (aInstall.existingAddon.id != "addon9@tests.mozilla.org")
+        do_throw("Saw unexpected onNewInstall for " + aInstall.existingAddon.id);
+      do_check_eq(aInstall.version, "2.0");
+    },
+    onDownloadFailed: function(aInstall) {
+      end_test();
+    }
+  });
+
+  Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, "http://localhost:4444/data/test_update.xml");
+  Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true);
+  // Fake a timer event
+  gInternalManager.notify(null);
+}
+
--- a/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js
@@ -1,16 +1,28 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 // This verifies that AddonUpdateChecker works correctly
 
 Components.utils.import("resource://gre/modules/AddonUpdateChecker.jsm");
 
+
+var channel = "default";
+try {
+  channel = Services.prefs.getCharPref("app.update.channel");
+} catch (e) { }
+if (channel != "aurora" && channel != "beta" && channel != "release")
+  var version = "nightly";
+else
+  version = Services.appinfo.version.replace(/^([^\.]+\.[0-9]+[a-z]*).*/gi, "$1");
+const COMPATIBILITY_PREF = "extensions.checkCompatibility." + version;
+
+
 do_load_httpd_js();
 var testserver;
 
 function run_test() {
   createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
 
   // Create and configure the HTTP server.
   testserver = new nsHttpServer();
@@ -221,12 +233,70 @@ function run_test_11() {
                                      "extension", null,
                                      "http://localhost:4444/data/test_updatecheck.rdf", {
     onUpdateCheckComplete: function(updates) {
       do_throw("Update check should have failed");
     },
 
     onUpdateCheckError: function(status) {
       do_check_eq(status, AddonUpdateChecker.ERROR_PARSE_ERROR);
-      end_test();
+      run_test_12();
+    }
+  });
+}
+
+function run_test_12() {
+  AddonUpdateChecker.checkForUpdates("ignore-compat@tests.mozilla.org",
+                                     "extension", null,
+                                     "http://localhost:4444/data/test_updatecheck.rdf", {
+    onUpdateCheckComplete: function(updates) {
+      do_check_eq(updates.length, 3);
+      let update = AddonUpdateChecker.getNewestCompatibleUpdate(updates,
+                                                                null,
+                                                                null,
+                                                                true);
+      do_check_neq(update, null);
+      do_check_eq(update.version, 2);
+      run_test_13();
+    },
+
+    onUpdateCheckError: function(status) {
+      do_throw("Update check failed with status " + status);
     }
   });
 }
+
+function run_test_13() {
+  AddonUpdateChecker.checkForUpdates("compat-override@tests.mozilla.org",
+                                     "extension", null,
+                                     "http://localhost:4444/data/test_updatecheck.rdf", {
+    onUpdateCheckComplete: function(updates) {
+      do_check_eq(updates.length, 3);
+      let overrides = [{
+        type: "incompatible",
+        minVersion: 1,
+        maxVersion: 2,
+        appID: "xpcshell@tests.mozilla.org",
+        appMinVersion: 0.1,
+        appMaxVersion: 0.2
+      }, {
+        type: "incompatible",
+        minVersion: 2,
+        maxVersion: 2,
+        appID: "xpcshell@tests.mozilla.org",
+        appMinVersion: 1,
+        appMaxVersion: 2
+      }];
+      let update = AddonUpdateChecker.getNewestCompatibleUpdate(updates,
+                                                                null,
+                                                                null,
+                                                                true,
+                                                                overrides);
+      do_check_neq(update, null);
+      do_check_eq(update.version, 1);
+      end_test();
+    },
+
+    onUpdateCheckError: function(status) {
+      do_throw("Update check failed with status " + status);
+    }
+  });
+}
--- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
+++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
@@ -194,20 +194,24 @@ 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_update_ignorecompat.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_update_compatmode.js]
 [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"