diff --git a/services/sync/tests/unit/test_addons_store.js b/services/sync/tests/unit/test_addons_store.js index ab5a53dec88a..f5a823650d44 100644 --- a/services/sync/tests/unit/test_addons_store.js +++ b/services/sync/tests/unit/test_addons_store.js @@ -37,6 +37,7 @@ function loadSystemAddon() { loadAddonTestFunctions(); loadSystemAddon(); +awaitPromise(overrideBuiltIns({ "system": [SYSTEM_ADDON_ID] })); startupManager(); let engine; diff --git a/toolkit/components/telemetry/tests/unit/head.js b/toolkit/components/telemetry/tests/unit/head.js index 558df77f8c4a..161201fc8bef 100644 --- a/toolkit/components/telemetry/tests/unit/head.js +++ b/toolkit/components/telemetry/tests/unit/head.js @@ -179,7 +179,7 @@ function wrapWithExceptionHandler(f) { return wrapper; } -function loadAddonManager(...args) { +async function loadAddonManager(...args) { AddonTestUtils.init(gGlobalScope); AddonTestUtils.overrideCertDB(); createAppInfo(...args); @@ -188,6 +188,8 @@ function loadAddonManager(...args) { // used by system add-ons. const distroDir = FileUtils.getDir("ProfD", ["sysfeatures", "app0"], true); AddonTestUtils.registerDirectory("XREAppFeat", distroDir); + await AddonTestUtils.overrideBuiltIns( + {"system": ["tel-system-xpi@tests.mozilla.org"]}); return AddonTestUtils.promiseStartupManager(); } diff --git a/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js b/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js index 41ae24635a97..4df3047d45f8 100644 --- a/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js +++ b/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js @@ -858,7 +858,7 @@ add_task(async function setup() { let system_addon = FileUtils.File(distroDir.path); system_addon.append("tel-system-xpi@tests.mozilla.org.xpi"); system_addon.lastModifiedTime = SYSTEM_ADDON_INSTALL_DATE; - loadAddonManager(APP_ID, APP_NAME, APP_VERSION, PLATFORM_VERSION); + await loadAddonManager(APP_ID, APP_NAME, APP_VERSION, PLATFORM_VERSION); // Spoof the persona ID. LightweightThemeManager.currentTheme = diff --git a/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm b/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm index e9834973d8a9..b05f59bf7256 100644 --- a/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm +++ b/toolkit/mozapps/extensions/internal/AddonTestUtils.jsm @@ -220,6 +220,7 @@ var AddonTestUtils = { testUnpacked: false, useRealCertChecks: false, usePrivilegedSignatures: true, + overrideEntry: null, init(testScope) { this.testScope = testScope; @@ -593,6 +594,10 @@ var AddonTestUtils = { if (!this.addonIntegrationService) return Promise.resolve(false); + if (this.overrideEntry) { + this.overrideEntry.destruct(); + } + Services.obs.notifyObservers(null, "quit-application-granted"); return MockAsyncShutdown.hook() .then(() => { @@ -1273,6 +1278,29 @@ var AddonTestUtils = { }); }); }, + + /** + * 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 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))); + this.overrideEntry = aomStartup.registerChrome(manifest, [ + ["override", "chrome://browser/content/built_in_addons.json", + Services.io.newFileURI(file).spec], + ]); + Services.prefs.setBoolPref(PREF_DISABLE_SECURITY, false); + } }; for (let [key, val] of Object.entries(AddonTestUtils)) { diff --git a/toolkit/mozapps/extensions/internal/XPIProvider.jsm b/toolkit/mozapps/extensions/internal/XPIProvider.jsm index fa5ed01d08c7..99d7b8317e1e 100644 --- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm +++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm @@ -102,6 +102,9 @@ const PREF_EM_MIN_COMPAT_PLATFORM_VERSION = "extensions.minCompatiblePlatformVer 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", @@ -2039,6 +2042,18 @@ this.XPIProvider = { 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); @@ -2107,8 +2122,8 @@ this.XPIProvider = { [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", @@ -6447,6 +6462,49 @@ class MutableDirectoryInstallLocation extends DirectoryInstallLocation { } } +/** + * An object which identifies a built-in install location for add-ons, such + * as default system add-ons. + * + * This location should point either to a XPI, 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. diff --git a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js index e80bd63d5a18..9e8777f7947a 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/head_addons.js +++ b/toolkit/mozapps/extensions/test/xpcshell/head_addons.js @@ -24,6 +24,8 @@ 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; @@ -74,6 +76,7 @@ const { createUpdateRDF, getFileForAddon, manuallyUninstall, + overrideBuiltIns, promiseAddonEvent, promiseCompleteAllInstalls, promiseCompleteInstall, @@ -1529,12 +1532,23 @@ async function setupSystemAddonConditions(setup, distroDir) { do_print("Clearing existing database."); Services.prefs.clearUserPref(PREF_SYSTEM_ADDON_SET); distroDir.leafName = "empty"; + + let updateList = []; + awaitPromise(overrideBuiltIns({ "system": updateList })); startupManager(false); await promiseShutdownManager(); do_print("Setting up conditions."); await setup.setup(); + if (distroDir) { + if (distroDir.path.endsWith("hidden")) { + updateList = ["system1@tests.mozilla.org", "system2@tests.mozilla.org"]; + } else if (distroDir.path.endsWith("prefilled")) { + updateList = ["system2@tests.mozilla.org", "system3@tests.mozilla.org"]; + } + } + awaitPromise(overrideBuiltIns({ "system": updateList })); startupManager(false); // Make sure the initial state is correct @@ -1580,7 +1594,19 @@ async function verifySystemAddonState(initialState, finalState = undefined, alre await checkInstalledSystemAddons(...finalState, distroDir); // Check that the new state is active after a restart - await promiseRestartManager(); + await promiseShutdownManager(); + + let updateList = []; + + if (distroDir) { + if (distroDir.path.endsWith("hidden")) { + updateList = ["system1@tests.mozilla.org", "system2@tests.mozilla.org"]; + } else if (distroDir.path.endsWith("prefilled")) { + updateList = ["system2@tests.mozilla.org", "system3@tests.mozilla.org"]; + } + } + awaitPromise(overrideBuiltIns({ "system": updateList })); + startupManager(); await checkInstalledSystemAddons(finalState, distroDir); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_nodisable_hidden.js b/toolkit/mozapps/extensions/test/xpcshell/test_nodisable_hidden.js index 428bbc0571bb..a927004cda42 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_nodisable_hidden.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_nodisable_hidden.js @@ -18,7 +18,7 @@ createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "42"); // normal add-ons can be user disabled. add_task(async function() { - writeInstallRDFToDir({ + writeInstallRDFToXPI({ id: NORMAL_ID, version: "1.0", bootstrap: true, @@ -62,7 +62,7 @@ add_task(async function() { // system add-ons can never be user disabled. add_task(async function() { - writeInstallRDFToDir({ + writeInstallRDFToXPI({ id: SYSTEM_ID, version: "1.0", bootstrap: true, @@ -74,6 +74,8 @@ add_task(async function() { 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); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_allowed.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_allowed.js new file mode 100644 index 000000000000..eb5cdbf595fc --- /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(); +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_delay_update.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_delay_update.js index 7732a1aa7193..74196fb0983e 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_system_delay_update.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_delay_update.js @@ -14,7 +14,6 @@ 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); @@ -118,6 +117,8 @@ add_task(async function() { 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" }, @@ -181,6 +182,8 @@ add_task(async function() { 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 = [ @@ -265,6 +268,8 @@ add_task(async function() { 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 = [ @@ -354,6 +359,8 @@ add_task(async function() { 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 = [ diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_repository.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_repository.js index 2a32b579e833..d3b8865a6c44 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_system_repository.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_repository.js @@ -30,6 +30,8 @@ add_task(async function test_app_addons() { 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) => { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_reset.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_reset.js index 921b0fc64f37..9034f4b4ec90 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_system_reset.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_reset.js @@ -95,6 +95,7 @@ async function check_installed(conditions) { // 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 = [ @@ -114,6 +115,7 @@ add_task(async function test_missing_app_dir() { 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 = [ @@ -133,6 +135,7 @@ add_task(async function test_new_version() { 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 = [ @@ -152,6 +155,7 @@ add_task(async function test_upgrade() { 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 = [ @@ -195,6 +199,7 @@ add_task(async function test_updated() { }; 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 = [ @@ -212,6 +217,7 @@ add_task(async function test_updated() { // 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 = [ @@ -228,6 +234,7 @@ add_task(async function safe_mode_disabled() { // 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 = [ @@ -247,6 +254,7 @@ add_task(async function test_skips_additional() { 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 = [ @@ -267,6 +275,7 @@ add_task(async function test_revert() { // 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 @@ -287,6 +296,7 @@ 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 = [ @@ -304,6 +314,7 @@ add_task(async function test_reuse() { 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 = [ @@ -340,6 +351,7 @@ add_task(async function test_bad_profile_cert() { }; 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 = [ @@ -357,6 +369,7 @@ add_task(async function test_bad_profile_cert() { 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. @@ -407,6 +420,7 @@ add_task(async function test_updated_bad_update_set() { }; 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 = [ @@ -417,4 +431,3 @@ add_task(async function test_updated_bad_update_set() { await promiseShutdownManager(); }); - diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_update_blank.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_blank.js new file mode 100644 index 000000000000..6462cf6ff48e --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_blank.js @@ -0,0 +1,126 @@ +// Tests that system add-on upgrades work. + +Components.utils.import("resource://testing-common/httpd.js"); + +BootstrapMonitor.init(); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2"); + +var testserver = new HttpServer(); +testserver.registerDirectory("/data/", do_get_file("data/system_addons")); +testserver.start(); +var root = testserver.identity.primaryScheme + "://" + + testserver.identity.primaryHost + ":" + + testserver.identity.primaryPort + "/data/" +Services.prefs.setCharPref(PREF_SYSTEM_ADDON_UPDATE_URL, root + "update.xml"); + +let distroDir = FileUtils.getDir("ProfD", ["sysfeatures", "empty"], true); +registerDirectory("XREAppFeat", distroDir); +initSystemAddonDirs(); + +/** + * Defines the set of initial conditions to run each test against. Each should + * define the following properties: + * + * setup: A task to setup the profile into the initial state. + * initialState: The initial expected system add-on state after setup has run. + */ +const TEST_CONDITIONS = { + // Runs tests with no updated or default system add-ons initially installed + blank: { + setup() { + clearSystemAddonUpdatesDir(); + distroDir.leafName = "empty"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + }, + // Runs tests with default system add-ons installed + withAppSet: { + setup() { + clearSystemAddonUpdatesDir(); + distroDir.leafName = "prefilled"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, + + // Runs tests with updated system add-ons installed + withProfileSet: { + setup() { + buildPrefilledUpdatesDir(); + distroDir.leafName = "empty"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, + + // Runs tests with both default and updated system add-ons installed + withBothSets: { + setup() { + buildPrefilledUpdatesDir(); + distroDir.leafName = "hidden"; + }, + initialState: [ + { isUpgrade: false, version: "1.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, +}; + +/** + * The tests to run. Each test must define an updateList or test. The following + * properties are used: + * + * updateList: The set of add-ons the server should respond with. + * test: A function to run to perform the update check (replaces + * updateList) + * fails: An optional property, if true the update check is expected to + * fail. + * finalState: An optional property, the expected final state of system add-ons, + * if missing the test condition's initialState is used. + */ +const TESTS = { + // Test that a blank response does nothing + blank: { + updateList: null, + } +} + +add_task(async function setup() { + // Initialise the profile + awaitPromise(overrideBuiltIns({ "system": [] })); + 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); + + let setup = TEST_CONDITIONS[setupName]; + let test = TESTS[testName]; + + await execSystemAddonTest(setupName, setup, test, distroDir, root, testserver); + } + } +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_update_checkSizeHash.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_checkSizeHash.js new file mode 100644 index 000000000000..82dbfb480169 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_checkSizeHash.js @@ -0,0 +1,160 @@ +// Tests that system add-on upgrades work. + +Components.utils.import("resource://testing-common/httpd.js"); + +BootstrapMonitor.init(); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2"); + +var testserver = new HttpServer(); +testserver.registerDirectory("/data/", do_get_file("data/system_addons")); +testserver.start(); +var root = testserver.identity.primaryScheme + "://" + + testserver.identity.primaryHost + ":" + + testserver.identity.primaryPort + "/data/" +Services.prefs.setCharPref(PREF_SYSTEM_ADDON_UPDATE_URL, root + "update.xml"); + +let distroDir = FileUtils.getDir("ProfD", ["sysfeatures", "empty"], true); +registerDirectory("XREAppFeat", distroDir); +initSystemAddonDirs(); + +/** + * Defines the set of initial conditions to run each test against. Each should + * define the following properties: + * + * setup: A task to setup the profile into the initial state. + * initialState: The initial expected system add-on state after setup has run. + */ +const TEST_CONDITIONS = { + // Runs tests with no updated or default system add-ons initially installed + blank: { + setup() { + clearSystemAddonUpdatesDir(); + distroDir.leafName = "empty"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + }, + // Runs tests with default system add-ons installed + withAppSet: { + setup() { + clearSystemAddonUpdatesDir(); + distroDir.leafName = "prefilled"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, + + // Runs tests with updated system add-ons installed + withProfileSet: { + setup() { + buildPrefilledUpdatesDir(); + distroDir.leafName = "empty"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, + + // Runs tests with both default and updated system add-ons installed + withBothSets: { + setup() { + buildPrefilledUpdatesDir(); + distroDir.leafName = "hidden"; + }, + initialState: [ + { isUpgrade: false, version: "1.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, +}; + +/** + * The tests to run. Each test must define an updateList or test. The following + * properties are used: + * + * updateList: The set of add-ons the server should respond with. + * test: A function to run to perform the update check (replaces + * updateList) + * fails: An optional property, if true the update check is expected to + * fail. + * finalState: An optional property, the expected final state of system add-ons, + * if missing the test condition's initialState is used. + */ +const TESTS = { + // Correct sizes and hashes should work + checkSizeHash: { + updateList: [ + { id: "system2@tests.mozilla.org", version: "3.0", path: "system2_3.xpi", size: 4697 }, + { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi", hashFunction: "sha1", hashValue: "a4c7198d56deb315511c02937fd96c696de6cb84" }, + { id: "system5@tests.mozilla.org", version: "1.0", path: "system5_1.xpi", size: 4691, hashFunction: "sha1", hashValue: "6887b916a1a9a5338b0df4181f6187f5396861eb" } + ], + finalState: { + blank: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "1.0"} + ], + withAppSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "1.0"} + ], + withProfileSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "1.0"} + ], + withBothSets: [ + { isUpgrade: false, version: "1.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "1.0"} + ] + } + } +} + +add_task(async function setup() { + // Initialise the profile + awaitPromise(overrideBuiltIns({ "system": [] })); + 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); + + let setup = TEST_CONDITIONS[setupName]; + let test = TESTS[testName]; + + await execSystemAddonTest(setupName, setup, test, distroDir, root, testserver); + } + } +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_update.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_custom.js similarity index 55% rename from toolkit/mozapps/extensions/test/xpcshell/test_system_update.js rename to toolkit/mozapps/extensions/test/xpcshell/test_system_update_custom.js index ec507c4e121e..f7575a7813fc 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_system_update.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_custom.js @@ -86,236 +86,6 @@ const TEST_CONDITIONS = { }, }; - -/** - * The tests to run. Each test must define an updateList or test. The following - * properties are used: - * - * updateList: The set of add-ons the server should respond with. - * test: A function to run to perform the update check (replaces - * updateList) - * fails: An optional property, if true the update check is expected to - * fail. - * finalState: An optional property, the expected final state of system add-ons, - * if missing the test condition's initialState is used. - */ -const TESTS = { - // Test that a blank response does nothing - blank: { - updateList: null, - }, - - // Test that an empty list removes existing updates, leaving defaults. - empty: { - updateList: [], - finalState: { - blank: [ - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ], - withAppSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: false, version: "2.0"}, - { isUpgrade: false, version: "2.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ], - withProfileSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ], - withBothSets: [ - { isUpgrade: false, version: "1.0"}, - { isUpgrade: false, version: "1.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - // Set this to `true` to so `verifySystemAddonState()` expects a blank profile dir - { isUpgrade: true, version: null} - ] - }, - }, - // Tests that a new set of system add-ons gets installed - newset: { - updateList: [ - { id: "system4@tests.mozilla.org", version: "1.0", path: "system4_1.xpi" }, - { id: "system5@tests.mozilla.org", version: "1.0", path: "system5_1.xpi" } - ], - finalState: { - blank: [ - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: true, version: "1.0"} - ], - withAppSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: false, version: "2.0"}, - { isUpgrade: false, version: "2.0"}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: true, version: "1.0"} - ], - withProfileSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: true, version: "1.0"} - ], - withBothSets: [ - { isUpgrade: false, version: "1.0"}, - { isUpgrade: false, version: "1.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: true, version: "1.0"} - ] - } - }, - - // Tests that an upgraded set of system add-ons gets installed - upgrades: { - updateList: [ - { id: "system2@tests.mozilla.org", version: "3.0", path: "system2_3.xpi" }, - { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi" } - ], - finalState: { - blank: [ - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ], - withAppSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ], - withProfileSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ], - withBothSets: [ - { isUpgrade: false, version: "1.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: false, version: null} - ] - } - }, - - // Tests that a set of system add-ons, some new, some existing gets installed - overlapping: { - updateList: [ - { id: "system1@tests.mozilla.org", version: "2.0", path: "system1_2.xpi" }, - { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, - { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi" }, - { id: "system4@tests.mozilla.org", version: "1.0", path: "system4_1.xpi" } - ], - finalState: { - blank: [ - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: false, version: null} - ], - withAppSet: [ - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: false, version: null} - ], - withProfileSet: [ - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: false, version: null} - ], - withBothSets: [ - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "2.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "1.0"}, - { isUpgrade: false, version: null} - ] - } - }, - - // Correct sizes and hashes should work - checkSizeHash: { - updateList: [ - { id: "system2@tests.mozilla.org", version: "3.0", path: "system2_3.xpi", size: 4697 }, - { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi", hashFunction: "sha1", hashValue: "a4c7198d56deb315511c02937fd96c696de6cb84" }, - { id: "system5@tests.mozilla.org", version: "1.0", path: "system5_1.xpi", size: 4691, hashFunction: "sha1", hashValue: "6887b916a1a9a5338b0df4181f6187f5396861eb" } - ], - finalState: { - blank: [ - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "1.0"} - ], - withAppSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "1.0"} - ], - withProfileSet: [ - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "1.0"} - ], - withBothSets: [ - { isUpgrade: false, version: "1.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: true, version: "3.0"}, - { isUpgrade: false, version: null}, - { isUpgrade: true, version: "1.0"} - ] - } - } -} - -add_task(async function setup() { - // Initialise the profile - 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); - - let setup = TEST_CONDITIONS[setupName]; - let test = TESTS[testName]; - - await execSystemAddonTest(setupName, setup, test, distroDir, root, testserver); - } - } -}); - -// Some custom tests // Test that the update check is performed as part of the regular add-on update // check add_task(async function test_addon_update() { diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_update_empty.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_empty.js new file mode 100644 index 000000000000..eb800730fd3f --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_empty.js @@ -0,0 +1,150 @@ +// Tests that system add-on upgrades work. + +Components.utils.import("resource://testing-common/httpd.js"); + +BootstrapMonitor.init(); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2"); + +var testserver = new HttpServer(); +testserver.registerDirectory("/data/", do_get_file("data/system_addons")); +testserver.start(); +var root = testserver.identity.primaryScheme + "://" + + testserver.identity.primaryHost + ":" + + testserver.identity.primaryPort + "/data/" +Services.prefs.setCharPref(PREF_SYSTEM_ADDON_UPDATE_URL, root + "update.xml"); + +let distroDir = FileUtils.getDir("ProfD", ["sysfeatures", "empty"], true); +registerDirectory("XREAppFeat", distroDir); +initSystemAddonDirs(); + +/** + * Defines the set of initial conditions to run each test against. Each should + * define the following properties: + * + * setup: A task to setup the profile into the initial state. + * initialState: The initial expected system add-on state after setup has run. + */ +const TEST_CONDITIONS = { + // Runs tests with no updated or default system add-ons initially installed + blank: { + setup() { + clearSystemAddonUpdatesDir(); + distroDir.leafName = "empty"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + }, + // Runs tests with default system add-ons installed + withAppSet: { + setup() { + clearSystemAddonUpdatesDir(); + distroDir.leafName = "prefilled"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, + + // Runs tests with updated system add-ons installed + withProfileSet: { + setup() { + buildPrefilledUpdatesDir(); + distroDir.leafName = "empty"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, + + // Runs tests with both default and updated system add-ons installed + withBothSets: { + setup() { + buildPrefilledUpdatesDir(); + distroDir.leafName = "hidden"; + }, + initialState: [ + { isUpgrade: false, version: "1.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, +}; + +/** + * The tests to run. Each test must define an updateList or test. The following + * properties are used: + * + * updateList: The set of add-ons the server should respond with. + * test: A function to run to perform the update check (replaces + * updateList) + * fails: An optional property, if true the update check is expected to + * fail. + * finalState: An optional property, the expected final state of system add-ons, + * if missing the test condition's initialState is used. + */ +const TESTS = { + // Test that an empty list removes existing updates, leaving defaults. + empty: { + updateList: [], + finalState: { + blank: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + withAppSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + withProfileSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + withBothSets: [ + { isUpgrade: false, version: "1.0"}, + { isUpgrade: false, version: "1.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + // Set this to `true` to so `verifySystemAddonState()` expects a blank profile dir + { isUpgrade: true, version: null} + ] + } + } +} + +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); + + let setup = TEST_CONDITIONS[setupName]; + let test = TESTS[testName]; + + await execSystemAddonTest(setupName, setup, test, distroDir, root, testserver); + } + } +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_update_fail.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_fail.js index 55e20044a1ca..683ccac14a6f 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_system_update_fail.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_fail.js @@ -86,7 +86,6 @@ const TEST_CONDITIONS = { }, }; - /** * The tests to run. Each test must define an updateList or test. The following * properties are used: @@ -166,6 +165,7 @@ const TESTS = { add_task(async function setup() { // Initialise the profile + await overrideBuiltIns({ "system": [] }); startupManager(); await promiseShutdownManager(); }); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_update_newset.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_newset.js new file mode 100644 index 000000000000..bb1a252e05c5 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_newset.js @@ -0,0 +1,159 @@ +// Tests that system add-on upgrades work. + +Components.utils.import("resource://testing-common/httpd.js"); + +BootstrapMonitor.init(); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2"); + +var testserver = new HttpServer(); +testserver.registerDirectory("/data/", do_get_file("data/system_addons")); +testserver.start(); +var root = testserver.identity.primaryScheme + "://" + + testserver.identity.primaryHost + ":" + + testserver.identity.primaryPort + "/data/" +Services.prefs.setCharPref(PREF_SYSTEM_ADDON_UPDATE_URL, root + "update.xml"); + +let distroDir = FileUtils.getDir("ProfD", ["sysfeatures", "empty"], true); +registerDirectory("XREAppFeat", distroDir); +initSystemAddonDirs(); + +/** + * Defines the set of initial conditions to run each test against. Each should + * define the following properties: + * + * setup: A task to setup the profile into the initial state. + * initialState: The initial expected system add-on state after setup has run. + */ +const TEST_CONDITIONS = { + // Runs tests with no updated or default system add-ons initially installed + blank: { + setup() { + clearSystemAddonUpdatesDir(); + distroDir.leafName = "empty"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + }, + // Runs tests with default system add-ons installed + withAppSet: { + setup() { + clearSystemAddonUpdatesDir(); + distroDir.leafName = "prefilled"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, + + // Runs tests with updated system add-ons installed + withProfileSet: { + setup() { + buildPrefilledUpdatesDir(); + distroDir.leafName = "empty"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, + + // Runs tests with both default and updated system add-ons installed + withBothSets: { + setup() { + buildPrefilledUpdatesDir(); + distroDir.leafName = "hidden"; + }, + initialState: [ + { isUpgrade: false, version: "1.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, +}; + +/** + * The tests to run. Each test must define an updateList or test. The following + * properties are used: + * + * updateList: The set of add-ons the server should respond with. + * test: A function to run to perform the update check (replaces + * updateList) + * fails: An optional property, if true the update check is expected to + * fail. + * finalState: An optional property, the expected final state of system add-ons, + * if missing the test condition's initialState is used. + */ +const TESTS = { + // Tests that a new set of system add-ons gets installed + newset: { + updateList: [ + { id: "system4@tests.mozilla.org", version: "1.0", path: "system4_1.xpi" }, + { id: "system5@tests.mozilla.org", version: "1.0", path: "system5_1.xpi" } + ], + finalState: { + blank: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: true, version: "1.0"} + ], + withAppSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: true, version: "1.0"} + ], + withProfileSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: true, version: "1.0"} + ], + withBothSets: [ + { isUpgrade: false, version: "1.0"}, + { isUpgrade: false, version: "1.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: true, version: "1.0"} + ] + } + } +} + +add_task(async function setup() { + // Initialise the profile + awaitPromise(overrideBuiltIns({ "system": [] })); + 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); + + let setup = TEST_CONDITIONS[setupName]; + let test = TESTS[testName]; + + await execSystemAddonTest(setupName, setup, test, distroDir, root, testserver); + } + } +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_update_overlapping.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_overlapping.js new file mode 100644 index 000000000000..7b347fe25c98 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_overlapping.js @@ -0,0 +1,161 @@ +// Tests that system add-on upgrades work. + +Components.utils.import("resource://testing-common/httpd.js"); + +BootstrapMonitor.init(); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2"); + +var testserver = new HttpServer(); +testserver.registerDirectory("/data/", do_get_file("data/system_addons")); +testserver.start(); +var root = testserver.identity.primaryScheme + "://" + + testserver.identity.primaryHost + ":" + + testserver.identity.primaryPort + "/data/" +Services.prefs.setCharPref(PREF_SYSTEM_ADDON_UPDATE_URL, root + "update.xml"); + +let distroDir = FileUtils.getDir("ProfD", ["sysfeatures", "empty"], true); +registerDirectory("XREAppFeat", distroDir); +initSystemAddonDirs(); + +/** + * Defines the set of initial conditions to run each test against. Each should + * define the following properties: + * + * setup: A task to setup the profile into the initial state. + * initialState: The initial expected system add-on state after setup has run. + */ +const TEST_CONDITIONS = { + // Runs tests with no updated or default system add-ons initially installed + blank: { + setup() { + clearSystemAddonUpdatesDir(); + distroDir.leafName = "empty"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + }, + // Runs tests with default system add-ons installed + withAppSet: { + setup() { + clearSystemAddonUpdatesDir(); + distroDir.leafName = "prefilled"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, + + // Runs tests with updated system add-ons installed + withProfileSet: { + setup() { + buildPrefilledUpdatesDir(); + distroDir.leafName = "empty"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, + + // Runs tests with both default and updated system add-ons installed + withBothSets: { + setup() { + buildPrefilledUpdatesDir(); + distroDir.leafName = "hidden"; + }, + initialState: [ + { isUpgrade: false, version: "1.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, +}; + +/** + * The tests to run. Each test must define an updateList or test. The following + * properties are used: + * + * updateList: The set of add-ons the server should respond with. + * test: A function to run to perform the update check (replaces + * updateList) + * fails: An optional property, if true the update check is expected to + * fail. + * finalState: An optional property, the expected final state of system add-ons, + * if missing the test condition's initialState is used. + */ +const TESTS = { + // Tests that a set of system add-ons, some new, some existing gets installed + overlapping: { + updateList: [ + { id: "system1@tests.mozilla.org", version: "2.0", path: "system1_2.xpi" }, + { id: "system2@tests.mozilla.org", version: "2.0", path: "system2_2.xpi" }, + { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi" }, + { id: "system4@tests.mozilla.org", version: "1.0", path: "system4_1.xpi" } + ], + finalState: { + blank: [ + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: false, version: null} + ], + withAppSet: [ + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: false, version: null} + ], + withProfileSet: [ + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: false, version: null} + ], + withBothSets: [ + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "1.0"}, + { isUpgrade: false, version: null} + ] + } + } +} + +add_task(async function setup() { + // Initialise the profile + awaitPromise(overrideBuiltIns({ "system": [] })); + 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); + + let setup = TEST_CONDITIONS[setupName]; + let test = TESTS[testName]; + + await execSystemAddonTest(setupName, setup, test, distroDir, root, testserver); + } + } +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_system_update_upgrades.js b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_upgrades.js new file mode 100644 index 000000000000..31463bcf5236 --- /dev/null +++ b/toolkit/mozapps/extensions/test/xpcshell/test_system_update_upgrades.js @@ -0,0 +1,159 @@ +// Tests that system add-on upgrades work. + +Components.utils.import("resource://testing-common/httpd.js"); + +BootstrapMonitor.init(); + +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "2"); + +var testserver = new HttpServer(); +testserver.registerDirectory("/data/", do_get_file("data/system_addons")); +testserver.start(); +var root = testserver.identity.primaryScheme + "://" + + testserver.identity.primaryHost + ":" + + testserver.identity.primaryPort + "/data/" +Services.prefs.setCharPref(PREF_SYSTEM_ADDON_UPDATE_URL, root + "update.xml"); + +let distroDir = FileUtils.getDir("ProfD", ["sysfeatures", "empty"], true); +registerDirectory("XREAppFeat", distroDir); +initSystemAddonDirs(); + +/** + * Defines the set of initial conditions to run each test against. Each should + * define the following properties: + * + * setup: A task to setup the profile into the initial state. + * initialState: The initial expected system add-on state after setup has run. + */ +const TEST_CONDITIONS = { + // Runs tests with no updated or default system add-ons initially installed + blank: { + setup() { + clearSystemAddonUpdatesDir(); + distroDir.leafName = "empty"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + }, + // Runs tests with default system add-ons installed + withAppSet: { + setup() { + clearSystemAddonUpdatesDir(); + distroDir.leafName = "prefilled"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, + + // Runs tests with updated system add-ons installed + withProfileSet: { + setup() { + buildPrefilledUpdatesDir(); + distroDir.leafName = "empty"; + }, + initialState: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, + + // Runs tests with both default and updated system add-ons installed + withBothSets: { + setup() { + buildPrefilledUpdatesDir(); + distroDir.leafName = "hidden"; + }, + initialState: [ + { isUpgrade: false, version: "1.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: true, version: "2.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + }, +}; + +/** + * The tests to run. Each test must define an updateList or test. The following + * properties are used: + * + * updateList: The set of add-ons the server should respond with. + * test: A function to run to perform the update check (replaces + * updateList) + * fails: An optional property, if true the update check is expected to + * fail. + * finalState: An optional property, the expected final state of system add-ons, + * if missing the test condition's initialState is used. + */ +const TESTS = { + // Tests that an upgraded set of system add-ons gets installed + upgrades: { + updateList: [ + { id: "system2@tests.mozilla.org", version: "3.0", path: "system2_3.xpi" }, + { id: "system3@tests.mozilla.org", version: "3.0", path: "system3_3.xpi" } + ], + finalState: { + blank: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + withAppSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + withProfileSet: [ + { isUpgrade: false, version: null}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ], + withBothSets: [ + { isUpgrade: false, version: "1.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: true, version: "3.0"}, + { isUpgrade: false, version: null}, + { isUpgrade: false, version: null} + ] + } + } +} + +add_task(async function setup() { + // Initialise the profile + awaitPromise(overrideBuiltIns({ "system": [] })); + 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); + + let setup = TEST_CONDITIONS[setupName]; + let test = TESTS[testName]; + + await execSystemAddonTest(setupName, setup, test, distroDir, root, testserver); + } + } +}); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_update.js b/toolkit/mozapps/extensions/test/xpcshell/test_update.js index afffe38da270..3897b7254c15 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_update.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_update.js @@ -1359,12 +1359,14 @@ function check_test_7_cache() { // Test that the update check returns nothing for addons in locked install // locations. -add_test(function run_test_locked_install() { +add_test(async function run_test_locked_install() { const lockedDir = gProfD.clone(); lockedDir.append("locked_extensions"); registerDirectory("XREAppFeat", lockedDir); - restartManager(); - writeInstallRDFForExtension({ + + await promiseShutdownManager(); + + writeInstallRDFToXPI({ id: "addon13@tests.mozilla.org", version: "1.0", updateURL: "http://localhost:" + gPort + "/data/test_update.rdf", @@ -1375,7 +1377,11 @@ add_test(function run_test_locked_install() { }], name: "Test Addon 13", }, lockedDir); - restartManager(); + + let validAddons = { "system": ["addon13@tests.mozilla.org"] }; + await overrideBuiltIns(validAddons); + + await promiseStartupManager(); AddonManager.getAddonByID("addon13@tests.mozilla.org", function(a13) { do_check_neq(a13, null); diff --git a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini index 07ef8e6d8624..73ef9601e958 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini +++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini @@ -30,8 +30,15 @@ tags = blocklist [test_provider_unsafe_access_startup.js] [test_ProductAddonChecker.js] [test_shutdown.js] -[test_system_update.js] +[test_system_update_blank.js] +[test_system_update_checkSizeHash.js] +[test_system_update_custom.js] +[test_system_update_empty.js] +skip-if = os == "linux" # Failing intermittently due to a race condition in the test, see bug 1348981 [test_system_update_fail.js] +[test_system_update_newset.js] +[test_system_update_overlapping.js] +[test_system_update_upgrades.js] [test_system_repository.js] [test_system_reset.js] [test_XPIcancel.js] @@ -51,5 +58,6 @@ tags = webextensions [test_system_delay_update.js] [test_schema_change.js] [test_registerchrome.js] +[test_system_allowed.js] [include:xpcshell-shared.ini]