Bug 1348981 - only load system add-ons from a built-in list r?kmag draft
authorRobert Helmer <rhelmer@mozilla.com>
Thu, 14 Sep 2017 00:36:04 -0700
changeset 668855 83eac9c787f2d8bdaa4c7e81fa600699fe7dae49
parent 668854 03b498be730b1f1341c4831c04db5a8381dc4808
child 732792 f20687540f2e29629ff5e62ede73ee46ff238ec3
push id81140
push userbmo:rhelmer@mozilla.com
push dateFri, 22 Sep 2017 03:38:54 +0000
reviewerskmag
bugs1348981
milestone58.0a1
Bug 1348981 - only load system add-ons from a built-in list r?kmag MozReview-Commit-ID: A6c5kaLmNPP
toolkit/mozapps/extensions/internal/XPIProvider.jsm
toolkit/mozapps/extensions/test/xpcshell/head_addons.js
toolkit/mozapps/extensions/test/xpcshell/test_nodisable_hidden.js
toolkit/mozapps/extensions/test/xpcshell/test_system_allowed.js
toolkit/mozapps/extensions/test/xpcshell/test_system_delay_update.js
toolkit/mozapps/extensions/test/xpcshell/test_system_repository.js
toolkit/mozapps/extensions/test/xpcshell/test_system_reset.js
toolkit/mozapps/extensions/test/xpcshell/test_system_update.js
toolkit/mozapps/extensions/test/xpcshell/test_system_update_fail.js
toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -97,16 +97,19 @@ const PREF_ALLOW_LEGACY               = 
 const PREF_ALLOW_NON_MPC              = "extensions.allow-non-mpc-extensions";
 
 const PREF_EM_MIN_COMPAT_APP_VERSION      = "extensions.minCompatibleAppVersion";
 const PREF_EM_MIN_COMPAT_PLATFORM_VERSION = "extensions.minCompatiblePlatformVersion";
 
 const PREF_EM_HOTFIX_ID               = "extensions.hotfix.id";
 const PREF_EM_LAST_APP_BUILD_ID       = "extensions.lastAppBuildId";
 
+// Specify a list of valid built-in add-ons to load.
+const BUILT_IN_ADDONS_URI             = "chrome://browser/content/built_in_addons.json";
+
 const OBSOLETE_PREFERENCES = [
   "extensions.bootstrappedAddons",
   "extensions.enabledAddons",
   "extensions.xpiState",
   "extensions.installCache",
 ];
 
 const URI_EXTENSION_STRINGS           = "chrome://mozapps/locale/extensions/extensions.properties";
@@ -2034,16 +2037,28 @@ this.XPIProvider = {
         logger.warn("Failed to add directory install location " + aName, e);
         return;
       }
 
       XPIProvider.installLocations.push(location);
       XPIProvider.installLocationsByName[location.name] = location;
     }
 
+    function addBuiltInInstallLocation(name, key, paths, scope) {
+      try {
+        let dir = FileUtils.getDir(key, paths);
+        let location = new BuiltInInstallLocation(name, dir, scope);
+
+        XPIProvider.installLocations.push(location);
+        XPIProvider.installLocationsByName[location.name] = location;
+      } catch (e) {
+        logger.warn(`Failed to add built-in install location ${name}`, e);
+      }
+    }
+
     function addSystemAddonInstallLocation(aName, aKey, aPaths, aScope) {
       try {
         var dir = FileUtils.getDir(aKey, aPaths);
       } catch (e) {
         // Some directories aren't defined on some platforms, ignore them
         logger.debug("Skipping unavailable install location " + aName);
         return;
       }
@@ -2102,18 +2117,18 @@ this.XPIProvider = {
       addDirectoryInstallLocation(KEY_APP_PROFILE, KEY_PROFILEDIR,
                                   [DIR_EXTENSIONS],
                                   AddonManager.SCOPE_PROFILE, false);
 
       addSystemAddonInstallLocation(KEY_APP_SYSTEM_ADDONS, KEY_PROFILEDIR,
                                     [DIR_SYSTEM_ADDONS],
                                     AddonManager.SCOPE_PROFILE);
 
-      addDirectoryInstallLocation(KEY_APP_SYSTEM_DEFAULTS, KEY_APP_FEATURES,
-                                  [], AddonManager.SCOPE_PROFILE, true);
+      addBuiltInInstallLocation(KEY_APP_SYSTEM_DEFAULTS, KEY_APP_FEATURES,
+                                [], AddonManager.SCOPE_PROFILE);
 
       if (enabledScopes & AddonManager.SCOPE_USER) {
         addDirectoryInstallLocation(KEY_APP_SYSTEM_USER, "XREUSysExt",
                                     [Services.appinfo.ID],
                                     AddonManager.SCOPE_USER, true);
         if (hasRegistry) {
           addRegistryInstallLocation("winreg-app-user",
                                      Ci.nsIWindowsRegKey.ROOT_KEY_CURRENT_USER,
@@ -6443,16 +6458,59 @@ class MutableDirectoryInstallLocation ex
 
     XPIStates.removeAddon(this.name, aId);
 
     delete this._IDToFileMap[aId];
   }
 }
 
 /**
+ * An object which identifies a built-in install location for add-ons, such
+ * as default system add-ons.
+ *
+ * This location should point either to an omni jar, or a directory in a local build.
+ */
+class BuiltInInstallLocation extends DirectoryInstallLocation {
+  /**
+   * Read the manifest of allowed add-ons and build a mapping between ID and URI
+   * for each.
+   */
+  _readAddons() {
+    let manifest;
+    try {
+      let url = Services.io.newURI(BUILT_IN_ADDONS_URI);
+      let data = Cu.readURI(url);
+      manifest = JSON.parse(data);
+    } catch (e) {
+      logger.warn("List of valid built-in add-ons could not be parsed.", e);
+      return;
+    }
+
+    if (!("system" in manifest)) {
+      logger.warn("No list of valid system add-ons found.");
+      return;
+    }
+
+    for (let id of manifest.system) {
+      let file = new FileUtils.File(this._directory.path);
+      file.append(`${id}.xpi`);
+
+      // Only attempt to load unpacked directory if unofficial build.
+      if (!AppConstants.MOZILLA_OFFICIAL && !file.exists()) {
+        file = new FileUtils.File(this._directory.path);
+        file.append(`${id}`);
+      }
+
+      this._IDToFileMap[id] = file;
+      XPIProvider._addURIMapping(id, file);
+    }
+  }
+}
+
+/**
  * An object which identifies a directory install location for system add-ons
  * updates.
  */
 class SystemAddonInstallLocation extends MutableDirectoryInstallLocation {
   /**
     * The location consists of a directory which contains the add-ons installed.
     *
     * @param  aName
--- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js
@@ -19,16 +19,18 @@ const PREF_EM_MIN_COMPAT_APP_VERSION    
 const PREF_EM_MIN_COMPAT_PLATFORM_VERSION = "extensions.minCompatiblePlatformVersion";
 const PREF_GETADDONS_BYIDS               = "extensions.getAddons.get.url";
 const PREF_GETADDONS_BYIDS_PERFORMANCE   = "extensions.getAddons.getWithPerformance.url";
 const PREF_XPI_SIGNATURES_REQUIRED    = "xpinstall.signatures.required";
 const PREF_SYSTEM_ADDON_SET           = "extensions.systemAddonSet";
 const PREF_SYSTEM_ADDON_UPDATE_URL    = "extensions.systemAddon.update.url";
 const PREF_APP_UPDATE_ENABLED         = "app.update.enabled";
 const PREF_ALLOW_NON_MPC              = "extensions.allow-non-mpc-extensions";
+const PREF_DISABLE_SECURITY = ("security.turn_off_all_security_so_that_" +
+                               "viruses_can_take_over_this_computer");
 
 // Forcibly end the test if it runs longer than 15 minutes
 const TIMEOUT_MS = 900000;
 
 // 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;
@@ -154,16 +156,17 @@ Object.defineProperty(this, "TEST_UNPACK
 // We need some internal bits of AddonManager
 var AMscope = Components.utils.import("resource://gre/modules/AddonManager.jsm", {});
 var { AddonManager, AddonManagerInternal, AddonManagerPrivate } = AMscope;
 
 const promiseAddonByID = AddonManager.getAddonByID;
 const promiseAddonsByIDs = AddonManager.getAddonsByIDs;
 const promiseAddonsWithOperationsByTypes = AddonManager.getAddonsWithOperationsByTypes;
 
+let gStartup = null;
 var gPort = null;
 var gUrlToFileMap = {};
 
 // Map resource://xpcshell-data/ to the data directory
 var resHandler = Services.io.getProtocolHandler("resource")
                          .QueryInterface(AM_Ci.nsISubstitutingProtocolHandler);
 // Allow non-existent files because of bug 1207735
 var dataURI = NetUtil.newURI(do_get_file("data", true));
@@ -1524,22 +1527,24 @@ async function getSystemAddonDirectories
  *  of the form {isUpgrade: false, version: null}
  *
  * @param {nsIFile} distroDir - the system add-on distribution directory (the "features" dir in the app directory)
  */
 async function setupSystemAddonConditions(setup, distroDir) {
   do_print("Clearing existing database.");
   Services.prefs.clearUserPref(PREF_SYSTEM_ADDON_SET);
   distroDir.leafName = "empty";
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system4@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager(false);
   await promiseShutdownManager();
 
   do_print("Setting up conditions.");
   await setup.setup();
 
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system4@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager(false);
 
   // Make sure the initial state is correct
   do_print("Checking initial state.");
   await checkInstalledSystemAddons(setup.initialState, distroDir);
 }
 
 /**
@@ -1575,17 +1580,19 @@ async function verifySystemAddonState(in
   do_print("Checking final state.");
 
   let dirs = await getSystemAddonDirectories();
   do_check_eq(dirs.length, expectedDirs);
 
   await checkInstalledSystemAddons(...finalState, distroDir);
 
   // Check that the new state is active after a restart
-  await promiseRestartManager();
+  shutdownManager();
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system4@tests.mozilla.org", "system5@tests.mozilla.org"] });
+  await promiseStartupManager();
   await checkInstalledSystemAddons(finalState, distroDir);
 }
 
 /**
  * Run system add-on tests and compare the results against a set of expected conditions.
  *
  * @param {String} setupName - name of the current setup conditions.
  * @param {Object<function, Array<Object>} setup -  Defines the set of initial conditions to run each test against. Each should
@@ -1630,8 +1637,30 @@ async function execSystemAddonTest(setup
   if (test.finalState && setupName in test.finalState) {
     await verifySystemAddonState(setup.initialState, test.finalState[setupName], false, distroDir);
   } else {
     await verifySystemAddonState(setup.initialState, undefined, false, distroDir);
   }
 
   await promiseShutdownManager();
 }
+
+/**
+ * Override chrome URL for specifying allowed built-in add-ons.
+ *
+ * @param {object} data - An object specifying which add-on IDs are permitted
+ *                        to load, for instance: { "system": ["id1", "..."] }
+ */
+async function overrideBuiltIns(data) {
+  // We need to set this in order load the URL preloader service, which
+  // is only possible when running in automation.
+  Services.prefs.setBoolPref(PREF_DISABLE_SECURITY, true);
+  aomStartup.initializeURLPreloader();
+
+  let file = FileUtils.getFile("TmpD", "override.txt");
+  let manifest = Services.io.newFileURI(file);
+  await OS.File.writeAtomic(file.path,
+    new TextEncoder().encode(JSON.stringify(data)));
+  gStartup = aomStartup.registerChrome(manifest, [
+    ["override", "chrome://browser/content/built_in_addons.json",
+     Services.io.newFileURI(file).spec],
+  ]);
+}
--- a/toolkit/mozapps/extensions/test/xpcshell/test_nodisable_hidden.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_nodisable_hidden.js
@@ -69,16 +69,18 @@ add_task(async function() {
     targetApplications: [{
       id: "xpcshell@tests.mozilla.org",
       minVersion: "1",
       maxVersion: "1"
     }],
     name: "Test disabling hidden add-ons, hidden system add-on case.",
   }, distroDir, SYSTEM_ID);
 
+  await overrideBuiltIns({ "system": [SYSTEM_ID] });
+
   startupManager();
 
   let addon = await promiseAddonByID(SYSTEM_ID);
   do_check_neq(addon, null);
   do_check_eq(addon.version, "1.0");
   do_check_eq(addon.name, "Test disabling hidden add-ons, hidden system add-on case.");
   do_check_true(addon.isCompatible);
   do_check_false(addon.appDisabled);
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_allowed.js
@@ -0,0 +1,48 @@
+// Tests that only allowed built-in system add-ons are loaded on startup.
+
+BootstrapMonitor.init();
+
+// Build the test set
+var distroDir = FileUtils.getDir("ProfD", ["sysfeatures"], true);
+do_get_file("data/system_addons/system1_1.xpi").copyTo(distroDir, "system1@tests.mozilla.org.xpi");
+do_get_file("data/system_addons/system2_1.xpi").copyTo(distroDir, "system2@tests.mozilla.org.xpi");
+do_get_file("data/system_addons/system3_1.xpi").copyTo(distroDir, "system3@tests.mozilla.org.xpi");
+registerDirectory("XREAppFeat", distroDir);
+
+createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "0");
+
+// Ensure that only allowed add-ons are loaded.
+add_task(async function test_allowed_addons() {
+  // 1 and 2 are allowed, 3 is not.
+  let validAddons = { "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org"]};
+  await overrideBuiltIns(validAddons);
+
+  await promiseStartupManager();
+
+  let addon = await AddonManager.getAddonByID("system1@tests.mozilla.org");
+  notEqual(addon, null);
+
+  addon = await AddonManager.getAddonByID("system2@tests.mozilla.org");
+  notEqual(addon, null);
+
+  addon = await AddonManager.getAddonByID("system3@tests.mozilla.org");
+  do_check_eq(addon, null);
+  equal(addon, null);
+
+  // 3 is now allowed, 1 and 2 are not.
+  validAddons = { "system": ["system3@tests.mozilla.org"]};
+  await overrideBuiltIns(validAddons);
+
+  await promiseRestartManager();
+
+  addon = await AddonManager.getAddonByID("system1@tests.mozilla.org");
+  equal(addon, null);
+
+  addon = await AddonManager.getAddonByID("system2@tests.mozilla.org");
+  equal(addon, null);
+
+  addon = await AddonManager.getAddonByID("system3@tests.mozilla.org");
+  notEqual(addon, null);
+
+  await promiseShutdownManager();
+});
--- a/toolkit/mozapps/extensions/test/xpcshell/test_system_delay_update.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_delay_update.js
@@ -9,17 +9,16 @@ const profileDir = gProfD.clone();
 profileDir.append("extensions");
 
 const IGNORE_ID = "system_delay_ignore@tests.mozilla.org";
 const COMPLETE_ID = "system_delay_complete@tests.mozilla.org";
 const DEFER_ID = "system_delay_defer@tests.mozilla.org";
 const DEFER_ALSO_ID = "system_delay_defer_also@tests.mozilla.org";
 const NORMAL_ID = "system1@tests.mozilla.org";
 
-
 const TEST_IGNORE_PREF = "delaytest.ignore";
 
 const distroDir = FileUtils.getDir("ProfD", ["sysfeatures"], true);
 registerDirectory("XREAppFeat", distroDir);
 
 let testserver = new HttpServer();
 testserver.registerDirectory("/data/", do_get_file("data/system_addons"));
 testserver.start();
@@ -113,16 +112,18 @@ function promiseInstallDeferred(addonID1
 // add-on registers upgrade listener, and ignores update.
 add_task(async function() {
   // discard system addon updates
   Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, "");
 
   do_get_file("data/system_addons/system_delay_ignore.xpi").copyTo(distroDir, "system_delay_ignore@tests.mozilla.org.xpi");
   do_get_file("data/system_addons/system1_1.xpi").copyTo(distroDir, "system1@tests.mozilla.org.xpi");
 
+  await overrideBuiltIns({ "system": [IGNORE_ID, NORMAL_ID] })
+
   startupManager();
   let updateList = [
     { id: IGNORE_ID, version: "2.0", path: "system_delay_ignore_2.xpi" },
     { id: NORMAL_ID, version: "2.0", path: "system1_2.xpi" },
   ];
 
   let postponed = promiseInstallPostponed(IGNORE_ID, NORMAL_ID);
   await installSystemAddons(await buildSystemAddonUpdates(updateList, root), testserver);
@@ -176,16 +177,18 @@ add_task(async function() {
 // add-on registers upgrade listener, and allows update.
 add_task(async function() {
   // discard system addon updates
   Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, "");
 
   do_get_file("data/system_addons/system_delay_complete.xpi").copyTo(distroDir, "system_delay_complete@tests.mozilla.org.xpi");
   do_get_file("data/system_addons/system1_1.xpi").copyTo(distroDir, "system1@tests.mozilla.org.xpi");
 
+  await overrideBuiltIns({ "system": [COMPLETE_ID, NORMAL_ID] })
+
   startupManager();
 
   let updateList = [
     { id: COMPLETE_ID, version: "2.0", path: "system_delay_complete_2.xpi" },
     { id: NORMAL_ID, version: "2.0", path: "system1_2.xpi" },
   ];
 
   // initial state
@@ -260,16 +263,18 @@ add_task(async function() {
 // add-on registers upgrade listener, initially defers update then allows upgrade
 add_task(async function() {
   // discard system addon updates
   Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, "");
 
   do_get_file("data/system_addons/system_delay_defer.xpi").copyTo(distroDir, "system_delay_defer@tests.mozilla.org.xpi");
   do_get_file("data/system_addons/system1_1.xpi").copyTo(distroDir, "system1@tests.mozilla.org.xpi");
 
+  await overrideBuiltIns({ "system": [DEFER_ID, NORMAL_ID] })
+
   startupManager();
 
   let updateList = [
     { id: DEFER_ID, version: "2.0", path: "system_delay_defer_2.xpi" },
     { id: NORMAL_ID, version: "2.0", path: "system1_2.xpi" },
   ];
 
   let postponed = promiseInstallPostponed(DEFER_ID, NORMAL_ID);
@@ -349,16 +354,18 @@ add_task(async function() {
 // multiple add-ons registers upgrade listeners, initially defers then each unblock in turn.
 add_task(async function() {
   // discard system addon updates.
   Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, "");
 
   do_get_file("data/system_addons/system_delay_defer.xpi").copyTo(distroDir, "system_delay_defer@tests.mozilla.org.xpi");
   do_get_file("data/system_addons/system_delay_defer_also.xpi").copyTo(distroDir, "system_delay_defer_also@tests.mozilla.org.xpi");
 
+  await overrideBuiltIns({ "system": [DEFER_ID, DEFER_ALSO_ID] })
+
   startupManager();
 
   let updateList = [
     { id: DEFER_ID, version: "2.0", path: "system_delay_defer_2.xpi" },
     { id: DEFER_ALSO_ID, version: "2.0", path: "system_delay_defer_also_2.xpi" },
   ];
 
   let postponed = promiseInstallPostponed(DEFER_ID, DEFER_ALSO_ID);
--- a/toolkit/mozapps/extensions/test/xpcshell/test_system_repository.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_repository.js
@@ -25,16 +25,18 @@ function getCachedAddon(id) {
 add_task(async function test_app_addons() {
   Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true);
   Services.prefs.setCharPref(PREF_GETADDONS_BYIDS, `http://localhost:${gServer.identity.primaryPort}/get?%IDS%`);
 
   gServer.registerPathHandler("/get", (request, response) => {
     do_throw("Unexpected request to server.");
   });
 
+  awaitPromise(overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org"] }))
+
   startupManager();
 
   await new Promise((resolve) => {
     AddonRepository.cacheAddons(["system1@tests.mozilla.org",
                                  "system2@tests.mozilla.org",
                                  "system3@tests.mozilla.org"], resolve);
   });
 
--- a/toolkit/mozapps/extensions/test/xpcshell/test_system_reset.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_reset.js
@@ -90,16 +90,17 @@ async function check_installed(condition
       else
         BootstrapMonitor.checkAddonNotInstalled(id);
     }
   }
 }
 
 // Test with a missing features directory
 add_task(async function test_missing_app_dir() {
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager();
 
   let conditions = [
       { isUpgrade: false, version: null },
       { isUpgrade: false, version: null },
       { isUpgrade: false, version: null },
   ];
 
@@ -109,16 +110,17 @@ add_task(async function test_missing_app
 
   await promiseShutdownManager();
 });
 
 // Add some features in a new version
 add_task(async function test_new_version() {
   gAppInfo.version = "1";
   distroDir.leafName = "app1";
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager();
 
   let conditions = [
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: false, version: null },
   ];
 
@@ -128,16 +130,17 @@ add_task(async function test_new_version
 
   await promiseShutdownManager();
 });
 
 // Another new version swaps one feature and upgrades another
 add_task(async function test_upgrade() {
   gAppInfo.version = "2";
   distroDir.leafName = "app2";
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager();
 
   let conditions = [
       { isUpgrade: false, version: "2.0" },
       { isUpgrade: false, version: null },
       { isUpgrade: false, version: "1.0" },
   ];
 
@@ -147,16 +150,17 @@ add_task(async function test_upgrade() {
 
   await promiseShutdownManager();
 });
 
 // Downgrade
 add_task(async function test_downgrade() {
   gAppInfo.version = "1";
   distroDir.leafName = "app1";
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager();
 
   let conditions = [
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: false, version: null },
   ];
 
@@ -190,16 +194,17 @@ add_task(async function test_updated() {
       },
       "system3@tests.mozilla.org": {
         version: "2.0"
       },
     }
   };
   Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, JSON.stringify(addonSet));
 
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager(false);
 
   let conditions = [
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: true, version: "2.0" },
       { isUpgrade: true, version: "2.0" },
   ];
 
@@ -207,32 +212,34 @@ add_task(async function test_updated() {
 
   await promiseShutdownManager();
 });
 
 // Entering safe mode should disable the updated system add-ons and use the
 // default system add-ons
 add_task(async function safe_mode_disabled() {
   gAppInfo.inSafeMode = true;
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager(false);
 
   let conditions = [
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: false, version: null },
   ];
 
   await check_installed(conditions);
 
   await promiseShutdownManager();
 });
 
 // Leaving safe mode should re-enable the updated system add-ons
 add_task(async function normal_mode_enabled() {
   gAppInfo.inSafeMode = false;
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager(false);
 
   let conditions = [
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: true, version: "2.0" },
       { isUpgrade: true, version: "2.0" },
   ];
 
@@ -242,16 +249,17 @@ add_task(async function normal_mode_enab
 });
 
 // An additional add-on in the directory should be ignored
 add_task(async function test_skips_additional() {
   // Copy in the system add-ons
   let file = do_get_file("data/system_addons/system4_1.xpi");
   file.copyTo(updatesDir, "system4@tests.mozilla.org.xpi");
 
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager(false);
 
   let conditions = [
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: true, version: "2.0" },
       { isUpgrade: true, version: "2.0" },
   ];
 
@@ -262,16 +270,17 @@ add_task(async function test_skips_addit
 
 // Missing add-on should revert to the default set
 add_task(async function test_revert() {
   manuallyUninstall(updatesDir, "system2@tests.mozilla.org");
 
   // With the add-on physically gone from disk we won't see uninstall events
   BootstrapMonitor.clear("system2@tests.mozilla.org");
 
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager(false);
 
   // With system add-on 2 gone the updated set is now invalid so it reverts to
   // the default set which is system add-ons 1 and 2.
   let conditions = [
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: false, version: null },
@@ -282,16 +291,17 @@ add_task(async function test_revert() {
   await promiseShutdownManager();
 });
 
 // Putting it back will make the set work again
 add_task(async function test_reuse() {
   let file = do_get_file("data/system_addons/system2_2.xpi");
   file.copyTo(updatesDir, "system2@tests.mozilla.org.xpi");
 
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager(false);
 
   let conditions = [
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: true, version: "2.0" },
       { isUpgrade: true, version: "2.0" },
   ];
 
@@ -299,16 +309,17 @@ add_task(async function test_reuse() {
 
   await promiseShutdownManager();
 });
 
 // Making the pref corrupt should revert to the default set
 add_task(async function test_corrupt_pref() {
   Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, "foo");
 
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager(false);
 
   let conditions = [
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: false, version: null },
   ];
 
@@ -335,16 +346,17 @@ add_task(async function test_bad_profile
       },
       "system3@tests.mozilla.org": {
         version: "1.0"
       },
     }
   };
   Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, JSON.stringify(addonSet));
 
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager(false);
 
   let conditions = [
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: false, version: "1.0" },
       { isUpgrade: false, version: null },
   ];
 
@@ -352,16 +364,17 @@ add_task(async function test_bad_profile
 
   await promiseShutdownManager();
 });
 
 // Switching to app defaults that contain a bad certificate should still work
 add_task(async function test_bad_app_cert() {
   gAppInfo.version = "3";
   distroDir.leafName = "app3";
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager();
 
   // Since we updated the app version, the system addon set should be reset as well.
   let addonSet = Services.prefs.getCharPref(PREF_SYSTEM_ADDON_SET);
   do_check_eq(addonSet, `{"schema":1,"addons":{}}`);
 
   // Add-on will still be present
   let addon = await promiseAddonByID("system1@tests.mozilla.org");
@@ -402,19 +415,19 @@ add_task(async function test_updated_bad
       },
       "system_failed_update@tests.mozilla.org": {
         version: "1.0"
       },
     }
   };
   Services.prefs.setCharPref(PREF_SYSTEM_ADDON_SET, JSON.stringify(addonSet));
 
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager(false);
 
   let conditions = [
       { isUpgrade: false, version: "1.0" },
   ];
 
   await check_installed(conditions);
 
   await promiseShutdownManager();
 });
-
--- a/toolkit/mozapps/extensions/test/xpcshell/test_system_update.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_update.js
@@ -293,16 +293,17 @@ const TESTS = {
         { isUpgrade: true, version: "1.0"}
       ]
     }
   }
 }
 
 add_task(async function setup() {
   // Initialise the profile
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system4@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager();
   await promiseShutdownManager();
 });
 
 add_task(async function() {
   for (let setupName of Object.keys(TEST_CONDITIONS)) {
     for (let testName of Object.keys(TESTS)) {
         do_print("Running test " + setupName + " " + testName);
--- a/toolkit/mozapps/extensions/test/xpcshell/test_system_update_fail.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_fail.js
@@ -161,16 +161,17 @@ const TESTS = {
       { id: "system6@tests.mozilla.org", version: "1.0", path: "system6_3_notMultiprocess.xpi" },
       { id: "system3@tests.mozilla.org", version: "1.0", path: "system3_1.xpi" }
     ],
   }
 }
 
 add_task(async function setup() {
   // Initialise the profile
+  await overrideBuiltIns({ "system": ["system1@tests.mozilla.org", "system2@tests.mozilla.org", "system3@tests.mozilla.org", "system4@tests.mozilla.org", "system5@tests.mozilla.org"] });
   startupManager();
   await promiseShutdownManager();
 });
 
 add_task(async function() {
   for (let setupName of Object.keys(TEST_CONDITIONS)) {
     for (let testName of Object.keys(TESTS)) {
         do_print("Running test " + setupName + " " + testName);
--- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
+++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
@@ -46,10 +46,11 @@ tags = webextensions
 [test_nodisable_hidden.js]
 [test_delay_update_webextension.js]
 skip-if = appname == "thunderbird"
 tags = webextensions
 [test_dependencies.js]
 [test_system_delay_update.js]
 [test_schema_change.js]
 [test_registerchrome.js]
+[test_system_allowed.js]
 
 [include:xpcshell-shared.ini]