Backed out changeset 4834a3833639 and c580afddd1cb (bug 985084 and bug 97500)
authorGregory Szorc <gps@mozilla.com>
Fri, 28 Mar 2014 21:45:10 -0700
changeset 176093 dca962be64873ec08c57b9a42bcb84158bbbfc5b
parent 176092 4834a3833639d944045a7e1409fbe93410e29544
child 176094 3951f7e82b4ca65b88016620ee6ebbd3fc5da6d7
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
bugs985084, 97500
milestone31.0a1
backs out4834a3833639d944045a7e1409fbe93410e29544
Backed out changeset 4834a3833639 and c580afddd1cb (bug 985084 and bug 97500)
browser/experiments/Experiments.jsm
toolkit/mozapps/extensions/AddonManager.jsm
toolkit/mozapps/extensions/LightweightThemeManager.jsm
toolkit/mozapps/extensions/internal/XPIProvider.jsm
toolkit/mozapps/extensions/test/addons/test_experiment1/install.rdf
toolkit/mozapps/extensions/test/browser/browser_experiments.js
toolkit/mozapps/extensions/test/xpcshell/test_experiment.js
toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js
toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini
--- a/browser/experiments/Experiments.jsm
+++ b/browser/experiments/Experiments.jsm
@@ -606,18 +606,16 @@ Experiments.Experiments.prototype = {
   },
 
   notify: function (timer) {
     gLogger.trace("Experiments::notify()");
     this._checkForShutdown();
     return this._run();
   },
 
-  // START OF ADD-ON LISTENERS
-
   onDisabled: function (addon) {
     gLogger.trace("Experiments::onDisabled() - addon id: " + addon.id);
     if (addon.id == this._pendingUninstall) {
       return;
     }
     let activeExperiment = this._getActiveExperiment();
     if (!activeExperiment || activeExperiment._addonId != addon.id) {
       return;
@@ -633,18 +631,16 @@ Experiments.Experiments.prototype = {
     }
     let activeExperiment = this._getActiveExperiment();
     if (!activeExperiment || activeExperiment._addonId != addon.id) {
       return;
     }
     this.disableExperiment();
   },
 
-  // END OF ADD-ON LISTENERS.
-
   _getExperimentByAddonId: function (addonId) {
     for (let [, entry] of this._experiments) {
       if (entry._addonId === addonId) {
         return entry;
       }
     }
 
     return null;
@@ -1375,70 +1371,66 @@ Experiments.ExperimentEntry.prototype = 
       this._failedStart = true;
 
       TelemetryLog.log(TELEMETRY_LOG.ACTIVATION_KEY,
                       [TELEMETRY_LOG.ACTIVATION.INSTALL_FAILURE, this.id]);
 
       deferred.reject(new Error(message));
     };
 
-    let entry = this;
     let listener = {
-      onDownloadEnded: function (install) {
+      onDownloadEnded: install => {
         gLogger.trace("ExperimentEntry::_installAddon() - onDownloadEnded for " + this.id);
 
         if (install.existingAddon) {
           gLogger.warn("ExperimentEntry::_installAddon() - onDownloadEnded, addon already installed");
         }
 
         if (install.addon.type !== "experiment") {
           gLogger.error("ExperimentEntry::_installAddon() - onDownloadEnded, wrong addon type");
           install.cancel();
         }
-      }.bind(entry),
+      },
 
-      onInstallStarted: function (install) {
+      onInstallStarted: install => {
         gLogger.trace("ExperimentEntry::_installAddon() - onInstallStarted for " + this.id);
 
         if (install.existingAddon) {
           gLogger.warn("ExperimentEntry::_installAddon() - onInstallStarted, addon already installed");
         }
 
         if (install.addon.type !== "experiment") {
           gLogger.error("ExperimentEntry::_installAddon() - onInstallStarted, wrong addon type");
           return false;
         }
+      },
 
-        // Experiment add-ons default to userDisabled = true.
-        install.addon.userDisabled = false;
-      }.bind(entry),
-
-      onInstallEnded: function (install) {
+      onInstallEnded: install => {
         gLogger.trace("ExperimentEntry::_installAddon() - install ended for " + this.id);
         this._lastChangedDate = this._policy.now();
         this._startDate = this._policy.now();
         this._enabled = true;
 
         TelemetryLog.log(TELEMETRY_LOG.ACTIVATION_KEY,
                        [TELEMETRY_LOG.ACTIVATION.ACTIVATED, this.id]);
 
         let addon = install.addon;
         this._name = addon.name;
         this._addonId = addon.id;
         this._description = addon.description || "";
         this._homepageURL = addon.homepageURL || "";
 
         deferred.resolve();
-      }.bind(entry),
+      },
+    };
 
-      onDownloadCancelled: failureHandler.bind(entry),
-      onDownloadFailed: failureHandler.bind(entry),
-      onInstallCancelled: failureHandler.bind(entry),
-      onInstallFailed: failureHandler.bind(entry),
-    };
+    ["onDownloadCancelled", "onDownloadFailed", "onInstallCancelled", "onInstallFailed"]
+      .forEach(what => {
+        listener[what] = install => failureHandler(install, what)
+      });
 
     install.addListener(listener);
     install.install();
 
     return deferred.promise;
   },
 
   /*
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -2312,35 +2312,17 @@ this.AddonManagerPrivate = {
 
   // Start a timer, record a simple measure of the time interval when
   // timer.done() is called
   simpleTimer: function(aName) {
     let startTime = Date.now();
     return {
       done: () => this.recordSimpleMeasure(aName, Date.now() - startTime)
     };
-  },
-
-  /**
-   * Helper to call update listeners when no update is available.
-   *
-   * This can be used as an implementation for Addon.findUpdates() when
-   * no update mechanism is available.
-   */
-  callNoUpdateListeners: function (addon, listener, reason, appVersion, platformVersion) {
-    if ("onNoCompatibilityUpdateAvailable" in listener) {
-      safeCall(listener.onNoCompatibilityUpdateAvailable, addon);
-    }
-    if ("onNoUpdateAvailable" in listener) {
-      safeCall(listener.onNoUpdateAvailable, addon);
-    }
-    if ("onUpdateFinished" in listener) {
-      safeCall(listener.onUpdateFinished, addon);
-    }
-  },
+  }
 };
 
 /**
  * This is the public API that UI and developers should be calling. All methods
  * just forward to AddonManagerInternal.
  */
 this.AddonManager = {
   // Constants for the AddonInstall.state property
--- a/toolkit/mozapps/extensions/LightweightThemeManager.jsm
+++ b/toolkit/mozapps/extensions/LightweightThemeManager.jsm
@@ -503,17 +503,22 @@ function AddonWrapper(aTheme) {
     LightweightThemeManager.forgetUsedTheme(aTheme.id);
   };
 
   this.cancelUninstall = function AddonWrapper_cancelUninstall() {
     throw new Error("Theme is not marked to be uninstalled");
   };
 
   this.findUpdates = function AddonWrapper_findUpdates(listener, reason, appVersion, platformVersion) {
-    AddonManagerPrivate.callNoUpdateListeners(this, listener, reason, appVersion, platformVersion);
+    if ("onNoCompatibilityUpdateAvailable" in listener)
+      listener.onNoCompatibilityUpdateAvailable(this);
+    if ("onNoUpdateAvailable" in listener)
+      listener.onNoUpdateAvailable(this);
+    if ("onUpdateFinished" in listener)
+      listener.onUpdateFinished(this);
   };
 }
 
 AddonWrapper.prototype = {
   // Lightweight themes are never disabled by the application
   get appDisabled() {
     return false;
   },
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -903,39 +903,23 @@ function loadManifestFromRDF(aUri, aStre
 
   // A theme's userDisabled value is true if the theme is not the selected skin
   // or if there is an active lightweight theme. We ignore whether softblocking
   // is in effect since it would change the active theme.
   if (addon.type == "theme") {
     addon.userDisabled = !!LightweightThemeManager.currentTheme ||
                          addon.internalName != XPIProvider.selectedSkin;
   }
-  // Experiments are disabled by default. It is up to the Experiments Manager
-  // to enable them (it drives installation).
-  else if (addon.type == "experiment") {
-    addon.userDisabled = true;
-  }
   else {
     addon.userDisabled = false;
     addon.softDisabled = addon.blocklistState == Ci.nsIBlocklistService.STATE_SOFTBLOCKED;
   }
 
   addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DEFAULT;
 
-  // Experiments are managed and updated through an external "experiments
-  // manager." So disable some built-in mechanisms.
-  if (addon.type == "experiment") {
-    addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_DISABLE;
-    addon.updateURL = null;
-    addon.updateKey = null;
-
-    addon.targetApplications = [];
-    addon.targetPlatforms = [];
-  }
-
   // Load the storage service before NSS (nsIRandomGenerator),
   // to avoid a SQLite initialization error (bug 717904).
   let storage = Services.storage;
 
   // Generate random GUID used for Sync.
   // This was lifted from util.js:makeGUID() from services-sync.
   let rng = Cc["@mozilla.org/security/random-generator;1"].
             createInstance(Ci.nsIRandomGenerator);
@@ -2082,29 +2066,18 @@ var XPIProvider = {
     Services.prefs.setBoolPref(PREF_PENDING_OPERATIONS,
                                !XPIDatabase.writeAddonsList());
   },
 
   /**
    * Persists changes to XPIProvider.bootstrappedAddons to its store (a pref).
    */
   persistBootstrappedAddons: function XPI_persistBootstrappedAddons() {
-    // Experiments are disabled upon app load, so don't persist references.
-    let filtered = {};
-    for (let id in this.bootstrappedAddons) {
-      let entry = this.bootstrappedAddons[id];
-      if (entry.type == "experiment") {
-        continue;
-      }
-
-      filtered[id] = entry;
-    }
-
     Services.prefs.setCharPref(PREF_BOOTSTRAP_ADDONS,
-                               JSON.stringify(filtered));
+                               JSON.stringify(this.bootstrappedAddons));
   },
 
   /**
    * Adds a list of currently active add-ons to the next crash report.
    */
   addAddonsToCrashReporter: function XPI_addAddonsToCrashReporter() {
     if (!("nsICrashReporter" in Ci) ||
         !(Services.appinfo instanceof Ci.nsICrashReporter))
@@ -4249,26 +4222,22 @@ var XPIProvider = {
 
     let wasDisabled = isAddonDisabled(aAddon);
     let isDisabled = aUserDisabled || aSoftDisabled || appDisabled;
 
     // If appDisabled changes but the result of isAddonDisabled() doesn't,
     // no onDisabling/onEnabling is sent - so send a onPropertyChanged.
     let appDisabledChanged = aAddon.appDisabled != appDisabled;
 
-    // Update the properties in the database.
-    // We never persist this for experiments because the disabled flags
-    // are controlled by the Experiments Manager.
-    if (aAddon.type != "experiment") {
-      XPIDatabase.setAddonProperties(aAddon, {
-        userDisabled: aUserDisabled,
-        appDisabled: appDisabled,
-        softDisabled: aSoftDisabled
-      });
-    }
+    // Update the properties in the database
+    XPIDatabase.setAddonProperties(aAddon, {
+      userDisabled: aUserDisabled,
+      appDisabled: appDisabled,
+      softDisabled: aSoftDisabled
+    });
 
     if (appDisabledChanged) {
       AddonManagerPrivate.callAddonListeners("onPropertyChanged",
                                             aAddon,
                                             ["appDisabled"]);
     }
 
     // If the add-on is not visible or the add-on is not changing state then
@@ -6040,27 +6009,16 @@ AddonInternal.prototype = {
         }
       }
     }
 
     return matchedOS && !needsABI;
   },
 
   isCompatibleWith: function AddonInternal_isCompatibleWith(aAppVersion, aPlatformVersion) {
-    // Experiments are installed through an external mechanism that
-    // limits target audience to compatible clients. We trust it knows what
-    // it's doing and skip compatibility checks.
-    //
-    // This decision does forfeit defense in depth. If the experiments system
-    // is ever wrong about targeting an add-on to a specific application
-    // or platform, the client will likely see errors.
-    if (this.type == "experiment") {
-      return true;
-    }
-
     let app = this.matchingTargetApplication;
     if (!app)
       return false;
 
     if (!aAppVersion)
       aAppVersion = Services.appinfo.version;
     if (!aPlatformVersion)
       aPlatformVersion = Services.appinfo.platformVersion;
@@ -6435,21 +6393,16 @@ function AddonWrapper(aAddon) {
 
     return null;
   });
 
   this.__defineGetter__("applyBackgroundUpdates", function AddonWrapper_applyBackgroundUpdatesGetter() {
     return aAddon.applyBackgroundUpdates;
   });
   this.__defineSetter__("applyBackgroundUpdates", function AddonWrapper_applyBackgroundUpdatesSetter(val) {
-    if (this.type == "experiment") {
-      logger.warn("Setting applyBackgroundUpdates on an experiment is not supported.");
-      return;
-    }
-
     if (val != AddonManager.AUTOUPDATE_DEFAULT &&
         val != AddonManager.AUTOUPDATE_DISABLE &&
         val != AddonManager.AUTOUPDATE_ENABLE) {
       val = val ? AddonManager.AUTOUPDATE_DEFAULT :
                   AddonManager.AUTOUPDATE_DISABLE;
     }
 
     if (val == aAddon.applyBackgroundUpdates)
@@ -6540,43 +6493,32 @@ function AddonWrapper(aAddon) {
 
   this.__defineGetter__("permissions", function AddonWrapper_permisionsGetter() {
     let permissions = 0;
 
     // Add-ons that aren't installed cannot be modified in any way
     if (!(aAddon.inDatabase))
       return permissions;
 
-    // Experiments can only be uninstalled. An uninstall reflects the user
-    // intent of "disable this experiment." This is partially managed by the
-    // experiments manager.
-    if (aAddon.type == "experiment") {
-      return AddonManager.PERM_CAN_UNINSTALL;
-    }
-
     if (!aAddon.appDisabled) {
-      if (this.userDisabled) {
+      if (this.userDisabled)
         permissions |= AddonManager.PERM_CAN_ENABLE;
-      }
-      else if (aAddon.type != "theme") {
+      else if (aAddon.type != "theme")
         permissions |= AddonManager.PERM_CAN_DISABLE;
-      }
     }
 
     // Add-ons that are in locked install locations, or are pending uninstall
     // cannot be upgraded or uninstalled
     if (!aAddon._installLocation.locked && !aAddon.pendingUninstall) {
       // Add-ons that are installed by a file link cannot be upgraded
-      if (!aAddon._installLocation.isLinkedAddon(aAddon.id)) {
+      if (!aAddon._installLocation.isLinkedAddon(aAddon.id))
         permissions |= AddonManager.PERM_CAN_UPGRADE;
-      }
 
       permissions |= AddonManager.PERM_CAN_UNINSTALL;
     }
-
     return permissions;
   });
 
   this.__defineGetter__("isActive", function AddonWrapper_isActiveGetter() {
     if (Services.appinfo.inSafeMode)
       return false;
     return aAddon.active;
   });
@@ -6648,24 +6590,16 @@ function AddonWrapper(aAddon) {
     if (!(aAddon.inDatabase))
       throw new Error("Cannot cancel uninstall for an add-on that isn't installed");
     if (!aAddon.pendingUninstall)
       throw new Error("Add-on is not marked to be uninstalled");
     XPIProvider.cancelUninstallAddon(aAddon);
   };
 
   this.findUpdates = function AddonWrapper_findUpdates(aListener, aReason, aAppVersion, aPlatformVersion) {
-    // Short-circuit updates for experiments because updates are handled
-    // through the Experiments Manager.
-    if (this.type == "experiment") {
-      AddonManagerPrivate.callNoUpdateListeners(this, aListener, aReason,
-                                                aAppVersion, aPlatformVersion);
-      return;
-    }
-
     new UpdateChecker(aAddon, aListener, aReason, aAppVersion, aPlatformVersion);
   };
 
   // Returns true if there was an update in progress, false if there was no update to cancel
   this.cancelUpdate = function AddonWrapper_cancelUpdate() {
     if (aAddon._updateCheck) {
       aAddon._updateCheck.cancel();
       return true;
deleted file mode 100644
--- a/toolkit/mozapps/extensions/test/addons/test_experiment1/install.rdf
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0"?>
-
-<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-     xmlns:em="http://www.mozilla.org/2004/em-rdf#">
-
-  <Description about="urn:mozilla:install-manifest">
-    <em:id>experiment1@tests.mozilla.org</em:id>
-    <em:version>1.0</em:version>
-    <em:type>128</em:type>
-    <em:bootstrap>true</em:bootstrap>
-
-    <!-- Front End MetaData -->
-    <em:name>Test Experiment 1</em:name>
-    <em:description>Test Description</em:description>
-
-  </Description>
-</RDF>
--- a/toolkit/mozapps/extensions/test/browser/browser_experiments.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_experiments.js
@@ -45,17 +45,18 @@ add_test(function testExperimentInfoNotV
 });
 
 // If we have an active experiment, we should see the experiments tab
 // and that tab should have some messages.
 add_test(function testActiveExperiment() {
   install_addon("addons/browser_experiment1.xpi", (addon) => {
     gInstalledAddons.push(addon);
 
-    Assert.ok(addon.userDisabled, "Add-on is disabled upon initial install.");
+    // This may change if we remove compatibility checking from experiments.
+    // Putting this check here so a test fails if preconditions change.
     Assert.equal(addon.isActive, false, "Add-on is not active.");
 
     Assert.ok(gCategoryUtilities.isTypeVisible("experiment"), "Experiment tab visible.");
 
     gCategoryUtilities.openType("experiment", (win) => {
       let el = gManagerWindow.document.getElementsByClassName("experiment-info-container")[0];
       is_element_visible(el, "Experiment info is visible on experiment tab.");
 
@@ -127,27 +128,8 @@ add_test(function testOpenPreferences() 
 
       run_next_test();
     }, "advanced-pane-loaded", false);
 
     info("Loading preferences pane.");
     EventUtils.synthesizeMouseAtCenter(btn, {}, gManagerWindow);
   });
 });
-
-add_test(function testButtonPresence() {
-  gCategoryUtilities.openType("experiment", (win) => {
-    let item = get_addon_element(gManagerWindow, "test-experiment1@experiments.mozilla.org");
-    Assert.ok(item, "Got add-on element.");
-
-    let el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "remove-btn");
-    // Corresponds to the uninstall permission.
-    is_element_visible(el, "Remove button is visible.");
-    // Corresponds to lack of disable permission.
-    el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "disable-btn");
-    is_element_hidden(el, "Disable button not visible.");
-    // Corresponds to lack of enable permission.
-    el = item.ownerDocument.getAnonymousElementByAttribute(item, "anonid", "enable-btn");
-    is_element_hidden(el, "Enable button not visible.");
-
-    run_next_test();
-  });
-});
deleted file mode 100644
--- a/toolkit/mozapps/extensions/test/xpcshell/test_experiment.js
+++ /dev/null
@@ -1,89 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-let scope = Components.utils.import("resource://gre/modules/addons/XPIProvider.jsm");
-const XPIProvider = scope.XPIProvider;
-
-function run_test() {
-  createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
-  startupManager();
-
-  run_next_test();
-}
-
-add_test(function test_experiment() {
-  AddonManager.getInstallForFile(do_get_addon("test_experiment1"), (install) => {
-    completeAllInstalls([install], () => {
-      AddonManager.getAddonByID("experiment1@tests.mozilla.org", (addon) => {
-        Assert.ok(addon, "Addon is found.");
-
-        Assert.ok(addon.userDisabled, "Experiments are userDisabled by default.");
-        Assert.equal(addon.isActive, false, "Add-on is not active.");
-        Assert.equal(addon.updateURL, null, "No updateURL for experiments.");
-        Assert.equal(addon.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE,
-                     "Background updates are disabled.");
-        Assert.equal(addon.permissions, AddonManager.PERM_CAN_UNINSTALL,
-                     "Permissions are minimal.");
-
-        // Setting applyBackgroundUpdates should not work.
-        addon.applyBackgroundUpdates = AddonManager.AUTOUPDATE_ENABLE;
-        Assert.equal(addon.applyBackgroundUpdates, AddonManager.AUTOUPDATE_DISABLE,
-                     "Setting applyBackgroundUpdates shouldn't do anything.");
-
-        let noCompatibleCalled = false;
-        let noUpdateCalled = false;
-        let finishedCalled = false;
-
-        let listener = {
-          onNoCompatibilityUpdateAvailable: () => { noCompatibleCalled = true; },
-          onNoUpdateAvailable: () => { noUpdateCalled = true; },
-          onUpdateFinished: () => { finishedCalled = true; },
-        };
-
-        addon.findUpdates(listener, "testing", null, null);
-        Assert.ok(noCompatibleCalled, "Listener called.");
-        Assert.ok(noUpdateCalled, "Listener called.");
-        Assert.ok(finishedCalled, "Listener called.");
-
-        run_next_test();
-      });
-    });
-  });
-});
-
-// Changes to userDisabled should not be persisted to the database.
-add_test(function test_userDisabledNotPersisted() {
-  AddonManager.getAddonByID("experiment1@tests.mozilla.org", (addon) => {
-    Assert.ok(addon, "Addon is found.");
-
-    let listener = {
-      onEnabled: (addon2) => {
-        Assert.equal(addon2.id, addon.id, "Changed add-on matches expected.");
-        Assert.ok(addon2.isActive, "Add-on is no longer disabled.");
-
-        Assert.ok("experiment1@tests.mozilla.org" in XPIProvider.bootstrappedAddons,
-                  "Experiment add-on listed in XPIProvider bootstrapped list.");
-
-        AddonManager.getAddonByID("experiment1@tests.mozilla.org", (addon) => {
-          Assert.ok(addon, "Add-on retrieved.");
-          Assert.ok(addon.userDisabled, "Add-on is disabled according to database.");
-
-          restartManager();
-          let persisted = JSON.parse(Services.prefs.getCharPref("extensions.bootstrappedAddons"));
-          Assert.ok(!("experiment1@tests.mozilla.org" in persisted),
-                    "Experiment add-on not persisted to bootstrappedAddons.");
-
-          AddonManager.getAddonByID("experiment1@tests.mozilla.org", (addon) => {
-            Assert.ok(addon, "Add-on retrieved.");
-            Assert.ok(addon.userDisabled, "Add-on is disabled after restart.");
-
-            run_next_test();
-          });
-        });
-      },
-    };
-
-    AddonManager.addAddonListener(listener);
-    addon.userDisabled = false;
-  });
-});
--- a/toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js
@@ -12,18 +12,17 @@ const IGNORE = ["escapeAddonURI", "shoul
                 "mapURIToAddonID"];
 
 const IGNORE_PRIVATE = ["AddonAuthor", "AddonCompatibilityOverride",
                         "AddonScreenshot", "AddonType", "startup", "shutdown",
                         "registerProvider", "unregisterProvider",
                         "addStartupChange", "removeStartupChange",
                         "recordTimestamp", "recordSimpleMeasure",
                         "recordException", "getSimpleMeasures", "simpleTimer",
-                        "setTelemetryDetails", "getTelemetryDetails",
-                        "callNoUpdateListeners"];
+                        "setTelemetryDetails", "getTelemetryDetails"];
 
 function test_functions() {
   for (let prop in AddonManager) {
     if (typeof AddonManager[prop] != "function")
       continue;
     if (IGNORE.indexOf(prop) != -1)
       continue;
 
--- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini
+++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini
@@ -158,17 +158,16 @@ fail-if = os == "android"
 [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
 skip-if = os == "android"
 [test_error.js]
-[test_experiment.js]
 [test_filepointer.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
 [test_fuel.js]
 [test_general.js]
 [test_getresource.js]
 [test_gfxBlacklist_Device.js]
 [test_gfxBlacklist_DriverNew.js]