Bug 741670 - Don't sync hotfix extensions; r=rnewman, Unfocused
authorGregory Szorc <gps@mozilla.com>
Tue, 03 Apr 2012 08:55:58 -0700
changeset 94230 c62d71bac750b9e6956029a744e0359d45683327
parent 94229 9f5925b56c85d43abe2b6a9e1dc4f9cf67d38733
child 94231 40406a497a3f74880cb8b6d28d0b90923a2c609e
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrnewman, Unfocused
bugs741670
milestone14.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 741670 - Don't sync hotfix extensions; r=rnewman, Unfocused
services/sync/modules/engines/addons.js
services/sync/tests/unit/test_addons_store.js
--- a/services/sync/modules/engines/addons.js
+++ b/services/sync/modules/engines/addons.js
@@ -270,16 +270,18 @@ function AddonsStore(name) {
   Store.call(this, name);
 }
 AddonsStore.prototype = {
   __proto__: Store.prototype,
 
   // Define the add-on types (.type) that we support.
   _syncableTypes: ["extension", "theme"],
 
+  _extensionsPrefs: new Preferences("extensions."),
+
   get reconciler() {
     return this.engine._reconciler;
   },
 
   get engine() {
     // Ideally we'd link to a specific object, but the API doesn't provide an
     // easy way to faciliate this. When the async API lands, this hackiness can
     // go away.
@@ -534,17 +536,18 @@ AddonsStore.prototype = {
    * @return Boolean indicating whether it is appropriate for Sync
    */
   isAddonSyncable: function isAddonSyncable(addon) {
     // Currently, we limit syncable add-ons to those that are:
     //   1) In a well-defined set of types
     //   2) Installed in the current profile
     //   3) Not installed by a foreign entity (i.e. installed by the app)
     //      since they act like global extensions.
-    //   4) Are installed from AMO
+    //   4) Is not a hotfix.
+    //   5) Are installed from AMO
 
     // We could represent the test as a complex boolean expression. We go the
     // verbose route so the failure reason is logged.
     if (!addon) {
       this._log.debug("Null object passed to isAddonSyncable.");
       return false;
     }
 
@@ -563,16 +566,22 @@ AddonsStore.prototype = {
     // manually placed in the profile directory, foreignInstall will be set.
     // Arguably, that add-on should be syncable.
     // TODO Address the edge case and come up with more robust heuristics.
     if (addon.foreignInstall) {
       this._log.debug(addon.id + " not syncable: is foreign install.");
       return false;
     }
 
+    // Ignore hotfix extensions (bug 741670). The pref may not be defined.
+    if (this._extensionsPrefs.get("hotfix.id", null) == addon.id) {
+      this._log.debug(addon.id + " not syncable: is a hotfix.");
+      return false;
+    }
+
     // We provide a back door to skip the repository checking of an add-on.
     // This is utilized by the tests to make testing easier. Users could enable
     // this, but it would sacrifice security.
     if (Svc.Prefs.get("addons.ignoreRepositoryChecking", false)) {
       return true;
     }
 
     let cb = Async.makeSyncCallback();
--- a/services/sync/tests/unit/test_addons_store.js
+++ b/services/sync/tests/unit/test_addons_store.js
@@ -362,16 +362,58 @@ add_test(function test_addon_syncability
   Svc.Prefs.set("addons.trustedSourceHostnames", "addons.mozilla.org");
   do_check_true(store.isSourceURITrusted(createURI("https://addons.mozilla.org/foo")));
 
   Svc.Prefs.reset("addons.trustedSourceHostnames");
 
   run_next_test();
 });
 
+add_test(function test_ignore_hotfixes() {
+  _("Ensure that hotfix extensions are ignored.");
+
+  Svc.Prefs.set("addons.ignoreRepositoryChecking", true);
+
+  // A hotfix extension is one that has the id the same as the
+  // extensions.hotfix.id pref.
+  let prefs = new Preferences("extensions.");
+
+  let addon = installAddon("test_bootstrap1_1");
+  do_check_true(store.isAddonSyncable(addon));
+
+  let dummy = {};
+  const KEYS = ["id", "syncGUID", "type", "scope", "foreignInstall"];
+  for each (let k in KEYS) {
+    dummy[k] = addon[k];
+  }
+
+  // Basic sanity check.
+  do_check_true(store.isAddonSyncable(dummy));
+
+  prefs.set("hotfix.id", dummy.id);
+  do_check_false(store.isAddonSyncable(dummy));
+
+  // Verify that int values don't throw off checking.
+  let prefSvc = Cc["@mozilla.org/preferences-service;1"]
+                .getService(Ci.nsIPrefService)
+                .getBranch("extensions.");
+  // Need to delete pref before changing type.
+  prefSvc.deleteBranch("hotfix.id");
+  prefSvc.setIntPref("hotfix.id", 0xdeadbeef);
+
+  do_check_true(store.isAddonSyncable(dummy));
+
+  uninstallAddon(addon);
+
+  Svc.Prefs.reset("addons.ignoreRepositoryChecking");
+  prefs.reset("hotfix.id");
+
+  run_next_test();
+});
+
 add_test(function test_ignore_untrusted_source_uris() {
   _("Ensures that source URIs from insecure schemes are rejected.");
 
   Svc.Prefs.set("addons.ignoreRepositoryChecking", false);
 
   let ioService = Cc["@mozilla.org/network/io-service;1"]
                   .getService(Ci.nsIIOService);