Bug 1371762 Part 2 Treat webextension experiments as legacy r=rhelmer
authorAndrew Swan <aswan@mozilla.com>
Wed, 19 Jul 2017 10:28:23 -0700
changeset 418788 7255faf1c8a4b0c34d6b01c1fe3af78444d1c750
parent 418787 47ebbbac4f990cca0dd681d18ff9be77bbb2fdca
child 418789 ec7291c0411c49ff2227cb961083726496ddf01e
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrhelmer
bugs1371762
milestone56.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 1371762 Part 2 Treat webextension experiments as legacy r=rhelmer MozReview-Commit-ID: ATa0DXnV2au
toolkit/mozapps/extensions/internal/XPIProvider.jsm
toolkit/mozapps/extensions/test/xpcshell/test_legacy.js
toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -257,17 +257,22 @@ const CHROME_TYPES = new Set([
 const SIGNED_TYPES = new Set([
   "apiextension",
   "extension",
   "experiment",
   "webextension",
   "webextension-theme",
 ]);
 
-const ALL_TYPES = new Set([
+const LEGACY_TYPES = new Set([
+  "apiextension",
+  "extension",
+]);
+
+const ALL_EXTERNAL_TYPES = new Set([
   "dictionary",
   "extension",
   "experiment",
   "locale",
   "theme",
 ]);
 
 // Whether add-on signing is required.
@@ -830,18 +835,18 @@ function isUsableAddon(aAddon) {
       let active = XPIProvider.activeAddons.get(id);
       return active && !active.disable;
     };
 
     if (aAddon.dependencies.some(id => !isActive(id)))
       return false;
   }
 
-  if (!AddonSettings.ALLOW_LEGACY_EXTENSIONS &&
-      aAddon.type == "extension" && !aAddon._installLocation.isSystem &&
+  if (!AddonSettings.ALLOW_LEGACY_EXTENSIONS && LEGACY_TYPES.has(aAddon.type) &&
+      !aAddon._installLocation.isSystem &&
       aAddon.signedState !== AddonManager.SIGNEDSTATE_PRIVILEGED) {
     logger.warn(`disabling legacy extension ${aAddon.id}`);
     return false;
   }
 
   if (!ALLOW_NON_MPC && aAddon.type == "extension" &&
       aAddon.multiprocessCompatible !== true) {
     logger.warn(`disabling ${aAddon.id} since it is not multiprocess compatible`);
@@ -3583,17 +3588,17 @@ this.XPIProvider = {
    *
    * @param  aTypes
    *         An array of types to fetch. Can be null to get all types.
    * @param  aCallback
    *         A callback to pass an array of Addons to
    */
   getAddonsByTypes(aTypes, aCallback) {
     let typesToGet = getAllAliasesForTypes(aTypes);
-    if (typesToGet && !typesToGet.some(type => ALL_TYPES.has(type))) {
+    if (typesToGet && !typesToGet.some(type => ALL_EXTERNAL_TYPES.has(type))) {
       aCallback([]);
       return;
     }
 
     XPIDatabase.getVisibleAddons(typesToGet, function(aAddons) {
       aCallback(aAddons.map(a => a.wrapper));
     });
   },
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_legacy.js
@@ -0,0 +1,131 @@
+
+const LEGACY_PREF = "extensions.legacy.enabled";
+
+createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1");
+startupManager();
+
+add_task(async function test_disable() {
+  let legacy = [
+    {
+      id: "bootstrap@tests.mozilla.org",
+      name: "Bootstrap add-on",
+      version: "1.0",
+      bootstrap: true,
+      multiprocessCompatible: true,
+    },
+    {
+      id: "apiexperiment@tests.mozilla.org",
+      name: "WebExtension Experiment",
+      version: "1.0",
+      type: 256,
+    },
+  ];
+
+  let nonLegacy = [
+    {
+      id: "webextension@tests.mozilla.org",
+      manifest: {
+        applications: {gecko: {id: "webextension@tests.mozilla.org"}},
+      },
+    },
+    {
+      id: "privileged@tests.mozilla.org",
+      name: "Privileged Bootstrap add-on",
+      version: "1.0",
+      bootstrap: true,
+      multiprocessCompatible: true,
+    },
+    {
+      id: "langpack@tests.mozilla.org",
+      name: "Test Langpack",
+      version: "1.0",
+      type: "8",
+    },
+    {
+      id: "dictionary@tests.mozilla.org",
+      name: "Test Dictionary",
+      version: "1.0",
+      type: "64",
+    }
+  ];
+
+  function makeXPI(info) {
+    if (info.manifest) {
+      return createTempWebExtensionFile(info);
+    }
+
+    return createTempXPIFile(Object.assign({}, info, {
+      targetApplications: [{
+        id: "xpcshell@tests.mozilla.org",
+        minVersion: "1",
+        maxVersion: "1"
+      }],
+    }));
+  }
+
+  AddonTestUtils.usePrivilegedSignatures = id => id.startsWith("privileged");
+
+  // Start out with legacy extensions disabled, installing non-legacy
+  // extensions should succeed.
+  Services.prefs.setBoolPref(LEGACY_PREF, false);
+  let installs = await Promise.all(nonLegacy.map(info => {
+    let xpi = makeXPI(info);
+    return AddonManager.getInstallForFile(xpi);
+  }));
+  await promiseCompleteAllInstalls(installs);
+  for (let install of installs) {
+    do_check_eq(install.state, AddonManager.STATE_INSTALLED);
+    do_check_eq(install.error, 0);
+  }
+  let addons = await AddonManager.getAddonsByIDs(nonLegacy.map(a => a.id));
+  for (let addon of addons) {
+    do_check_eq(addon.appDisabled, false);
+  }
+
+  // And installing legacy extensions should fail
+  let legacyXPIs = legacy.map(makeXPI);
+  installs = await Promise.all(legacyXPIs.map(xpi => AddonManager.getInstallForFile(xpi)));
+
+  // Yuck, the AddonInstall API is atrocious.  Installs of incompatible
+  // extensions are detected when the install reaches the DOWNLOADED state
+  // and the install is abandoned at that point.  Since this is a local file
+  // install we just start out in the DONWLOADED state.
+  for (let install of installs) {
+    do_check_eq(install.state, AddonManager.STATE_DOWNLOADED);
+    do_check_eq(install.addon.appDisabled, true);
+  }
+
+  // Now enable legacy extensions, and we should be able to install
+  // the legacy extensions.
+  Services.prefs.setBoolPref(LEGACY_PREF, true);
+  installs = await Promise.all(legacyXPIs.map(xpi => AddonManager.getInstallForFile(xpi)));
+  for (let install of installs) {
+    do_check_eq(install.state, AddonManager.STATE_DOWNLOADED);
+    do_check_eq(install.addon.appDisabled, false);
+  }
+  await promiseCompleteAllInstalls(installs);
+  for (let install of installs) {
+    do_check_eq(install.state, AddonManager.STATE_INSTALLED);
+    do_check_eq(install.error, 0);
+  }
+  addons = await AddonManager.getAddonsByIDs(legacy.map(a => a.id));
+  for (let addon of addons) {
+    do_check_eq(addon.appDisabled, false);
+  }
+
+  // Flip the preference back, the legacy extensions should become disabled
+  // but non-legacy extensions should remain enabled.
+  Services.prefs.setBoolPref(LEGACY_PREF, false);
+  addons = await AddonManager.getAddonsByIDs(nonLegacy.map(a => a.id));
+  for (let addon of addons) {
+    do_check_eq(addon.appDisabled, false);
+    addon.uninstall();
+  }
+  addons = await AddonManager.getAddonsByIDs(legacy.map(a => a.id));
+  for (let addon of addons) {
+    do_check_eq(addon.appDisabled, true);
+    addon.uninstall();
+  }
+
+  Services.prefs.clearUserPref(LEGACY_PREF);
+});
--- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini
+++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell-shared.ini
@@ -234,16 +234,17 @@ tags = blocklist
 [test_install_icons.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"
 run-sequentially = Uses hardcoded ports in xpi files.
 [test_isDebuggable.js]
+[test_legacy.js]
 [test_locale.js]
 [test_locked.js]
 [test_locked2.js]
 [test_locked_strictcompat.js]
 [test_manifest.js]
 [test_mapURIToAddonID.js]
 # Same as test_bootstrap.js
 skip-if = os == "android"