summaryrefslogtreecommitdiffstats
path: root/browser/components/enterprisepolicies/tests/xpcshell
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/enterprisepolicies/tests/xpcshell')
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/config_popups_cookies_addons.json17
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/head.js150
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/policytest_v0.1.xpibin0 -> 305 bytes
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_3rdparty.js22
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_addon_update.js156
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_appupdatepin.js80
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_appupdateurl.js25
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_bug1658259.js44
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_cleanup.js84
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_clear_blocked_cookies.js118
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_containers.js37
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_defaultbrowsercheck.js52
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_empty_policy.js32
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_exempt_domain_file_type_pairs_from_file_type_download_warnings.js66
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_extensions.js83
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_extensionsettings.js291
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_macosparser_unflatten.js110
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_permissions.js355
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_policy_search_engine.js490
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_popups_cookies_addons.js121
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_preferences.js257
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_proxy.js122
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_requestedlocales.js119
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_runOnce_helper.js21
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_simple_pref_policies.js1055
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_sorted_alphabetically.js48
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/test_telemetry.js102
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/xpcshell.toml55
28 files changed, 4112 insertions, 0 deletions
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/config_popups_cookies_addons.json b/browser/components/enterprisepolicies/tests/xpcshell/config_popups_cookies_addons.json
new file mode 100644
index 0000000000..256358b204
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/config_popups_cookies_addons.json
@@ -0,0 +1,17 @@
+{
+ "policies": {
+ "PopupBlocking": {
+ "Allow": ["https://www.allow.com", "https://www.pre-existing-deny.com"]
+ },
+
+ "Cookies": {
+ "Allow": ["https://www.allow.com", "https://www.pre-existing-deny.com"],
+
+ "Block": ["https://www.deny.com", "https://www.pre-existing-allow.com"]
+ },
+
+ "InstallAddonsPermission": {
+ "Allow": ["https://www.allow.com", "https://www.pre-existing-deny.com"]
+ }
+ }
+}
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/head.js b/browser/components/enterprisepolicies/tests/xpcshell/head.js
new file mode 100644
index 0000000000..8b81261538
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/head.js
@@ -0,0 +1,150 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const lazy = {};
+
+const { Preferences } = ChromeUtils.importESModule(
+ "resource://gre/modules/Preferences.sys.mjs"
+);
+const { SearchSettings } = ChromeUtils.importESModule(
+ "resource://gre/modules/SearchSettings.sys.mjs"
+);
+const { updateAppInfo, getAppInfo } = ChromeUtils.importESModule(
+ "resource://testing-common/AppInfo.sys.mjs"
+);
+const { FileTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/FileTestUtils.sys.mjs"
+);
+const { PermissionTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/PermissionTestUtils.sys.mjs"
+);
+ChromeUtils.defineESModuleGetters(lazy, {
+ SearchTestUtils: "resource://testing-common/SearchTestUtils.sys.mjs",
+});
+const { EnterprisePolicyTesting } = ChromeUtils.importESModule(
+ "resource://testing-common/EnterprisePolicyTesting.sys.mjs"
+);
+
+updateAppInfo({
+ name: "XPCShell",
+ ID: "xpcshell@tests.mozilla.org",
+ version: "48",
+ platformVersion: "48",
+});
+
+// This initializes the policy engine for xpcshell tests
+let policies = Cc["@mozilla.org/enterprisepolicies;1"].getService(
+ Ci.nsIObserver
+);
+policies.observe(null, "policies-startup", null);
+
+SearchSettings.SETTINGS_INVALIDATION_DELAY = 100;
+
+async function setupPolicyEngineWithJson(json, customSchema) {
+ if (typeof json != "object") {
+ let filePath = do_get_file(json ? json : "non-existing-file.json").path;
+ return EnterprisePolicyTesting.setupPolicyEngineWithJson(
+ filePath,
+ customSchema
+ );
+ }
+ return EnterprisePolicyTesting.setupPolicyEngineWithJson(json, customSchema);
+}
+
+/**
+ * Loads a new enterprise policy, and re-initialise the search service
+ * with the new policy. Also waits for the search service to write the settings
+ * file to disk.
+ *
+ * @param {object} json
+ * The enterprise policy to use.
+ * @param {object} customSchema
+ * A custom schema to use to validate the enterprise policy.
+ */
+async function setupPolicyEngineWithJsonWithSearch(json, customSchema) {
+ Services.search.wrappedJSObject.reset();
+ if (typeof json != "object") {
+ let filePath = do_get_file(json ? json : "non-existing-file.json").path;
+ await EnterprisePolicyTesting.setupPolicyEngineWithJson(
+ filePath,
+ customSchema
+ );
+ } else {
+ await EnterprisePolicyTesting.setupPolicyEngineWithJson(json, customSchema);
+ }
+ let settingsWritten = lazy.SearchTestUtils.promiseSearchNotification(
+ "write-settings-to-disk-complete"
+ );
+ await Services.search.init();
+ return settingsWritten;
+}
+
+function checkLockedPref(prefName, prefValue) {
+ equal(
+ Preferences.locked(prefName),
+ true,
+ `Pref ${prefName} is correctly locked`
+ );
+ strictEqual(
+ Preferences.get(prefName),
+ prefValue,
+ `Pref ${prefName} has the correct value`
+ );
+}
+
+function checkUnlockedPref(prefName, prefValue) {
+ equal(
+ Preferences.locked(prefName),
+ false,
+ `Pref ${prefName} is correctly unlocked`
+ );
+ strictEqual(
+ Preferences.get(prefName),
+ prefValue,
+ `Pref ${prefName} has the correct value`
+ );
+}
+
+function checkUserPref(prefName, prefValue) {
+ strictEqual(
+ Preferences.get(prefName),
+ prefValue,
+ `Pref ${prefName} has the correct value`
+ );
+}
+
+function checkClearPref(prefName, prefValue) {
+ equal(
+ Services.prefs.prefHasUserValue(prefName),
+ false,
+ `Pref ${prefName} has no user value`
+ );
+}
+
+function checkDefaultPref(prefName, prefValue) {
+ let defaultPrefBranch = Services.prefs.getDefaultBranch("");
+ let prefType = defaultPrefBranch.getPrefType(prefName);
+ notEqual(
+ prefType,
+ Services.prefs.PREF_INVALID,
+ `Pref ${prefName} is set on the default branch`
+ );
+ strictEqual(
+ Preferences.get(prefName),
+ prefValue,
+ `Pref ${prefName} has the correct value`
+ );
+}
+
+function checkUnsetPref(prefName) {
+ let defaultPrefBranch = Services.prefs.getDefaultBranch("");
+ let prefType = defaultPrefBranch.getPrefType(prefName);
+ equal(
+ prefType,
+ Services.prefs.PREF_INVALID,
+ `Pref ${prefName} is not set on the default branch`
+ );
+}
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/policytest_v0.1.xpi b/browser/components/enterprisepolicies/tests/xpcshell/policytest_v0.1.xpi
new file mode 100644
index 0000000000..ee2a6289ee
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/policytest_v0.1.xpi
Binary files differ
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_3rdparty.js b/browser/components/enterprisepolicies/tests/xpcshell/test_3rdparty.js
new file mode 100644
index 0000000000..0f53cc80c9
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_3rdparty.js
@@ -0,0 +1,22 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+add_task(async function setup() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ "3rdparty": {
+ Extensions: {
+ "3rdparty-policy@mozilla.com": {
+ string: "value",
+ },
+ },
+ },
+ },
+ });
+
+ let extensionPolicy = Services.policies.getExtensionPolicy(
+ "3rdparty-policy@mozilla.com"
+ );
+ deepEqual(extensionPolicy, { string: "value" });
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_addon_update.js b/browser/components/enterprisepolicies/tests/xpcshell/test_addon_update.js
new file mode 100644
index 0000000000..0133aa3a40
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_addon_update.js
@@ -0,0 +1,156 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const { AddonTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/AddonTestUtils.sys.mjs"
+);
+const { AddonManager } = ChromeUtils.importESModule(
+ "resource://gre/modules/AddonManager.sys.mjs"
+);
+const { ExtensionTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/ExtensionXPCShellUtils.sys.mjs"
+);
+
+AddonTestUtils.init(this);
+AddonTestUtils.overrideCertDB();
+AddonTestUtils.appInfo = getAppInfo();
+ExtensionTestUtils.init(this);
+
+const server = AddonTestUtils.createHttpServer({ hosts: ["example.com"] });
+const BASE_URL = `http://example.com/data`;
+
+let TEST_NAME = "updatable.xpi";
+
+/* Test that when a local file addon is updated,
+ the new version gets installed. */
+add_task(async function test_local_addon_update() {
+ await AddonTestUtils.promiseStartupManager();
+
+ let tmpDir = Services.dirsvc.get("TmpD", Ci.nsIFile);
+ let id = "updatable1@test";
+ let xpi1 = AddonTestUtils.createTempWebExtensionFile({
+ manifest: {
+ version: "1.0",
+ browser_specific_settings: {
+ gecko: { id },
+ },
+ },
+ });
+ xpi1.copyTo(tmpDir, TEST_NAME);
+ let extension = ExtensionTestUtils.expectExtension(id);
+ await Promise.all([
+ extension.awaitStartup(),
+ setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "updatable1@test": {
+ installation_mode: "force_installed",
+ install_url: Services.io.newFileURI(tmpDir).spec + "/" + TEST_NAME,
+ },
+ },
+ },
+ }),
+ ]);
+ let addon = await AddonManager.getAddonByID(id);
+ notEqual(addon, null, "Addon should not be null");
+ equal(addon.version, "1.0", "Addon 1.0 installed");
+
+ let xpi2 = AddonTestUtils.createTempWebExtensionFile({
+ manifest: {
+ version: "2.0",
+ browser_specific_settings: {
+ gecko: { id },
+ },
+ },
+ });
+ // overwrite the test file
+ xpi2.copyTo(tmpDir, TEST_NAME);
+
+ extension = ExtensionTestUtils.expectExtension(id);
+ await Promise.all([
+ extension.awaitStartup(),
+ setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "updatable1@test": {
+ installation_mode: "force_installed",
+ install_url: Services.io.newFileURI(tmpDir).spec + "/" + TEST_NAME,
+ },
+ },
+ },
+ }),
+ ]);
+
+ addon = await AddonManager.getAddonByID(id);
+ equal(addon.version, "2.0", "Addon 2.0 installed");
+
+ let xpifile = tmpDir.clone();
+ xpifile.append(TEST_NAME);
+ xpifile.remove(false);
+});
+
+/* Test that when the url changes,
+ the new version gets installed. */
+add_task(async function test_newurl_addon_update() {
+ let id = "updatable2@test";
+
+ let xpi1 = AddonTestUtils.createTempWebExtensionFile({
+ manifest: {
+ version: "1.0",
+ browser_specific_settings: {
+ gecko: { id },
+ },
+ },
+ });
+ server.registerFile("/data/policy_test1.xpi", xpi1);
+
+ let xpi2 = AddonTestUtils.createTempWebExtensionFile({
+ manifest: {
+ version: "2.0",
+ browser_specific_settings: {
+ gecko: { id },
+ },
+ },
+ });
+ server.registerFile("/data/policy_test2.xpi", xpi2);
+
+ let extension = ExtensionTestUtils.expectExtension(id);
+ await Promise.all([
+ extension.awaitStartup(),
+ setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "updatable2@test": {
+ installation_mode: "force_installed",
+ install_url: `${BASE_URL}/policy_test1.xpi`,
+ },
+ },
+ },
+ }),
+ ]);
+ let addon = await AddonManager.getAddonByID(id);
+ notEqual(addon, null, "Addon should not be null");
+ equal(addon.version, "1.0", "Addon 1.0 installed");
+
+ extension = ExtensionTestUtils.expectExtension(id);
+ await Promise.all([
+ extension.awaitStartup(),
+ setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "updatable2@test": {
+ installation_mode: "force_installed",
+ install_url: `${BASE_URL}/policy_test2.xpi`,
+ },
+ },
+ },
+ }),
+ ]);
+
+ addon = await AddonManager.getAddonByID(id);
+ equal(addon.version, "2.0", "Addon 2.0 installed");
+
+ await AddonTestUtils.promiseShutdownManager();
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_appupdatepin.js b/browser/components/enterprisepolicies/tests/xpcshell/test_appupdatepin.js
new file mode 100644
index 0000000000..6be2aa0b50
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_appupdatepin.js
@@ -0,0 +1,80 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const { TelemetryTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/TelemetryTestUtils.sys.mjs"
+);
+
+/**
+ * Note that these tests only ensure that the pin is properly added to the
+ * update URL and to the telemetry. They do not test that the update applied
+ * will be of the correct version. This is because we are not attempting to have
+ * Firefox check if the update provided is valid given the pin, we are leaving
+ * it to the update server (Balrog) to find and serve the correct version.
+ */
+
+async function test_update_pin(pinString, pinIsValid = true) {
+ await setupPolicyEngineWithJson({
+ policies: {
+ AppUpdateURL: "https://www.example.com/update.xml",
+ AppUpdatePin: pinString,
+ },
+ });
+ Services.telemetry.clearScalars();
+
+ equal(
+ Services.policies.status,
+ Ci.nsIEnterprisePolicies.ACTIVE,
+ "Engine is active"
+ );
+
+ let policies = Services.policies.getActivePolicies();
+ equal(
+ "AppUpdatePin" in policies,
+ pinIsValid,
+ "AppUpdatePin policy should only be active if the pin was valid."
+ );
+
+ let checker = Cc["@mozilla.org/updates/update-checker;1"].getService(
+ Ci.nsIUpdateChecker
+ );
+ let updateURL = await checker.getUpdateURL(checker.BACKGROUND_CHECK);
+
+ let expected = pinIsValid
+ ? `https://www.example.com/update.xml?pin=${pinString}`
+ : "https://www.example.com/update.xml";
+
+ equal(updateURL, expected, "App Update URL should match expected URL.");
+
+ let scalars = TelemetryTestUtils.getProcessScalars("parent", false, true);
+ if (pinIsValid) {
+ TelemetryTestUtils.assertScalar(
+ scalars,
+ "update.version_pin",
+ pinString,
+ "Update pin telemetry should be set"
+ );
+ } else {
+ TelemetryTestUtils.assertScalarUnset(scalars, "update.version_pin");
+ }
+}
+
+add_task(async function test_app_update_pin() {
+ await test_update_pin("102.");
+ await test_update_pin("102.0.");
+ await test_update_pin("102.1.");
+ await test_update_pin("102.1.1", false);
+ await test_update_pin("102.1.1.", false);
+ await test_update_pin("102", false);
+ await test_update_pin("foobar", false);
+ await test_update_pin("-102.1.", false);
+ await test_update_pin("102.-1.", false);
+ await test_update_pin("102a.1.", false);
+ await test_update_pin("102.1a.", false);
+ await test_update_pin("0102.1.", false);
+ // Should not accept version numbers that will never be in Balrog's pinning
+ // table (i.e. versions before 102.0).
+ await test_update_pin("101.1.", false);
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_appupdateurl.js b/browser/components/enterprisepolicies/tests/xpcshell/test_appupdateurl.js
new file mode 100644
index 0000000000..48d04e1a8d
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_appupdateurl.js
@@ -0,0 +1,25 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_app_update_URL() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ AppUpdateURL: "https://www.example.com/",
+ },
+ });
+
+ equal(
+ Services.policies.status,
+ Ci.nsIEnterprisePolicies.ACTIVE,
+ "Engine is active"
+ );
+
+ let checker = Cc["@mozilla.org/updates/update-checker;1"].getService(
+ Ci.nsIUpdateChecker
+ );
+ let expected = await checker.getUpdateURL(checker.BACKGROUND_CHECK);
+
+ equal("https://www.example.com/", expected, "Correct app update URL");
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_bug1658259.js b/browser/components/enterprisepolicies/tests/xpcshell/test_bug1658259.js
new file mode 100644
index 0000000000..1449e664c2
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_bug1658259.js
@@ -0,0 +1,44 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_bug1658259_1() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ OfferToSaveLogins: false,
+ OfferToSaveLoginsDefault: true,
+ },
+ });
+ checkLockedPref("signon.rememberSignons", false);
+});
+
+add_task(async function test_bug1658259_2() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ OfferToSaveLogins: true,
+ OfferToSaveLoginsDefault: false,
+ },
+ });
+ checkLockedPref("signon.rememberSignons", true);
+});
+
+add_task(async function test_bug1658259_3() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ OfferToSaveLoginsDefault: true,
+ OfferToSaveLogins: false,
+ },
+ });
+ checkLockedPref("signon.rememberSignons", false);
+});
+
+add_task(async function test_bug1658259_4() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ OfferToSaveLoginsDefault: false,
+ OfferToSaveLogins: true,
+ },
+ });
+ checkLockedPref("signon.rememberSignons", true);
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_cleanup.js b/browser/components/enterprisepolicies/tests/xpcshell/test_cleanup.js
new file mode 100644
index 0000000000..4171987cbb
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_cleanup.js
@@ -0,0 +1,84 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+async function checkMessages(expectedResult) {
+ let onBeforeAddons = false;
+ let onProfileAfterChange = false;
+ let onBeforeUIStartup = false;
+ let onAllWindowsRestored = false;
+
+ let errorListener = {
+ observe(subject) {
+ let message = subject.wrappedJSObject.arguments[0];
+ if (message.includes("_cleanup from onBeforeAddons")) {
+ onBeforeAddons = true;
+ } else if (message.includes("_cleanup from onProfileAfterChange")) {
+ onProfileAfterChange = true;
+ } else if (message.includes("_cleanup from onBeforeUIStartup")) {
+ onBeforeUIStartup = true;
+ } else if (message.includes("_cleanup from onAllWindowsRestored")) {
+ onAllWindowsRestored = true;
+ }
+ },
+ };
+
+ Services.console.registerListener(errorListener);
+
+ const ConsoleAPIStorage = Cc["@mozilla.org/consoleAPI-storage;1"].getService(
+ Ci.nsIConsoleAPIStorage
+ );
+ ConsoleAPIStorage.addLogEventListener(
+ errorListener.observe,
+ Cc["@mozilla.org/systemprincipal;1"].createInstance(Ci.nsIPrincipal)
+ );
+
+ await setupPolicyEngineWithJson({
+ policies: {},
+ });
+
+ equal(
+ onBeforeAddons,
+ expectedResult,
+ "onBeforeAddons should be " + expectedResult
+ );
+ equal(
+ onProfileAfterChange,
+ expectedResult,
+ "onProfileAfterChange should be" + expectedResult
+ );
+ equal(
+ onBeforeUIStartup,
+ expectedResult,
+ "onBeforeUIStartup should be" + expectedResult
+ );
+ equal(
+ onAllWindowsRestored,
+ expectedResult,
+ "onAllWindowsRestored should be" + expectedResult
+ );
+}
+
+/* If there is no existing policy, cleanup should not run. */
+add_task(async function test_cleanup_no_policy() {
+ await checkMessages(false);
+});
+
+add_task(async function setup_policy() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ BlockAboutConfig: true,
+ },
+ });
+});
+
+/* Since there was a policy, cleanup should run. */
+add_task(async function test_cleanup_with_policy() {
+ await checkMessages(true);
+});
+
+/* Since cleanup was already done, cleanup should not run again. */
+add_task(async function test_cleanup_after_policy() {
+ await checkMessages(false);
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_clear_blocked_cookies.js b/browser/components/enterprisepolicies/tests/xpcshell/test_clear_blocked_cookies.js
new file mode 100644
index 0000000000..571ae95a1b
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_clear_blocked_cookies.js
@@ -0,0 +1,118 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const HOSTNAME_DOMAIN = "browser_policy_clear_blocked_cookies.com";
+const ORIGIN_DOMAIN = "browser_policy_clear_blocked_cookies.org";
+
+add_task(async function setup() {
+ const expiry = Date.now() + 24 * 60 * 60;
+ Services.cookies.add(
+ HOSTNAME_DOMAIN,
+ "/",
+ "secure",
+ "true",
+ true,
+ false,
+ false,
+ expiry,
+ {},
+ Ci.nsICookie.SAMESITE_NONE,
+ Ci.nsICookie.SCHEME_HTTPS
+ );
+ Services.cookies.add(
+ HOSTNAME_DOMAIN,
+ "/",
+ "insecure",
+ "true",
+ false,
+ false,
+ false,
+ expiry,
+ {},
+ Ci.nsICookie.SAMESITE_NONE,
+ Ci.nsICookie.SCHEME_HTTP
+ );
+ Services.cookies.add(
+ ORIGIN_DOMAIN,
+ "/",
+ "secure",
+ "true",
+ true,
+ false,
+ false,
+ expiry,
+ {},
+ Ci.nsICookie.SAMESITE_NONE,
+ Ci.nsICookie.SCHEME_HTTPS
+ );
+ Services.cookies.add(
+ ORIGIN_DOMAIN,
+ "/",
+ "insecure",
+ "true",
+ false,
+ false,
+ false,
+ expiry,
+ {},
+ Ci.nsICookie.SAMESITE_NONE,
+ Ci.nsICookie.SCHEME_HTTP
+ );
+ Services.cookies.add(
+ "example.net",
+ "/",
+ "secure",
+ "true",
+ true,
+ false,
+ false,
+ expiry,
+ {},
+ Ci.nsICookie.SAMESITE_NONE,
+ Ci.nsICookie.SCHEME_HTTPS
+ );
+ await setupPolicyEngineWithJson({
+ policies: {
+ Cookies: {
+ Block: [`http://${HOSTNAME_DOMAIN}`, `https://${ORIGIN_DOMAIN}:8080`],
+ },
+ },
+ });
+});
+
+function retrieve_all_cookies(host) {
+ const values = [];
+ for (let cookie of Services.cookies.getCookiesFromHost(host, {})) {
+ values.push({
+ host: cookie.host,
+ name: cookie.name,
+ path: cookie.path,
+ });
+ }
+ return values;
+}
+
+add_task(async function test_cookies_for_blocked_sites_cleared() {
+ const cookies = {
+ hostname: retrieve_all_cookies(HOSTNAME_DOMAIN),
+ origin: retrieve_all_cookies(ORIGIN_DOMAIN),
+ keep: retrieve_all_cookies("example.net"),
+ };
+ const expected = {
+ hostname: [],
+ origin: [],
+ keep: [{ host: "example.net", name: "secure", path: "/" }],
+ };
+ equal(
+ JSON.stringify(cookies),
+ JSON.stringify(expected),
+ "All stored cookies for blocked origins should be cleared"
+ );
+});
+
+add_task(function teardown() {
+ for (let host of [HOSTNAME_DOMAIN, ORIGIN_DOMAIN, "example.net"]) {
+ Services.cookies.removeCookiesWithOriginAttributes("{}", host);
+ }
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_containers.js b/browser/components/enterprisepolicies/tests/xpcshell/test_containers.js
new file mode 100644
index 0000000000..0f6a0190ac
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_containers.js
@@ -0,0 +1,37 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ ContextualIdentityService:
+ "resource://gre/modules/ContextualIdentityService.sys.mjs",
+});
+
+add_task(async function setup() {
+ Services.prefs.setBoolPref("privacy.userContext.enabled", true);
+ do_get_profile();
+});
+
+add_task(async function test_containers_default() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Containers: {
+ Default: [
+ {
+ name: "Test Container",
+ icon: "cart",
+ color: "orange",
+ },
+ ],
+ },
+ },
+ });
+ let identities = ContextualIdentityService.getPublicIdentities();
+ equal(identities.length, 1);
+ ContextualIdentityService.getPublicIdentities().forEach(identity => {
+ equal(identity.name, "Test Container");
+ equal(identity.icon, "cart");
+ equal(identity.color, "orange");
+ });
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_defaultbrowsercheck.js b/browser/components/enterprisepolicies/tests/xpcshell/test_defaultbrowsercheck.js
new file mode 100644
index 0000000000..ff54669f4f
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_defaultbrowsercheck.js
@@ -0,0 +1,52 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+const { ShellService } = ChromeUtils.importESModule(
+ "resource:///modules/ShellService.sys.mjs"
+);
+
+add_task(async function test_default_browser_check() {
+ ShellService._checkedThisSession = false;
+ // On a normal profile, the default is true. However, this gets set to false on the
+ // testing profile. Let's start with true for a sanity check.
+
+ ShellService.shouldCheckDefaultBrowser = true;
+ equal(ShellService.shouldCheckDefaultBrowser, true, "Sanity check");
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ DontCheckDefaultBrowser: true,
+ },
+ });
+
+ equal(
+ ShellService.shouldCheckDefaultBrowser,
+ false,
+ "Policy changed it to not check"
+ );
+
+ // Try to change it to true and check that it doesn't take effect
+ ShellService.shouldCheckDefaultBrowser = true;
+
+ equal(ShellService.shouldCheckDefaultBrowser, false, "Policy is enforced");
+});
+
+add_task(async function test_default_browser_check() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DontCheckDefaultBrowser: false,
+ },
+ });
+
+ equal(
+ ShellService.shouldCheckDefaultBrowser,
+ true,
+ "Policy changed it to check"
+ );
+
+ // Try to change it to false and check that it doesn't take effect
+ ShellService.shouldCheckDefaultBrowser = false;
+
+ equal(ShellService.shouldCheckDefaultBrowser, true, "Policy is enforced");
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_empty_policy.js b/browser/components/enterprisepolicies/tests/xpcshell/test_empty_policy.js
new file mode 100644
index 0000000000..5047eeb4e0
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_empty_policy.js
@@ -0,0 +1,32 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_empty_policy() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Certificates: {},
+ },
+ });
+
+ equal(
+ Services.policies.status,
+ Ci.nsIEnterprisePolicies.INACTIVE,
+ "Engine is not active"
+ );
+});
+
+add_task(async function test_empty_array() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ RequestedLocales: [],
+ },
+ });
+
+ equal(
+ Services.policies.status,
+ Ci.nsIEnterprisePolicies.ACTIVE,
+ "Engine is active"
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_exempt_domain_file_type_pairs_from_file_type_download_warnings.js b/browser/components/enterprisepolicies/tests/xpcshell/test_exempt_domain_file_type_pairs_from_file_type_download_warnings.js
new file mode 100644
index 0000000000..5d93391ce9
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_exempt_domain_file_type_pairs_from_file_type_download_warnings.js
@@ -0,0 +1,66 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_exempt_xxx() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExemptDomainFileTypePairsFromFileTypeDownloadWarnings: [
+ {
+ file_extension: "jnlp",
+ domains: ["example.com", "www.example.edu"],
+ },
+ ],
+ },
+ });
+ equal(
+ Services.policies.isExemptExecutableExtension(
+ "https://www.example.edu",
+ "jnlp"
+ ),
+ true
+ );
+ equal(
+ Services.policies.isExemptExecutableExtension(
+ "https://example.edu",
+ "jnlp"
+ ),
+ false
+ );
+ equal(
+ Services.policies.isExemptExecutableExtension(
+ "https://example.com",
+ "jnlp"
+ ),
+ true
+ );
+ equal(
+ Services.policies.isExemptExecutableExtension(
+ "https://www.example.com",
+ "jnlp"
+ ),
+ true
+ );
+ equal(
+ Services.policies.isExemptExecutableExtension(
+ "https://wwwexample.com",
+ "jnlp"
+ ),
+ false
+ );
+ equal(
+ Services.policies.isExemptExecutableExtension(
+ "https://www.example.org",
+ "jnlp"
+ ),
+ false
+ );
+ equal(
+ Services.policies.isExemptExecutableExtension(
+ "https://www.example.edu",
+ "exe"
+ ),
+ false
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_extensions.js b/browser/components/enterprisepolicies/tests/xpcshell/test_extensions.js
new file mode 100644
index 0000000000..66cd49e004
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_extensions.js
@@ -0,0 +1,83 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const { AddonTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/AddonTestUtils.sys.mjs"
+);
+const { AddonManager } = ChromeUtils.importESModule(
+ "resource://gre/modules/AddonManager.sys.mjs"
+);
+
+AddonTestUtils.init(this);
+AddonTestUtils.overrideCertDB();
+AddonTestUtils.appInfo = getAppInfo();
+
+const server = AddonTestUtils.createHttpServer({ hosts: ["example.com"] });
+const BASE_URL = `http://example.com/data`;
+
+let addonID = "policytest2@mozilla.com";
+
+add_task(async function setup() {
+ await AddonTestUtils.promiseStartupManager();
+
+ let webExtensionFile = AddonTestUtils.createTempWebExtensionFile({
+ manifest: {
+ browser_specific_settings: {
+ gecko: {
+ id: addonID,
+ },
+ },
+ },
+ });
+
+ server.registerFile("/data/policy_test.xpi", webExtensionFile);
+});
+
+add_task(async function test_addon_forceinstalled_remote() {
+ await Promise.all([
+ AddonTestUtils.promiseInstallEvent("onInstallEnded"),
+ setupPolicyEngineWithJson({
+ policies: {
+ Extensions: {
+ Install: [BASE_URL + "/policy_test.xpi"],
+ Locked: [addonID],
+ },
+ },
+ }),
+ ]);
+ let addon = await AddonManager.getAddonByID(addonID);
+ notEqual(addon, null, "Addon should not be null");
+ equal(addon.appDisabled, false, "Addon should not be disabled");
+ equal(
+ addon.permissions & AddonManager.PERM_CAN_UNINSTALL,
+ 0,
+ "Addon should not be able to be uninstalled."
+ );
+ equal(
+ addon.permissions & AddonManager.PERM_CAN_DISABLE,
+ 0,
+ "Addon should not be able to be disabled."
+ );
+ await addon.uninstall();
+});
+
+add_task(async function test_addon_forceinstalled_local() {
+ let addonID2 = "policytest@mozilla.com";
+
+ let file = Services.dirsvc.get("CurWorkD", Ci.nsIFile);
+ file.append("policytest_v0.1.xpi");
+ await Promise.all([
+ AddonTestUtils.promiseInstallEvent("onInstallEnded"),
+ setupPolicyEngineWithJson({
+ policies: {
+ Extensions: {
+ Install: [file.path],
+ },
+ },
+ }),
+ ]);
+ let addon = await AddonManager.getAddonByID(addonID2);
+ notEqual(addon, null, "Addon should not be null");
+ await addon.uninstall();
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_extensionsettings.js b/browser/components/enterprisepolicies/tests/xpcshell/test_extensionsettings.js
new file mode 100644
index 0000000000..ee329a65f8
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_extensionsettings.js
@@ -0,0 +1,291 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const { AddonTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/AddonTestUtils.sys.mjs"
+);
+const { AddonManager } = ChromeUtils.importESModule(
+ "resource://gre/modules/AddonManager.sys.mjs"
+);
+
+AddonTestUtils.init(this);
+AddonTestUtils.overrideCertDB();
+AddonTestUtils.appInfo = getAppInfo();
+
+const server = AddonTestUtils.createHttpServer({ hosts: ["example.com"] });
+const BASE_URL = `http://example.com/data`;
+
+let addonID = "policytest2@mozilla.com";
+let themeID = "policytheme@mozilla.com";
+
+let fileURL;
+
+add_task(async function setup() {
+ await AddonTestUtils.promiseStartupManager();
+
+ let webExtensionFile = AddonTestUtils.createTempWebExtensionFile({
+ manifest: {
+ browser_specific_settings: {
+ gecko: {
+ id: addonID,
+ },
+ },
+ },
+ });
+
+ server.registerFile("/data/policy_test.xpi", webExtensionFile);
+ fileURL = Services.io
+ .newFileURI(webExtensionFile)
+ .QueryInterface(Ci.nsIFileURL);
+});
+
+add_task(async function test_extensionsettings() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "extension1@mozilla.com": {
+ blocked_install_message: "Extension1 error message.",
+ },
+ "*": {
+ blocked_install_message: "Generic error message.",
+ },
+ },
+ },
+ });
+
+ let extensionSettings = Services.policies.getExtensionSettings(
+ "extension1@mozilla.com"
+ );
+ equal(
+ extensionSettings.blocked_install_message,
+ "Extension1 error message.",
+ "Should have extension specific message."
+ );
+ extensionSettings = Services.policies.getExtensionSettings(
+ "extension2@mozilla.com"
+ );
+ equal(
+ extensionSettings.blocked_install_message,
+ "Generic error message.",
+ "Should have generic message."
+ );
+});
+
+add_task(async function test_addon_blocked() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "policytest2@mozilla.com": {
+ installation_mode: "blocked",
+ },
+ },
+ },
+ });
+
+ let install = await AddonManager.getInstallForURL(
+ BASE_URL + "/policy_test.xpi"
+ );
+ await install.install();
+ notEqual(install.addon, null, "Addon should not be null");
+ equal(install.addon.appDisabled, true, "Addon should be disabled");
+ await install.addon.uninstall();
+});
+
+add_task(async function test_addon_allowed() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "policytest2@mozilla.com": {
+ installation_mode: "allowed",
+ },
+ "*": {
+ installation_mode: "blocked",
+ },
+ },
+ },
+ });
+
+ let install = await AddonManager.getInstallForURL(
+ BASE_URL + "/policy_test.xpi"
+ );
+ await install.install();
+ notEqual(install.addon, null, "Addon should not be null");
+ equal(install.addon.appDisabled, false, "Addon should not be disabled");
+ await install.addon.uninstall();
+});
+
+add_task(async function test_addon_uninstalled() {
+ let install = await AddonManager.getInstallForURL(
+ BASE_URL + "/policy_test.xpi"
+ );
+ await install.install();
+ notEqual(install.addon, null, "Addon should not be null");
+
+ await Promise.all([
+ AddonTestUtils.promiseAddonEvent("onUninstalled"),
+ setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "*": {
+ installation_mode: "blocked",
+ },
+ },
+ },
+ }),
+ ]);
+ let addon = await AddonManager.getAddonByID(addonID);
+ equal(addon, null, "Addon should be null");
+});
+
+add_task(async function test_addon_forceinstalled() {
+ await Promise.all([
+ AddonTestUtils.promiseInstallEvent("onInstallEnded"),
+ setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "policytest2@mozilla.com": {
+ installation_mode: "force_installed",
+ install_url: BASE_URL + "/policy_test.xpi",
+ },
+ },
+ },
+ }),
+ ]);
+ let addon = await AddonManager.getAddonByID(addonID);
+ notEqual(addon, null, "Addon should not be null");
+ equal(addon.appDisabled, false, "Addon should not be disabled");
+ equal(
+ addon.permissions & AddonManager.PERM_CAN_UNINSTALL,
+ 0,
+ "Addon should not be able to be uninstalled."
+ );
+ equal(
+ addon.permissions & AddonManager.PERM_CAN_DISABLE,
+ 0,
+ "Addon should not be able to be disabled."
+ );
+ await addon.uninstall();
+});
+
+add_task(async function test_addon_normalinstalled() {
+ await Promise.all([
+ AddonTestUtils.promiseInstallEvent("onInstallEnded"),
+ setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "policytest2@mozilla.com": {
+ installation_mode: "normal_installed",
+ install_url: BASE_URL + "/policy_test.xpi",
+ },
+ },
+ },
+ }),
+ ]);
+ let addon = await AddonManager.getAddonByID(addonID);
+ notEqual(addon, null, "Addon should not be null");
+ equal(addon.appDisabled, false, "Addon should not be disabled");
+ equal(
+ addon.permissions & AddonManager.PERM_CAN_UNINSTALL,
+ 0,
+ "Addon should not be able to be uninstalled."
+ );
+ notEqual(
+ addon.permissions & AddonManager.PERM_CAN_DISABLE,
+ 0,
+ "Addon should be able to be disabled."
+ );
+ await addon.uninstall();
+});
+
+add_task(async function test_extensionsettings_string() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: '{"*": {"installation_mode": "blocked"}}',
+ },
+ });
+
+ let extensionSettings = Services.policies.getExtensionSettings("*");
+ equal(extensionSettings.installation_mode, "blocked");
+});
+
+add_task(async function test_extensionsettings_string() {
+ let restrictedDomains = Services.prefs.getCharPref(
+ "extensions.webextensions.restrictedDomains"
+ );
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings:
+ '{"*": {"restricted_domains": ["example.com","example.org"]}}',
+ },
+ });
+
+ let newRestrictedDomains = Services.prefs.getCharPref(
+ "extensions.webextensions.restrictedDomains"
+ );
+ equal(newRestrictedDomains, restrictedDomains + ",example.com,example.org");
+});
+
+add_task(async function test_theme() {
+ let themeFile = AddonTestUtils.createTempWebExtensionFile({
+ manifest: {
+ browser_specific_settings: {
+ gecko: {
+ id: themeID,
+ },
+ },
+ theme: {},
+ },
+ });
+
+ server.registerFile("/data/policy_theme.xpi", themeFile);
+
+ await Promise.all([
+ AddonTestUtils.promiseInstallEvent("onInstallEnded"),
+ setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "policytheme@mozilla.com": {
+ installation_mode: "normal_installed",
+ install_url: BASE_URL + "/policy_theme.xpi",
+ },
+ },
+ },
+ }),
+ ]);
+ let currentTheme = Services.prefs.getCharPref("extensions.activeThemeID");
+ equal(currentTheme, themeID, "Theme should be active");
+ let addon = await AddonManager.getAddonByID(themeID);
+ await addon.uninstall();
+});
+
+add_task(async function test_addon_normalinstalled_file() {
+ await Promise.all([
+ AddonTestUtils.promiseInstallEvent("onInstallEnded"),
+ setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "policytest2@mozilla.com": {
+ installation_mode: "normal_installed",
+ install_url: fileURL.spec,
+ },
+ },
+ },
+ }),
+ ]);
+ let addon = await AddonManager.getAddonByID(addonID);
+ notEqual(addon, null, "Addon should not be null");
+ equal(addon.appDisabled, false, "Addon should not be disabled");
+ equal(
+ addon.permissions & AddonManager.PERM_CAN_UNINSTALL,
+ 0,
+ "Addon should not be able to be uninstalled."
+ );
+ notEqual(
+ addon.permissions & AddonManager.PERM_CAN_DISABLE,
+ 0,
+ "Addon should be able to be disabled."
+ );
+
+ await addon.uninstall();
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_macosparser_unflatten.js b/browser/components/enterprisepolicies/tests/xpcshell/test_macosparser_unflatten.js
new file mode 100644
index 0000000000..096852612c
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_macosparser_unflatten.js
@@ -0,0 +1,110 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+let { macOSPoliciesParser } = ChromeUtils.importESModule(
+ "resource://gre/modules/policies/macOSPoliciesParser.sys.mjs"
+);
+
+add_task(async function test_object_unflatten() {
+ // Note: these policies are just examples and they won't actually
+ // run through the policy engine on this test. We're just testing
+ // that the unflattening algorithm produces the correct output.
+ let input = {
+ DisplayBookmarksToolbar: true,
+
+ Homepage__URL: "https://www.mozilla.org",
+ Homepage__Locked: "true",
+ Homepage__Additional__0: "https://extra-homepage-1.example.com",
+ Homepage__Additional__1: "https://extra-homepage-2.example.com",
+
+ WebsiteFilter__Block__0: "*://*.example.org/*",
+ WebsiteFilter__Block__1: "*://*.example.net/*",
+ WebsiteFilter__Exceptions__0: "*://*.example.org/*exception*",
+
+ Permissions__Camera__Allow__0: "https://www.example.com",
+
+ Permissions__Notifications__Allow__0: "https://www.example.com",
+ Permissions__Notifications__Allow__1: "https://www.example.org",
+ Permissions__Notifications__Block__0: "https://www.example.net",
+
+ Permissions__Notifications__BlockNewRequests: true,
+ Permissions__Notifications__Locked: true,
+
+ Bookmarks__0__Title: "Bookmark 1",
+ Bookmarks__0__URL: "https://bookmark1.example.com",
+
+ Bookmarks__1__Title: "Bookmark 2",
+ Bookmarks__1__URL: "https://bookmark2.example.com",
+ Bookmarks__1__Folder: "Folder",
+ };
+
+ let expected = {
+ DisplayBookmarksToolbar: true,
+
+ Homepage: {
+ URL: "https://www.mozilla.org",
+ Locked: "true",
+ Additional: [
+ "https://extra-homepage-1.example.com",
+ "https://extra-homepage-2.example.com",
+ ],
+ },
+
+ WebsiteFilter: {
+ Block: ["*://*.example.org/*", "*://*.example.net/*"],
+ Exceptions: ["*://*.example.org/*exception*"],
+ },
+
+ Permissions: {
+ Camera: {
+ Allow: ["https://www.example.com"],
+ },
+
+ Notifications: {
+ Allow: ["https://www.example.com", "https://www.example.org"],
+ Block: ["https://www.example.net"],
+ BlockNewRequests: true,
+ Locked: true,
+ },
+ },
+
+ Bookmarks: [
+ {
+ Title: "Bookmark 1",
+ URL: "https://bookmark1.example.com",
+ },
+ {
+ Title: "Bookmark 2",
+ URL: "https://bookmark2.example.com",
+ Folder: "Folder",
+ },
+ ],
+ };
+
+ let unflattened = macOSPoliciesParser.unflatten(input);
+
+ deepEqual(unflattened, expected, "Input was unflattened correctly.");
+});
+
+add_task(async function test_array_unflatten() {
+ let input = {
+ Foo__1: 1,
+ Foo__5: 5,
+ Foo__10: 10,
+ Foo__30: 30,
+ Foo__51: 51, // This one should not be included as the limit is 50
+ };
+
+ let unflattened = macOSPoliciesParser.unflatten(input);
+ equal(unflattened.Foo.length, 31, "Array size is correct");
+
+ let expected = {
+ Foo: [, 1, , , , 5], // eslint-disable-line no-sparse-arrays
+ };
+ expected.Foo[10] = 10;
+ expected.Foo[30] = 30;
+
+ deepEqual(unflattened, expected, "Array was unflattened correctly.");
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_permissions.js b/browser/components/enterprisepolicies/tests/xpcshell/test_permissions.js
new file mode 100644
index 0000000000..f4440e53f5
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_permissions.js
@@ -0,0 +1,355 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+function URI(str) {
+ return Services.io.newURI(str);
+}
+
+add_task(async function test_setup_preexisting_permissions() {
+ // Pre-existing ALLOW permissions that should be overridden
+ // with DENY.
+
+ // No ALLOW -> DENY override for popup and install permissions,
+ // because their policies only supports the Allow parameter.
+
+ PermissionTestUtils.add(
+ "https://www.pre-existing-allow.com",
+ "camera",
+ Ci.nsIPermissionManager.ALLOW_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.pre-existing-allow.com",
+ "microphone",
+ Ci.nsIPermissionManager.ALLOW_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.pre-existing-allow.com",
+ "geo",
+ Ci.nsIPermissionManager.ALLOW_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.pre-existing-allow.com",
+ "desktop-notification",
+ Ci.nsIPermissionManager.ALLOW_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.pre-existing-allow.com",
+ "autoplay-media",
+ Ci.nsIPermissionManager.ALLOW_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.pre-existing-allow.com",
+ "xr",
+ Ci.nsIPermissionManager.ALLOW_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+
+ // Pre-existing DENY permissions that should be overridden
+ // with ALLOW.
+
+ PermissionTestUtils.add(
+ "https://www.pre-existing-deny.com",
+ "camera",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.pre-existing-deny.com",
+ "microphone",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.pre-existing-deny.com",
+ "geo",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.pre-existing-deny.com",
+ "desktop-notification",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.pre-existing-deny.com",
+ "autoplay-media",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.pre-existing-deny.com",
+ "xr",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+});
+
+add_task(async function test_setup_activate_policies() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Permissions: {
+ Camera: {
+ Allow: ["https://www.allow.com", "https://www.pre-existing-deny.com"],
+ Block: ["https://www.deny.com", "https://www.pre-existing-allow.com"],
+ },
+ Microphone: {
+ Allow: ["https://www.allow.com", "https://www.pre-existing-deny.com"],
+ Block: ["https://www.deny.com", "https://www.pre-existing-allow.com"],
+ },
+ Location: {
+ Allow: ["https://www.allow.com", "https://www.pre-existing-deny.com"],
+ Block: ["https://www.deny.com", "https://www.pre-existing-allow.com"],
+ },
+ Notifications: {
+ Allow: ["https://www.allow.com", "https://www.pre-existing-deny.com"],
+ Block: ["https://www.deny.com", "https://www.pre-existing-allow.com"],
+ },
+ Autoplay: {
+ Allow: ["https://www.allow.com", "https://www.pre-existing-deny.com"],
+ Block: ["https://www.deny.com", "https://www.pre-existing-allow.com"],
+ },
+ VirtualReality: {
+ Allow: ["https://www.allow.com", "https://www.pre-existing-deny.com"],
+ Block: ["https://www.deny.com", "https://www.pre-existing-allow.com"],
+ },
+ },
+ },
+ });
+ equal(
+ Services.policies.status,
+ Ci.nsIEnterprisePolicies.ACTIVE,
+ "Engine is active"
+ );
+});
+
+function checkPermission(url, expected, permissionName) {
+ let expectedValue = Ci.nsIPermissionManager[`${expected}_ACTION`];
+ let uri = Services.io.newURI(`https://www.${url}`);
+
+ equal(
+ PermissionTestUtils.testPermission(uri, permissionName),
+ expectedValue,
+ `Correct (${permissionName}=${expected}) for URL ${url}`
+ );
+
+ if (expected != "UNKNOWN") {
+ let permission = PermissionTestUtils.getPermissionObject(
+ uri,
+ permissionName,
+ true
+ );
+ ok(permission, "Permission object exists");
+ equal(
+ permission.expireType,
+ Ci.nsIPermissionManager.EXPIRE_POLICY,
+ "Permission expireType is correct"
+ );
+ }
+}
+
+function checkAllPermissionsForType(type, typeSupportsDeny = true) {
+ checkPermission("allow.com", "ALLOW", type);
+ checkPermission("unknown.com", "UNKNOWN", type);
+ checkPermission("pre-existing-deny.com", "ALLOW", type);
+
+ if (typeSupportsDeny) {
+ checkPermission("deny.com", "DENY", type);
+ checkPermission("pre-existing-allow.com", "DENY", type);
+ }
+}
+
+add_task(async function test_camera_policy() {
+ checkAllPermissionsForType("camera");
+});
+
+add_task(async function test_microphone_policy() {
+ checkAllPermissionsForType("microphone");
+});
+
+add_task(async function test_location_policy() {
+ checkAllPermissionsForType("geo");
+});
+
+add_task(async function test_notifications_policy() {
+ checkAllPermissionsForType("desktop-notification");
+});
+
+add_task(async function test_autoplay_policy() {
+ checkAllPermissionsForType("autoplay-media");
+});
+
+add_task(async function test_xr_policy() {
+ checkAllPermissionsForType("xr");
+});
+
+add_task(async function test_change_permission() {
+ // Checks that changing a permission will still retain the
+ // value set through the engine.
+ PermissionTestUtils.add(
+ "https://www.allow.com",
+ "camera",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.allow.com",
+ "microphone",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.allow.com",
+ "geo",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.allow.com",
+ "desktop-notification",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.allow.com",
+ "autoplay-media",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.allow.com",
+ "xr",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+
+ checkPermission("allow.com", "ALLOW", "camera");
+ checkPermission("allow.com", "ALLOW", "microphone");
+ checkPermission("allow.com", "ALLOW", "geo");
+ checkPermission("allow.com", "ALLOW", "desktop-notification");
+ checkPermission("allow.com", "ALLOW", "autoplay-media");
+ checkPermission("allow.com", "ALLOW", "xr");
+
+ // Also change one un-managed permission to make sure it doesn't
+ // cause any problems to the policy engine or the permission manager.
+ PermissionTestUtils.add(
+ "https://www.unmanaged.com",
+ "camera",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.unmanaged.com",
+ "microphone",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.unmanaged.com",
+ "geo",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.unmanaged.com",
+ "desktop-notification",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.unmanaged.com",
+ "autoplay-media",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+ PermissionTestUtils.add(
+ "https://www.unmanaged.com",
+ "xr",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+});
+
+add_task(async function test_setup_trackingprotection() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ EnableTrackingProtection: {
+ Exceptions: ["https://www.allow.com"],
+ },
+ },
+ });
+ equal(
+ Services.policies.status,
+ Ci.nsIEnterprisePolicies.ACTIVE,
+ "Engine is active"
+ );
+});
+
+add_task(async function test_trackingprotection() {
+ checkPermission("allow.com", "ALLOW", "trackingprotection");
+});
+
+// This seems a little out of place, but it's really a cookie
+// permission, not cookies per say.
+add_task(async function test_cookie_allow_session() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Cookies: {
+ AllowSession: ["https://allowsession.example.com"],
+ },
+ },
+ });
+ equal(
+ PermissionTestUtils.testPermission(
+ URI("https://allowsession.example.com"),
+ "cookie"
+ ),
+ Ci.nsICookiePermission.ACCESS_SESSION
+ );
+});
+
+// This again seems out of places, but AutoLaunchProtocolsFromOrigins
+// is all permissions.
+add_task(async function test_autolaunchprotocolsfromorigins() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ AutoLaunchProtocolsFromOrigins: [
+ {
+ allowed_origins: ["https://allowsession.example.com"],
+ protocol: "test-protocol",
+ },
+ ],
+ },
+ });
+ equal(
+ PermissionTestUtils.testPermission(
+ URI("https://allowsession.example.com"),
+ "open-protocol-handler^test-protocol"
+ ),
+ Ci.nsIPermissionManager.ALLOW_ACTION
+ );
+});
+
+// This again seems out of places, but PasswordManagerExceptions
+// is all permissions.
+add_task(async function test_passwordmanagerexceptions() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ PasswordManagerExceptions: ["https://pwexception.example.com"],
+ },
+ });
+ equal(
+ PermissionTestUtils.testPermission(
+ URI("https://pwexception.example.com"),
+ "login-saving"
+ ),
+ Ci.nsIPermissionManager.DENY_ACTION
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_policy_search_engine.js b/browser/components/enterprisepolicies/tests/xpcshell/test_policy_search_engine.js
new file mode 100644
index 0000000000..5c602442f2
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_policy_search_engine.js
@@ -0,0 +1,490 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const { SearchTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/SearchTestUtils.sys.mjs"
+);
+const { TestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/TestUtils.sys.mjs"
+);
+var { AddonTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/AddonTestUtils.sys.mjs"
+);
+
+Services.prefs.setBoolPref("browser.search.log", true);
+SearchTestUtils.init(this);
+
+AddonTestUtils.init(this, false);
+AddonTestUtils.createAppInfo(
+ "xpcshell@tests.mozilla.org",
+ "XPCShell",
+ "48",
+ "48"
+);
+
+add_setup(async () => {
+ await AddonTestUtils.promiseStartupManager();
+ await Services.search.init();
+ console.log("done init");
+});
+
+add_task(async function test_install_and_set_default() {
+ // Make sure we are starting in an expected state to avoid false positive
+ // test results.
+ Assert.notEqual(
+ (await Services.search.getDefault()).name,
+ "MozSearch",
+ "Default search engine should not be MozSearch when test starts"
+ );
+ Assert.equal(
+ Services.search.getEngineByName("Foo"),
+ null,
+ 'Engine "Foo" should not be present when test starts'
+ );
+
+ await setupPolicyEngineWithJsonWithSearch({
+ policies: {
+ SearchEngines: {
+ Add: [
+ {
+ Name: "MozSearch",
+ URLTemplate: "http://example.com/?q={searchTerms}",
+ },
+ ],
+ Default: "MozSearch",
+ },
+ },
+ });
+ // Get in line, because the Search policy callbacks are async.
+ await TestUtils.waitForTick();
+
+ // If this passes, it means that the new search engine was properly installed
+ // *and* was properly set as the default.
+ Assert.equal(
+ (await Services.search.getDefault()).name,
+ "MozSearch",
+ "Specified search engine should be the default"
+ );
+
+ // Clean up
+ await setupPolicyEngineWithJsonWithSearch({});
+ EnterprisePolicyTesting.resetRunOnceState();
+});
+
+add_task(async function test_install_and_set_default_private() {
+ // Make sure we are starting in an expected state to avoid false positive
+ // test results.
+ Assert.notEqual(
+ (await Services.search.getDefaultPrivate()).name,
+ "MozSearch",
+ "Default search engine should not be MozSearch when test starts"
+ );
+ Assert.equal(
+ Services.search.getEngineByName("Foo"),
+ null,
+ 'Engine "Foo" should not be present when test starts'
+ );
+
+ await setupPolicyEngineWithJsonWithSearch({
+ policies: {
+ SearchEngines: {
+ Add: [
+ {
+ Name: "MozSearch",
+ URLTemplate: "http://example.com/?q={searchTerms}",
+ },
+ ],
+ DefaultPrivate: "MozSearch",
+ },
+ },
+ });
+ // Get in line, because the Search policy callbacks are async.
+ await TestUtils.waitForTick();
+
+ // If this passes, it means that the new search engine was properly installed
+ // *and* was properly set as the default.
+ Assert.equal(
+ (await Services.search.getDefaultPrivate()).name,
+ "MozSearch",
+ "Specified search engine should be the default private engine"
+ );
+
+ // Clean up
+ await setupPolicyEngineWithJsonWithSearch({});
+ EnterprisePolicyTesting.resetRunOnceState();
+});
+
+// Same as the last test, but with "PreventInstalls" set to true to make sure
+// it does not prevent search engines from being installed properly
+add_task(async function test_install_and_set_default_prevent_installs() {
+ Assert.notEqual(
+ (await Services.search.getDefault()).name,
+ "MozSearch",
+ "Default search engine should not be MozSearch when test starts"
+ );
+ Assert.equal(
+ Services.search.getEngineByName("Foo"),
+ null,
+ 'Engine "Foo" should not be present when test starts'
+ );
+
+ await setupPolicyEngineWithJsonWithSearch({
+ policies: {
+ SearchEngines: {
+ Add: [
+ {
+ Name: "MozSearch",
+ URLTemplate: "http://example.com/?q={searchTerms}",
+ },
+ ],
+ Default: "MozSearch",
+ PreventInstalls: true,
+ },
+ },
+ });
+ // Get in line, because the Search policy callbacks are async.
+ await TestUtils.waitForTick();
+
+ Assert.equal(
+ (await Services.search.getDefault()).name,
+ "MozSearch",
+ "Specified search engine should be the default"
+ );
+
+ // Clean up
+ await setupPolicyEngineWithJsonWithSearch({});
+ EnterprisePolicyTesting.resetRunOnceState();
+});
+
+add_task(async function test_install_and_remove() {
+ let iconURL =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=";
+
+ Assert.equal(
+ Services.search.getEngineByName("Foo"),
+ null,
+ 'Engine "Foo" should not be present when test starts'
+ );
+
+ await setupPolicyEngineWithJsonWithSearch({
+ policies: {
+ SearchEngines: {
+ Add: [
+ {
+ Name: "Foo",
+ URLTemplate: "http://example.com/?q={searchTerms}",
+ IconURL: iconURL,
+ },
+ ],
+ },
+ },
+ });
+ // Get in line, because the Search policy callbacks are async.
+ await TestUtils.waitForTick();
+
+ // If this passes, it means that the new search engine was properly installed
+
+ let engine = Services.search.getEngineByName("Foo");
+ Assert.notEqual(engine, null, "Specified search engine should be installed");
+
+ Assert.equal(
+ engine.wrappedJSObject.getIconURL(),
+ iconURL,
+ "Icon should be present"
+ );
+ Assert.equal(
+ engine.wrappedJSObject.queryCharset,
+ "UTF-8",
+ "Should default to utf-8"
+ );
+
+ await setupPolicyEngineWithJsonWithSearch({
+ policies: {
+ SearchEngines: {
+ Remove: ["Foo"],
+ },
+ },
+ });
+ // Get in line, because the Search policy callbacks are async.
+ await TestUtils.waitForTick();
+
+ // If this passes, it means that the specified engine was properly removed
+ Assert.equal(
+ Services.search.getEngineByName("Foo"),
+ null,
+ "Specified search engine should not be installed"
+ );
+
+ await setupPolicyEngineWithJsonWithSearch({});
+ EnterprisePolicyTesting.resetRunOnceState();
+});
+
+add_task(async function test_install_post_method_engine() {
+ Assert.equal(
+ Services.search.getEngineByName("Post"),
+ null,
+ 'Engine "Post" should not be present when test starts'
+ );
+
+ await setupPolicyEngineWithJsonWithSearch({
+ policies: {
+ SearchEngines: {
+ Add: [
+ {
+ Name: "Post",
+ Method: "POST",
+ PostData: "q={searchTerms}&anotherParam=yes",
+ URLTemplate: "http://example.com/",
+ },
+ ],
+ },
+ },
+ });
+ // Get in line, because the Search policy callbacks are async.
+ await TestUtils.waitForTick();
+
+ let engine = Services.search.getEngineByName("Post");
+ Assert.notEqual(engine, null, "Specified search engine should be installed");
+
+ Assert.equal(
+ engine.wrappedJSObject._urls[0].method,
+ "POST",
+ "Method should be POST"
+ );
+
+ let submission = engine.getSubmission("term", "text/html");
+ Assert.notEqual(submission.postData, null, "Post data should not be null");
+
+ let scriptableInputStream = Cc[
+ "@mozilla.org/scriptableinputstream;1"
+ ].createInstance(Ci.nsIScriptableInputStream);
+ scriptableInputStream.init(submission.postData);
+ Assert.equal(
+ scriptableInputStream.read(scriptableInputStream.available()),
+ "q=term&anotherParam=yes",
+ "Post data should be present"
+ );
+
+ await setupPolicyEngineWithJsonWithSearch({});
+ EnterprisePolicyTesting.resetRunOnceState();
+});
+
+add_task(async function test_install_with_encoding() {
+ // Make sure we are starting in an expected state to avoid false positive
+ // test results.
+ Assert.equal(
+ Services.search.getEngineByName("Encoding"),
+ null,
+ 'Engine "Encoding" should not be present when test starts'
+ );
+
+ await setupPolicyEngineWithJsonWithSearch({
+ policies: {
+ SearchEngines: {
+ Add: [
+ {
+ Name: "Encoding",
+ Encoding: "windows-1252",
+ URLTemplate: "http://example.com/?q={searchTerms}",
+ },
+ ],
+ },
+ },
+ });
+ // Get in line, because the Search policy callbacks are async.
+ await TestUtils.waitForTick();
+
+ let engine = Services.search.getEngineByName("Encoding");
+ Assert.equal(
+ engine.wrappedJSObject.queryCharset,
+ "windows-1252",
+ "Should have correct encoding"
+ );
+
+ // Clean up
+ await setupPolicyEngineWithJsonWithSearch({});
+ EnterprisePolicyTesting.resetRunOnceState();
+});
+
+add_task(async function test_install_and_update() {
+ await setupPolicyEngineWithJsonWithSearch({
+ policies: {
+ SearchEngines: {
+ Add: [
+ {
+ Name: "ToUpdate",
+ URLTemplate: "http://initial.example.com/?q={searchTerms}",
+ },
+ ],
+ },
+ },
+ });
+ // Get in line, because the Search policy callbacks are async.
+ await TestUtils.waitForTick();
+
+ let engine = Services.search.getEngineByName("ToUpdate");
+ Assert.notEqual(engine, null, "Specified search engine should be installed");
+
+ Assert.equal(
+ engine.getSubmission("test").uri.spec,
+ "http://initial.example.com/?q=test",
+ "Initial submission URL should be correct."
+ );
+
+ await setupPolicyEngineWithJsonWithSearch({
+ policies: {
+ SearchEngines: {
+ Add: [
+ {
+ Name: "ToUpdate",
+ URLTemplate: "http://update.example.com/?q={searchTerms}",
+ },
+ ],
+ },
+ },
+ });
+ // Get in line, because the Search policy callbacks are async.
+ await TestUtils.waitForTick();
+
+ engine = Services.search.getEngineByName("ToUpdate");
+ Assert.notEqual(engine, null, "Specified search engine should be installed");
+
+ Assert.equal(
+ engine.getSubmission("test").uri.spec,
+ "http://update.example.com/?q=test",
+ "Updated Submission URL should be correct."
+ );
+
+ // Clean up
+ await setupPolicyEngineWithJsonWithSearch({});
+ EnterprisePolicyTesting.resetRunOnceState();
+});
+
+add_task(async function test_install_with_suggest() {
+ // Make sure we are starting in an expected state to avoid false positive
+ // test results.
+ Assert.equal(
+ Services.search.getEngineByName("Suggest"),
+ null,
+ 'Engine "Suggest" should not be present when test starts'
+ );
+
+ await setupPolicyEngineWithJsonWithSearch({
+ policies: {
+ SearchEngines: {
+ Add: [
+ {
+ Name: "Suggest",
+ URLTemplate: "http://example.com/?q={searchTerms}",
+ SuggestURLTemplate: "http://suggest.example.com/?q={searchTerms}",
+ },
+ ],
+ },
+ },
+ });
+ // Get in line, because the Search policy callbacks are async.
+ await TestUtils.waitForTick();
+
+ let engine = Services.search.getEngineByName("Suggest");
+
+ Assert.equal(
+ engine.getSubmission("test", "application/x-suggestions+json").uri.spec,
+ "http://suggest.example.com/?q=test",
+ "Updated Submission URL should be correct."
+ );
+
+ // Clean up
+ await setupPolicyEngineWithJsonWithSearch({});
+ EnterprisePolicyTesting.resetRunOnceState();
+});
+
+add_task(async function test_install_and_restart_keeps_settings() {
+ // Make sure we are starting in an expected state to avoid false positive
+ // test results.
+ Assert.equal(
+ Services.search.getEngineByName("Settings"),
+ null,
+ 'Engine "Settings" should not be present when test starts'
+ );
+
+ await setupPolicyEngineWithJsonWithSearch({
+ policies: {
+ SearchEngines: {
+ Add: [
+ {
+ Name: "Settings",
+ URLTemplate: "http://example.com/?q={searchTerms}",
+ },
+ ],
+ },
+ },
+ });
+ // Get in line, because the Search policy callbacks are async.
+ await TestUtils.waitForTick();
+
+ let settingsWritten = SearchTestUtils.promiseSearchNotification(
+ "write-settings-to-disk-complete"
+ );
+ let engine = Services.search.getEngineByName("Settings");
+ engine.hidden = true;
+ engine.alias = "settings";
+ await settingsWritten;
+
+ await setupPolicyEngineWithJsonWithSearch({
+ policies: {
+ SearchEngines: {
+ Add: [
+ {
+ Name: "Settings",
+ URLTemplate: "http://example.com/?q={searchTerms}",
+ },
+ ],
+ },
+ },
+ });
+
+ engine = Services.search.getEngineByName("Settings");
+
+ Assert.ok(engine.hidden, "Should have kept the engine hidden after restart");
+ Assert.equal(
+ engine.alias,
+ "settings",
+ "Should have kept the engine alias after restart"
+ );
+
+ // Clean up
+ await setupPolicyEngineWithJsonWithSearch({});
+ EnterprisePolicyTesting.resetRunOnceState();
+});
+
+add_task(async function test_reset_default() {
+ await setupPolicyEngineWithJsonWithSearch({
+ policies: {
+ SearchEngines: {
+ Remove: ["DuckDuckGo"],
+ },
+ },
+ });
+ // Get in line, because the Search policy callbacks are async.
+ await TestUtils.waitForTick();
+
+ let engine = Services.search.getEngineByName("DuckDuckGo");
+
+ Assert.equal(
+ engine.hidden,
+ true,
+ "Application specified engine should be hidden."
+ );
+
+ await Services.search.restoreDefaultEngines();
+
+ engine = Services.search.getEngineByName("DuckDuckGo");
+ Assert.equal(
+ engine.hidden,
+ false,
+ "Application specified engine should not be hidden"
+ );
+
+ EnterprisePolicyTesting.resetRunOnceState();
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_popups_cookies_addons.js b/browser/components/enterprisepolicies/tests/xpcshell/test_popups_cookies_addons.js
new file mode 100644
index 0000000000..8da8d4b9e4
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_popups_cookies_addons.js
@@ -0,0 +1,121 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_setup_preexisting_permissions() {
+ // Pre-existing ALLOW permissions that should be overriden
+ // with DENY.
+
+ // No ALLOW -> DENY override for popup and install permissions,
+ // because their policies only supports the Allow parameter.
+
+ PermissionTestUtils.add(
+ "https://www.pre-existing-allow.com",
+ "cookie",
+ Ci.nsIPermissionManager.ALLOW_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+
+ // Pre-existing DENY permissions that should be overriden
+ // with ALLOW.
+ PermissionTestUtils.add(
+ "https://www.pre-existing-deny.com",
+ "popup",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+
+ PermissionTestUtils.add(
+ "https://www.pre-existing-deny.com",
+ "install",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+
+ PermissionTestUtils.add(
+ "https://www.pre-existing-deny.com",
+ "cookie",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+});
+
+add_task(async function test_setup_activate_policies() {
+ await setupPolicyEngineWithJson("config_popups_cookies_addons.json");
+ equal(
+ Services.policies.status,
+ Ci.nsIEnterprisePolicies.ACTIVE,
+ "Engine is active"
+ );
+});
+
+function checkPermission(url, expected, permissionName) {
+ let expectedValue = Ci.nsIPermissionManager[`${expected}_ACTION`];
+ let uri = Services.io.newURI(`https://www.${url}`);
+
+ equal(
+ PermissionTestUtils.testPermission(uri, permissionName),
+ expectedValue,
+ `Correct (${permissionName}=${expected}) for URL ${url}`
+ );
+
+ if (expected != "UNKNOWN") {
+ let permission = PermissionTestUtils.getPermissionObject(
+ uri,
+ permissionName,
+ true
+ );
+ ok(permission, "Permission object exists");
+ equal(
+ permission.expireType,
+ Ci.nsIPermissionManager.EXPIRE_POLICY,
+ "Permission expireType is correct"
+ );
+ }
+}
+
+function checkAllPermissionsForType(type, typeSupportsDeny = true) {
+ checkPermission("allow.com", "ALLOW", type);
+ checkPermission("unknown.com", "UNKNOWN", type);
+ checkPermission("pre-existing-deny.com", "ALLOW", type);
+
+ if (typeSupportsDeny) {
+ checkPermission("deny.com", "DENY", type);
+ checkPermission("pre-existing-allow.com", "DENY", type);
+ }
+}
+
+add_task(async function test_popups_policy() {
+ checkAllPermissionsForType("popup", false);
+});
+
+add_task(async function test_webextensions_policy() {
+ checkAllPermissionsForType("install", false);
+});
+
+add_task(async function test_cookies_policy() {
+ checkAllPermissionsForType("cookie");
+});
+
+add_task(async function test_change_permission() {
+ // Checks that changing a permission will still retain the
+ // value set through the engine.
+ PermissionTestUtils.add(
+ "https://www.allow.com",
+ "cookie",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+
+ checkPermission("allow.com", "ALLOW", "cookie");
+
+ // Also change one un-managed permission to make sure it doesn't
+ // cause any problems to the policy engine or the permission manager.
+ PermissionTestUtils.add(
+ "https://www.unmanaged.com",
+ "cookie",
+ Ci.nsIPermissionManager.DENY_ACTION,
+ Ci.nsIPermissionManager.EXPIRE_SESSION
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_preferences.js b/browser/components/enterprisepolicies/tests/xpcshell/test_preferences.js
new file mode 100644
index 0000000000..eb13fe24ae
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_preferences.js
@@ -0,0 +1,257 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const OLD_PREFERENCES_TESTS = [
+ {
+ policies: {
+ Preferences: {
+ "network.IDN_show_punycode": true,
+ "accessibility.force_disabled": 1,
+ "security.default_personal_cert": "Select Automatically",
+ "geo.enabled": 1,
+ "extensions.getAddons.showPane": 0,
+ },
+ },
+ lockedPrefs: {
+ "network.IDN_show_punycode": true,
+ "accessibility.force_disabled": 1,
+ "security.default_personal_cert": "Select Automatically",
+ "geo.enabled": true,
+ "extensions.getAddons.showPane": false,
+ },
+ },
+];
+
+const NEW_PREFERENCES_TESTS = [
+ {
+ policies: {
+ Preferences: {
+ "browser.policies.test.default.boolean": {
+ Value: true,
+ Status: "default",
+ },
+ "browser.policies.test.default.string": {
+ Value: "string",
+ Status: "default",
+ },
+ "browser.policies.test.default.number": {
+ Value: 11,
+ Status: "default",
+ },
+ "browser.policies.test.locked.boolean": {
+ Value: true,
+ Status: "locked",
+ },
+ "browser.policies.test.locked.string": {
+ Value: "string",
+ Status: "locked",
+ },
+ "browser.policies.test.locked.number": {
+ Value: 11,
+ Status: "locked",
+ },
+ "browser.policies.test.user.boolean": {
+ Value: true,
+ Status: "user",
+ },
+ "browser.policies.test.user.string": {
+ Value: "string",
+ Status: "user",
+ },
+ "browser.policies.test.user.number": {
+ Value: 11,
+ Status: "user",
+ },
+ "browser.policies.test.default.number.implicit": {
+ Value: 0,
+ Status: "default",
+ },
+ "browser.policies.test.default.number.explicit": {
+ Value: 0,
+ Status: "default",
+ Type: "number",
+ },
+ },
+ },
+ defaultPrefs: {
+ "browser.policies.test.default.boolean": true,
+ "browser.policies.test.default.string": "string",
+ "browser.policies.test.default.number": 11,
+ "browser.policies.test.default.number.implicit": false,
+ "browser.policies.test.default.number.explicit": 0,
+ },
+ lockedPrefs: {
+ "browser.policies.test.locked.boolean": true,
+ "browser.policies.test.locked.string": "string",
+ "browser.policies.test.locked.number": 11,
+ },
+ userPrefs: {
+ "browser.policies.test.user.boolean": true,
+ "browser.policies.test.user.string": "string",
+ "browser.policies.test.user.number": 11,
+ },
+ },
+ {
+ policies: {
+ Preferences: {
+ "browser.policies.test.user.boolean": {
+ Status: "clear",
+ },
+ "browser.policies.test.user.string": {
+ Status: "clear",
+ },
+ "browser.policies.test.user.number": {
+ Status: "clear",
+ },
+ },
+ },
+
+ clearPrefs: {
+ "browser.policies.test.user.boolean": true,
+ "browser.policies.test.user.string": "string",
+ "browser.policies.test.user.number": 11,
+ },
+ },
+];
+
+const BAD_PREFERENCES_TESTS = [
+ {
+ policies: {
+ Preferences: {
+ "not.a.valid.branch": {
+ Value: true,
+ Status: "default",
+ },
+ "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer":
+ {
+ Value: true,
+ Status: "default",
+ },
+ },
+ },
+ defaultPrefs: {
+ "not.a.valid.branch": true,
+ "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer": true,
+ },
+ },
+];
+
+add_task(async function test_old_preferences() {
+ for (let test of OLD_PREFERENCES_TESTS) {
+ await setupPolicyEngineWithJson({
+ policies: test.policies,
+ });
+
+ info("Checking policy: " + Object.keys(test.policies)[0]);
+
+ for (let [prefName, prefValue] of Object.entries(test.lockedPrefs || {})) {
+ checkLockedPref(prefName, prefValue);
+ }
+ }
+});
+
+add_task(async function test_new_preferences() {
+ for (let test of NEW_PREFERENCES_TESTS) {
+ await setupPolicyEngineWithJson({
+ policies: test.policies,
+ });
+
+ info("Checking policy: " + Object.keys(test.policies)[0]);
+
+ for (let [prefName, prefValue] of Object.entries(test.lockedPrefs || {})) {
+ checkLockedPref(prefName, prefValue);
+ }
+
+ for (let [prefName, prefValue] of Object.entries(test.defaultPrefs || {})) {
+ checkDefaultPref(prefName, prefValue);
+ }
+
+ for (let [prefName, prefValue] of Object.entries(test.userPrefs || {})) {
+ checkUserPref(prefName, prefValue);
+ }
+
+ for (let [prefName, prefValue] of Object.entries(test.clearPrefs || {})) {
+ checkClearPref(prefName, prefValue);
+ }
+ }
+});
+
+add_task(async function test_bad_preferences() {
+ for (let test of BAD_PREFERENCES_TESTS) {
+ await setupPolicyEngineWithJson({
+ policies: test.policies,
+ });
+
+ info("Checking policy: " + Object.keys(test.policies)[0]);
+
+ for (let prefName of Object.entries(test.defaultPrefs || {})) {
+ checkUnsetPref(prefName);
+ }
+ }
+});
+
+add_task(async function test_user_default_preference() {
+ Services.prefs
+ .getDefaultBranch("")
+ .setBoolPref("browser.policies.test.override", true);
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ Preferences: {
+ "browser.policies.test.override": {
+ Value: true,
+ Status: "user",
+ },
+ },
+ },
+ });
+
+ checkUserPref("browser.policies.test.override", true);
+});
+
+add_task(async function test_security_preference() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Preferences: {
+ "security.this.should.not.work": {
+ Value: true,
+ Status: "default",
+ },
+ },
+ },
+ });
+
+ checkUnsetPref("security.this.should.not.work");
+});
+
+add_task(async function test_JSON_preferences() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Preferences:
+ '{"browser.policies.test.default.boolean.json": {"Value": true,"Status": "default"}}',
+ },
+ });
+
+ checkDefaultPref("browser.policies.test.default.boolean.json", true);
+});
+
+add_task(async function test_bug_1666836() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Preferences: {
+ "browser.tabs.warnOnClose": {
+ Value: 0,
+ Status: "default",
+ },
+ },
+ },
+ });
+
+ equal(
+ Preferences.get("browser.tabs.warnOnClose"),
+ false,
+ `browser.tabs.warnOnClose should be false`
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_proxy.js b/browser/components/enterprisepolicies/tests/xpcshell/test_proxy.js
new file mode 100644
index 0000000000..ef5ad1e178
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_proxy.js
@@ -0,0 +1,122 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+add_task(async function test_proxy_modes_and_autoconfig() {
+ // Directly test the proxy Mode and AutoconfigURL parameters through
+ // the API instead of the policy engine, because the test harness
+ // uses these prefs, and changing them interfere with the harness.
+
+ // Checks that every Mode value translates correctly to the expected pref value
+ let { ProxyPolicies, PROXY_TYPES_MAP } = ChromeUtils.importESModule(
+ "resource:///modules/policies/ProxyPolicies.sys.mjs"
+ );
+
+ for (let [mode, expectedValue] of PROXY_TYPES_MAP) {
+ ProxyPolicies.configureProxySettings({ Mode: mode }, (_, value) => {
+ equal(value, expectedValue, "Correct proxy mode");
+ });
+ }
+
+ let autoconfigURL = new URL("data:text/plain,test");
+ ProxyPolicies.configureProxySettings(
+ { AutoConfigURL: autoconfigURL },
+ (_, value) => {
+ equal(value, autoconfigURL.href, "AutoconfigURL correctly set");
+ }
+ );
+});
+
+add_task(async function test_proxy_boolean_settings() {
+ // Tests that both false and true values are correctly set and locked
+ await setupPolicyEngineWithJson({
+ policies: {
+ Proxy: {
+ UseProxyForDNS: false,
+ AutoLogin: false,
+ },
+ },
+ });
+
+ checkUnlockedPref("network.proxy.socks_remote_dns", false);
+ checkUnlockedPref("signon.autologin.proxy", false);
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ Proxy: {
+ UseProxyForDNS: true,
+ AutoLogin: true,
+ },
+ },
+ });
+
+ checkUnlockedPref("network.proxy.socks_remote_dns", true);
+ checkUnlockedPref("signon.autologin.proxy", true);
+});
+
+add_task(async function test_proxy_socks_and_passthrough() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Proxy: {
+ SOCKSVersion: 4,
+ Passthrough: "a, b, c",
+ },
+ },
+ });
+
+ checkUnlockedPref("network.proxy.socks_version", 4);
+ checkUnlockedPref("network.proxy.no_proxies_on", "a, b, c");
+});
+
+add_task(async function test_proxy_addresses() {
+ function checkProxyPref(proxytype, address, port) {
+ checkUnlockedPref(`network.proxy.${proxytype}`, address);
+ checkUnlockedPref(`network.proxy.${proxytype}_port`, port);
+ }
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ Proxy: {
+ HTTPProxy: "http.proxy.example.com:10",
+ SSLProxy: "ssl.proxy.example.com:30",
+ SOCKSProxy: "socks.proxy.example.com:40",
+ },
+ },
+ });
+
+ checkProxyPref("http", "http.proxy.example.com", 10);
+ checkProxyPref("ssl", "ssl.proxy.example.com", 30);
+ checkProxyPref("socks", "socks.proxy.example.com", 40);
+
+ // Do the same, but now use the UseHTTPProxyForAllProtocols option
+ // and check that it takes effect.
+ await setupPolicyEngineWithJson({
+ policies: {
+ Proxy: {
+ HTTPProxy: "http.proxy.example.com:10",
+ // FTP support was removed in bug 1574475
+ // Setting an FTPProxy should result in a warning but should not fail
+ FTPProxy: "ftp.proxy.example.com:20",
+ SSLProxy: "ssl.proxy.example.com:30",
+ SOCKSProxy: "socks.proxy.example.com:40",
+ UseHTTPProxyForAllProtocols: true,
+ },
+ },
+ });
+
+ checkProxyPref("http", "http.proxy.example.com", 10);
+ checkProxyPref("ssl", "http.proxy.example.com", 10);
+ checkProxyPref("socks", "http.proxy.example.com", 10);
+
+ // Make sure the FTPProxy setting did nothing
+ Assert.equal(
+ Preferences.has("network.proxy.ftp"),
+ false,
+ "network.proxy.ftp should not be set"
+ );
+ Assert.equal(
+ Preferences.has("network.proxy.ftp_port"),
+ false,
+ "network.proxy.ftp_port should not be set"
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_requestedlocales.js b/browser/components/enterprisepolicies/tests/xpcshell/test_requestedlocales.js
new file mode 100644
index 0000000000..5908b2d35c
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_requestedlocales.js
@@ -0,0 +1,119 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+var { setTimeout } = ChromeUtils.importESModule(
+ "resource://gre/modules/Timer.sys.mjs"
+);
+
+const REQ_LOC_CHANGE_EVENT = "intl:requested-locales-changed";
+
+function promiseLocaleChanged(requestedLocale) {
+ return new Promise(resolve => {
+ let localeObserver = {
+ observe(aSubject, aTopic, aData) {
+ switch (aTopic) {
+ case REQ_LOC_CHANGE_EVENT:
+ let reqLocs = Services.locale.requestedLocales;
+ equal(reqLocs[0], requestedLocale);
+ Services.obs.removeObserver(localeObserver, REQ_LOC_CHANGE_EVENT);
+ resolve();
+ }
+ },
+ };
+ Services.obs.addObserver(localeObserver, REQ_LOC_CHANGE_EVENT);
+ });
+}
+
+function promiseLocaleNotChanged(requestedLocale) {
+ return new Promise(resolve => {
+ let localeObserver = {
+ observe(aSubject, aTopic, aData) {
+ switch (aTopic) {
+ case REQ_LOC_CHANGE_EVENT:
+ ok(false, "Locale should not change.");
+ Services.obs.removeObserver(localeObserver, REQ_LOC_CHANGE_EVENT);
+ resolve();
+ }
+ },
+ };
+ Services.obs.addObserver(localeObserver, REQ_LOC_CHANGE_EVENT);
+ /* eslint-disable mozilla/no-arbitrary-setTimeout */
+ setTimeout(function () {
+ Services.obs.removeObserver(localeObserver, REQ_LOC_CHANGE_EVENT);
+ resolve();
+ }, 100);
+ });
+}
+
+add_task(async function test_requested_locale_array() {
+ let originalLocales = Services.locale.requestedLocales;
+ let localePromise = promiseLocaleChanged("de");
+ await setupPolicyEngineWithJson({
+ policies: {
+ RequestedLocales: ["de"],
+ },
+ });
+ await localePromise;
+ Services.locale.requestedLocales = originalLocales;
+});
+
+add_task(async function test_requested_locale_string() {
+ let originalLocales = Services.locale.requestedLocales;
+ let localePromise = promiseLocaleChanged("fr");
+ await setupPolicyEngineWithJson({
+ policies: {
+ RequestedLocales: "fr",
+ },
+ });
+ await localePromise;
+ Services.locale.requestedLocales = originalLocales;
+});
+
+add_task(async function test_system_locale_string() {
+ let originalLocales = Services.locale.requestedLocales;
+
+ let localePromise = promiseLocaleChanged("und");
+ Services.locale.requestedLocales = ["und"];
+ await localePromise;
+
+ let systemLocale = Cc["@mozilla.org/intl/ospreferences;1"].getService(
+ Ci.mozIOSPreferences
+ ).systemLocale;
+ localePromise = promiseLocaleChanged(systemLocale);
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ RequestedLocales: "",
+ },
+ });
+ await localePromise;
+ Services.locale.requestedLocales = originalLocales;
+});
+
+add_task(async function test_user_requested_locale_change() {
+ let originalLocales = Services.locale.requestedLocales;
+ let localePromise = promiseLocaleChanged("fr");
+ await setupPolicyEngineWithJson({
+ policies: {
+ RequestedLocales: "fr",
+ },
+ });
+ await localePromise;
+
+ // Simulate user change of locale
+ localePromise = promiseLocaleChanged("de");
+ Services.locale.requestedLocales = ["de"];
+ await localePromise;
+
+ localePromise = promiseLocaleNotChanged("fr");
+ await setupPolicyEngineWithJson({
+ policies: {
+ RequestedLocales: "fr",
+ },
+ });
+ await localePromise;
+
+ Services.locale.requestedLocales = originalLocales;
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_runOnce_helper.js b/browser/components/enterprisepolicies/tests/xpcshell/test_runOnce_helper.js
new file mode 100644
index 0000000000..c8e73b3422
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_runOnce_helper.js
@@ -0,0 +1,21 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+let { runOnce } = ChromeUtils.importESModule(
+ "resource:///modules/policies/Policies.sys.mjs"
+);
+
+let runCount = 0;
+function callback() {
+ runCount++;
+}
+
+add_task(async function test_runonce_helper() {
+ runOnce("test_action", callback);
+ equal(runCount, 1, "Callback ran for the first time.");
+
+ runOnce("test_action", callback);
+ equal(runCount, 1, "Callback didn't run again.");
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_simple_pref_policies.js b/browser/components/enterprisepolicies/tests/xpcshell/test_simple_pref_policies.js
new file mode 100644
index 0000000000..8ef8b831ef
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_simple_pref_policies.js
@@ -0,0 +1,1055 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/*
+ * Use this file to add tests to policies that are
+ * simple pref flips.
+ *
+ * It's best to make a test to actually test the feature
+ * instead of the pref flip, but if that feature is well
+ * covered by tests, including that its pref actually works,
+ * it's OK to have the policy test here just to ensure
+ * that the right pref values are set.
+ */
+
+const POLICIES_TESTS = [
+ /*
+ * Example:
+ * {
+ * // Policies to be set at once through the engine
+ * policies: { "DisableFoo": true, "ConfigureBar": 42 },
+ *
+ * // Locked prefs to check
+ * lockedPrefs: { "feature.foo": false },
+ *
+ * // Unlocked prefs to check
+ * unlockedPrefs: { "bar.baz": 42 }
+ * },
+ */
+
+ // POLICY: DisableSecurityBypass
+ {
+ policies: {
+ DisableSecurityBypass: {
+ InvalidCertificate: true,
+ SafeBrowsing: true,
+ },
+ },
+ lockedPrefs: {
+ "security.certerror.hideAddException": true,
+ "browser.safebrowsing.allowOverride": false,
+ },
+ },
+
+ // POLICY: DisableBuiltinPDFViewer
+ {
+ policies: { DisableBuiltinPDFViewer: true },
+ lockedPrefs: { "pdfjs.disabled": true },
+ },
+
+ // POLICY: DisableFormHistory
+ {
+ policies: { DisableFormHistory: true },
+ lockedPrefs: { "browser.formfill.enable": false },
+ },
+
+ // POLICY: EnableTrackingProtection
+ {
+ policies: {
+ EnableTrackingProtection: {
+ Value: true,
+ },
+ },
+ unlockedPrefs: {
+ "privacy.trackingprotection.enabled": true,
+ "privacy.trackingprotection.pbmode.enabled": true,
+ },
+ },
+ {
+ policies: {
+ EnableTrackingProtection: {
+ Value: false,
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "privacy.trackingprotection.enabled": false,
+ "privacy.trackingprotection.pbmode.enabled": false,
+ },
+ },
+
+ {
+ policies: {
+ EnableTrackingProtection: {
+ Cryptomining: true,
+ Fingerprinting: true,
+ EmailTracking: true,
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "privacy.trackingprotection.cryptomining.enabled": true,
+ "privacy.trackingprotection.fingerprinting.enabled": true,
+ "privacy.trackingprotection.emailtracking.enabled": true,
+ "privacy.trackingprotection.emailtracking.pbmode.enabled": true,
+ },
+ },
+
+ // POLICY: GoToIntranetSiteForSingleWordEntryInAddressBar
+ {
+ policies: {
+ GoToIntranetSiteForSingleWordEntryInAddressBar: true,
+ },
+ lockedPrefs: {
+ "browser.fixup.dns_first_for_single_words": true,
+ },
+ },
+
+ // POLICY: OverrideFirstRunPage
+ {
+ policies: { OverrideFirstRunPage: "https://www.example.com/" },
+ lockedPrefs: { "startup.homepage_welcome_url": "https://www.example.com/" },
+ },
+
+ // POLICY: Authentication
+ {
+ policies: {
+ Authentication: {
+ SPNEGO: ["a.com", "b.com"],
+ Delegated: ["a.com", "b.com"],
+ NTLM: ["a.com", "b.com"],
+ AllowNonFQDN: {
+ SPNEGO: true,
+ NTLM: true,
+ },
+ AllowProxies: {
+ SPNEGO: false,
+ NTLM: false,
+ },
+ PrivateBrowsing: true,
+ },
+ },
+ lockedPrefs: {
+ "network.negotiate-auth.trusted-uris": "a.com, b.com",
+ "network.negotiate-auth.delegation-uris": "a.com, b.com",
+ "network.automatic-ntlm-auth.trusted-uris": "a.com, b.com",
+ "network.automatic-ntlm-auth.allow-non-fqdn": true,
+ "network.negotiate-auth.allow-non-fqdn": true,
+ "network.automatic-ntlm-auth.allow-proxies": false,
+ "network.negotiate-auth.allow-proxies": false,
+ "network.auth.private-browsing-sso": true,
+ },
+ },
+
+ // POLICY: Authentication (unlocked)
+ {
+ policies: {
+ Authentication: {
+ SPNEGO: ["a.com", "b.com"],
+ Delegated: ["a.com", "b.com"],
+ NTLM: ["a.com", "b.com"],
+ AllowNonFQDN: {
+ SPNEGO: true,
+ NTLM: true,
+ },
+ AllowProxies: {
+ SPNEGO: false,
+ NTLM: false,
+ },
+ PrivateBrowsing: true,
+ Locked: false,
+ },
+ },
+ unlockedPrefs: {
+ "network.negotiate-auth.trusted-uris": "a.com, b.com",
+ "network.negotiate-auth.delegation-uris": "a.com, b.com",
+ "network.automatic-ntlm-auth.trusted-uris": "a.com, b.com",
+ "network.automatic-ntlm-auth.allow-non-fqdn": true,
+ "network.negotiate-auth.allow-non-fqdn": true,
+ "network.automatic-ntlm-auth.allow-proxies": false,
+ "network.negotiate-auth.allow-proxies": false,
+ "network.auth.private-browsing-sso": true,
+ },
+ },
+
+ // POLICY: Certificates (true)
+ {
+ policies: {
+ Certificates: {
+ ImportEnterpriseRoots: true,
+ },
+ },
+ lockedPrefs: {
+ "security.enterprise_roots.enabled": true,
+ },
+ },
+
+ // POLICY: Certificates (false)
+ {
+ policies: {
+ Certificates: {
+ ImportEnterpriseRoots: false,
+ },
+ },
+ lockedPrefs: {
+ "security.enterprise_roots.enabled": false,
+ },
+ },
+
+ // POLICY: InstallAddons.Default (block addon installs)
+ {
+ policies: {
+ InstallAddonsPermission: {
+ Default: false,
+ },
+ },
+ lockedPrefs: {
+ "xpinstall.enabled": false,
+ "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons": false,
+ "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features": false,
+ },
+ },
+
+ // POLICY: SanitizeOnShutdown
+ {
+ policies: {
+ SanitizeOnShutdown: true,
+ },
+ lockedPrefs: {
+ "privacy.sanitize.sanitizeOnShutdown": true,
+ "privacy.clearOnShutdown.cache": true,
+ "privacy.clearOnShutdown.cookies": true,
+ "privacy.clearOnShutdown.downloads": true,
+ "privacy.clearOnShutdown.formdata": true,
+ "privacy.clearOnShutdown.history": true,
+ "privacy.clearOnShutdown.sessions": true,
+ "privacy.clearOnShutdown.siteSettings": true,
+ "privacy.clearOnShutdown.offlineApps": true,
+ },
+ },
+
+ {
+ policies: {
+ SanitizeOnShutdown: false,
+ },
+ lockedPrefs: {
+ "privacy.sanitize.sanitizeOnShutdown": false,
+ "privacy.clearOnShutdown.cache": false,
+ "privacy.clearOnShutdown.cookies": false,
+ "privacy.clearOnShutdown.downloads": false,
+ "privacy.clearOnShutdown.formdata": false,
+ "privacy.clearOnShutdown.history": false,
+ "privacy.clearOnShutdown.sessions": false,
+ "privacy.clearOnShutdown.siteSettings": false,
+ "privacy.clearOnShutdown.offlineApps": false,
+ },
+ },
+
+ {
+ policies: {
+ SanitizeOnShutdown: {
+ Cache: true,
+ },
+ },
+ lockedPrefs: {
+ "privacy.sanitize.sanitizeOnShutdown": true,
+ "privacy.clearOnShutdown.cache": true,
+ "privacy.clearOnShutdown.cookies": false,
+ "privacy.clearOnShutdown.downloads": false,
+ "privacy.clearOnShutdown.formdata": false,
+ "privacy.clearOnShutdown.history": false,
+ "privacy.clearOnShutdown.sessions": false,
+ },
+ },
+
+ {
+ policies: {
+ SanitizeOnShutdown: {
+ Cookies: true,
+ },
+ },
+ lockedPrefs: {
+ "privacy.sanitize.sanitizeOnShutdown": true,
+ "privacy.clearOnShutdown.cache": false,
+ "privacy.clearOnShutdown.cookies": true,
+ "privacy.clearOnShutdown.downloads": false,
+ "privacy.clearOnShutdown.formdata": false,
+ "privacy.clearOnShutdown.history": false,
+ "privacy.clearOnShutdown.sessions": false,
+ },
+ },
+
+ {
+ policies: {
+ SanitizeOnShutdown: {
+ Downloads: true,
+ },
+ },
+ lockedPrefs: {
+ "privacy.sanitize.sanitizeOnShutdown": true,
+ "privacy.clearOnShutdown.cache": false,
+ "privacy.clearOnShutdown.cookies": false,
+ "privacy.clearOnShutdown.downloads": true,
+ "privacy.clearOnShutdown.formdata": false,
+ "privacy.clearOnShutdown.history": false,
+ "privacy.clearOnShutdown.sessions": false,
+ },
+ },
+
+ {
+ policies: {
+ SanitizeOnShutdown: {
+ FormData: true,
+ },
+ },
+ lockedPrefs: {
+ "privacy.sanitize.sanitizeOnShutdown": true,
+ "privacy.clearOnShutdown.cache": false,
+ "privacy.clearOnShutdown.cookies": false,
+ "privacy.clearOnShutdown.downloads": false,
+ "privacy.clearOnShutdown.formdata": true,
+ "privacy.clearOnShutdown.history": false,
+ "privacy.clearOnShutdown.sessions": false,
+ },
+ },
+
+ {
+ policies: {
+ SanitizeOnShutdown: {
+ History: true,
+ },
+ },
+ lockedPrefs: {
+ "privacy.sanitize.sanitizeOnShutdown": true,
+ "privacy.clearOnShutdown.cache": false,
+ "privacy.clearOnShutdown.cookies": false,
+ "privacy.clearOnShutdown.downloads": false,
+ "privacy.clearOnShutdown.formdata": false,
+ "privacy.clearOnShutdown.history": true,
+ "privacy.clearOnShutdown.sessions": false,
+ },
+ },
+
+ {
+ policies: {
+ SanitizeOnShutdown: {
+ Sessions: true,
+ },
+ },
+ lockedPrefs: {
+ "privacy.sanitize.sanitizeOnShutdown": true,
+ "privacy.clearOnShutdown.cache": false,
+ "privacy.clearOnShutdown.cookies": false,
+ "privacy.clearOnShutdown.downloads": false,
+ "privacy.clearOnShutdown.formdata": false,
+ "privacy.clearOnShutdown.history": false,
+ "privacy.clearOnShutdown.sessions": true,
+ },
+ },
+
+ {
+ policies: {
+ SanitizeOnShutdown: {
+ SiteSettings: true,
+ },
+ },
+ lockedPrefs: {
+ "privacy.sanitize.sanitizeOnShutdown": true,
+ "privacy.clearOnShutdown.cache": false,
+ "privacy.clearOnShutdown.cookies": false,
+ "privacy.clearOnShutdown.downloads": false,
+ "privacy.clearOnShutdown.formdata": false,
+ "privacy.clearOnShutdown.history": false,
+ "privacy.clearOnShutdown.sessions": false,
+ "privacy.clearOnShutdown.siteSettings": true,
+ },
+ },
+
+ {
+ policies: {
+ SanitizeOnShutdown: {
+ OfflineApps: true,
+ },
+ },
+ lockedPrefs: {
+ "privacy.sanitize.sanitizeOnShutdown": true,
+ "privacy.clearOnShutdown.cache": false,
+ "privacy.clearOnShutdown.cookies": false,
+ "privacy.clearOnShutdown.downloads": false,
+ "privacy.clearOnShutdown.formdata": false,
+ "privacy.clearOnShutdown.history": false,
+ "privacy.clearOnShutdown.sessions": false,
+ "privacy.clearOnShutdown.offlineApps": true,
+ },
+ },
+
+ // POLICY: SanitizeOnShutdown using Locked
+ {
+ policies: {
+ SanitizeOnShutdown: {
+ Cache: true,
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "privacy.sanitize.sanitizeOnShutdown": true,
+ "privacy.clearOnShutdown.cache": true,
+ },
+ unlockedPrefs: {
+ "privacy.clearOnShutdown.cookies": false,
+ "privacy.clearOnShutdown.downloads": false,
+ "privacy.clearOnShutdown.formdata": false,
+ "privacy.clearOnShutdown.history": false,
+ "privacy.clearOnShutdown.sessions": false,
+ },
+ },
+
+ {
+ policies: {
+ SanitizeOnShutdown: {
+ Cache: true,
+ Cookies: false,
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "privacy.sanitize.sanitizeOnShutdown": true,
+ "privacy.clearOnShutdown.cache": true,
+ "privacy.clearOnShutdown.cookies": false,
+ },
+ unlockedPrefs: {
+ "privacy.clearOnShutdown.downloads": false,
+ "privacy.clearOnShutdown.formdata": false,
+ "privacy.clearOnShutdown.history": false,
+ "privacy.clearOnShutdown.sessions": false,
+ },
+ },
+
+ {
+ policies: {
+ SanitizeOnShutdown: {
+ Cache: true,
+ Locked: false,
+ },
+ },
+ unlockedPrefs: {
+ "privacy.sanitize.sanitizeOnShutdown": true,
+ "privacy.clearOnShutdown.cache": true,
+ "privacy.clearOnShutdown.cookies": false,
+ "privacy.clearOnShutdown.downloads": false,
+ "privacy.clearOnShutdown.formdata": false,
+ "privacy.clearOnShutdown.history": false,
+ "privacy.clearOnShutdown.sessions": false,
+ },
+ },
+
+ // POLICY: DNSOverHTTPS Unlocked
+ {
+ policies: {
+ DNSOverHTTPS: {
+ Enabled: false,
+ ProviderURL: "https://example.com/provider",
+ ExcludedDomains: ["example.com", "example.org"],
+ },
+ },
+ unlockedPrefs: {
+ "network.trr.mode": 5,
+ "network.trr.uri": "https://example.com/provider",
+ "network.trr.excluded-domains": "example.com,example.org",
+ },
+ },
+
+ // POLICY: DNSOverHTTPS Fallback off
+ {
+ policies: {
+ DNSOverHTTPS: {
+ Enabled: true,
+ Fallback: false,
+ },
+ },
+ unlockedPrefs: {
+ "network.trr.mode": 3,
+ },
+ },
+
+ // POLICY: DNSOverHTTPS Locked
+ {
+ policies: {
+ DNSOverHTTPS: {
+ Enabled: true,
+ ProviderURL: "https://example.com/provider",
+ ExcludedDomains: ["example.com", "example.org"],
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "network.trr.mode": 2,
+ "network.trr.uri": "https://example.com/provider",
+ "network.trr.excluded-domains": "example.com,example.org",
+ },
+ },
+
+ // POLICY: SSLVersionMin/SSLVersionMax (1)
+ {
+ policies: {
+ SSLVersionMin: "tls1",
+ SSLVersionMax: "tls1.1",
+ },
+ lockedPrefs: {
+ "security.tls.version.min": 1,
+ "security.tls.version.max": 2,
+ },
+ },
+
+ // POLICY: SSLVersionMin/SSLVersionMax (2)
+ {
+ policies: {
+ SSLVersionMin: "tls1.2",
+ SSLVersionMax: "tls1.3",
+ },
+ lockedPrefs: {
+ "security.tls.version.min": 3,
+ "security.tls.version.max": 4,
+ },
+ },
+
+ // POLICY: CaptivePortal
+ {
+ policies: {
+ CaptivePortal: false,
+ },
+ lockedPrefs: {
+ "network.captive-portal-service.enabled": false,
+ },
+ },
+
+ // POLICY: NetworkPrediction
+ {
+ policies: {
+ NetworkPrediction: false,
+ },
+ lockedPrefs: {
+ "network.dns.disablePrefetch": true,
+ "network.dns.disablePrefetchFromHTTPS": true,
+ },
+ },
+
+ // POLICY: ExtensionUpdate
+ {
+ policies: {
+ ExtensionUpdate: false,
+ },
+ lockedPrefs: {
+ "extensions.update.enabled": false,
+ },
+ },
+
+ // POLICY: DisableShield
+ {
+ policies: {
+ DisableFirefoxStudies: true,
+ },
+ lockedPrefs: {
+ "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons": false,
+ "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features": false,
+ },
+ },
+
+ // POLICY: NewTabPage
+ {
+ policies: {
+ NewTabPage: false,
+ },
+ lockedPrefs: {
+ "browser.newtabpage.enabled": false,
+ },
+ },
+
+ // POLICY: SearchSuggestEnabled
+ {
+ policies: {
+ SearchSuggestEnabled: false,
+ },
+ lockedPrefs: {
+ "browser.urlbar.suggest.searches": false,
+ "browser.search.suggest.enabled": false,
+ },
+ },
+
+ // POLICY: FirefoxHome
+ {
+ policies: {
+ FirefoxHome: {
+ Pocket: false,
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "browser.newtabpage.activity-stream.feeds.system.topstories": false,
+ },
+ },
+
+ // POLICY: OfferToSaveLoginsDefault
+ {
+ policies: {
+ OfferToSaveLoginsDefault: false,
+ },
+ unlockedPrefs: {
+ "signon.rememberSignons": false,
+ },
+ },
+
+ // POLICY: RememberPasswords
+ {
+ policies: { OfferToSaveLogins: false },
+ lockedPrefs: { "signon.rememberSignons": false },
+ },
+ {
+ policies: { OfferToSaveLogins: true },
+ lockedPrefs: { "signon.rememberSignons": true },
+ },
+
+ // POLICY: UserMessaging
+ {
+ policies: {
+ UserMessaging: {
+ WhatsNew: false,
+ SkipOnboarding: true,
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "browser.messaging-system.whatsNewPanel.enabled": false,
+ "browser.aboutwelcome.enabled": false,
+ },
+ },
+
+ // POLICY: UserMessaging->SkipOnboarding false (bug 1697566)
+ {
+ policies: {
+ UserMessaging: {
+ SkipOnboarding: false,
+ Locked: false,
+ },
+ },
+ unlockedPrefs: {
+ "browser.aboutwelcome.enabled": true,
+ },
+ },
+
+ {
+ policies: {
+ UserMessaging: {
+ ExtensionRecommendations: false,
+ Locked: false,
+ },
+ },
+ unlockedPrefs: {
+ "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons": false,
+ },
+ },
+
+ {
+ policies: {
+ UserMessaging: {
+ FeatureRecommendations: false,
+ Locked: false,
+ },
+ },
+ unlockedPrefs: {
+ "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features": false,
+ },
+ },
+
+ // POLICY: Permissions->Autoplay
+ {
+ policies: {
+ Permissions: {
+ Autoplay: {
+ Default: "block-audio-video",
+ },
+ },
+ },
+ unlockedPrefs: {
+ "media.autoplay.default": 5,
+ },
+ },
+
+ {
+ policies: {
+ Permissions: {
+ Autoplay: {
+ Default: "allow-audio-video",
+ Locked: true,
+ },
+ },
+ },
+ lockedPrefs: {
+ "media.autoplay.default": 0,
+ },
+ },
+
+ {
+ policies: {
+ Permissions: {
+ Autoplay: {
+ Default: "block-audio",
+ Locked: false,
+ },
+ },
+ },
+ unlockedPrefs: {
+ "media.autoplay.default": 1,
+ },
+ },
+
+ // POLICY: LegacySameSiteCookieBehaviorEnabled
+
+ {
+ policies: {
+ LegacySameSiteCookieBehaviorEnabled: true,
+ },
+ unlockedPrefs: {
+ "network.cookie.sameSite.laxByDefault": false,
+ },
+ },
+
+ // POLICY: LegacySameSiteCookieBehaviorEnabledForDomainList
+
+ {
+ policies: {
+ LegacySameSiteCookieBehaviorEnabledForDomainList: [
+ "example.com",
+ "example.org",
+ ],
+ },
+ unlockedPrefs: {
+ "network.cookie.sameSite.laxByDefault.disabledHosts":
+ "example.com,example.org",
+ },
+ },
+
+ // POLICY: EncryptedMediaExtensions
+
+ {
+ policies: {
+ EncryptedMediaExtensions: {
+ Enabled: false,
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "media.eme.enabled": false,
+ },
+ },
+
+ // POLICY: PDFjs
+
+ {
+ policies: {
+ PDFjs: {
+ Enabled: false,
+ },
+ },
+ lockedPrefs: {
+ "pdfjs.disabled": true,
+ },
+ },
+
+ {
+ policies: {
+ PDFjs: {
+ Enabled: true,
+ EnablePermissions: true,
+ },
+ },
+ lockedPrefs: {
+ "pdfjs.disabled": false,
+ "pdfjs.enablePermissions": true,
+ },
+ },
+
+ {
+ policies: {
+ PDFjs: {
+ Enabled: true,
+ EnablePermissions: false,
+ },
+ },
+ lockedPrefs: {
+ "pdfjs.disabled": false,
+ "pdfjs.enablePermissions": false,
+ },
+ },
+
+ // POLICY: PictureInPicture
+
+ {
+ policies: {
+ PictureInPicture: {
+ Enabled: false,
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "media.videocontrols.picture-in-picture.video-toggle.enabled": false,
+ },
+ },
+
+ // POLICY: DisabledCiphers
+ {
+ policies: {
+ DisabledCiphers: {
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: false,
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: false,
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: false,
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: false,
+ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: false,
+ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: false,
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: false,
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: false,
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: false,
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: false,
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA: false,
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA: false,
+ TLS_RSA_WITH_AES_128_GCM_SHA256: false,
+ TLS_RSA_WITH_AES_256_GCM_SHA384: false,
+ TLS_RSA_WITH_AES_128_CBC_SHA: false,
+ TLS_RSA_WITH_AES_256_CBC_SHA: false,
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA: false,
+ },
+ },
+ lockedPrefs: {
+ "security.ssl3.ecdhe_rsa_aes_128_gcm_sha256": true,
+ "security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256": true,
+ "security.ssl3.ecdhe_ecdsa_chacha20_poly1305_sha256": true,
+ "security.ssl3.ecdhe_rsa_chacha20_poly1305_sha256": true,
+ "security.ssl3.ecdhe_ecdsa_aes_256_gcm_sha384": true,
+ "security.ssl3.ecdhe_rsa_aes_256_gcm_sha384": true,
+ "security.ssl3.ecdhe_rsa_aes_128_sha": true,
+ "security.ssl3.ecdhe_ecdsa_aes_128_sha": true,
+ "security.ssl3.ecdhe_rsa_aes_256_sha": true,
+ "security.ssl3.ecdhe_ecdsa_aes_256_sha": true,
+ "security.ssl3.dhe_rsa_aes_128_sha": true,
+ "security.ssl3.dhe_rsa_aes_256_sha": true,
+ "security.ssl3.rsa_aes_128_gcm_sha256": true,
+ "security.ssl3.rsa_aes_256_gcm_sha384": true,
+ "security.ssl3.rsa_aes_128_sha": true,
+ "security.ssl3.rsa_aes_256_sha": true,
+ "security.ssl3.deprecated.rsa_des_ede3_sha": true,
+ },
+ },
+
+ {
+ policies: {
+ DisabledCiphers: {
+ TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: true,
+ TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: true,
+ TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: true,
+ TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: true,
+ TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: true,
+ TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: true,
+ TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: true,
+ TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: true,
+ TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: true,
+ TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: true,
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA: true,
+ TLS_DHE_RSA_WITH_AES_256_CBC_SHA: true,
+ TLS_RSA_WITH_AES_128_GCM_SHA256: true,
+ TLS_RSA_WITH_AES_256_GCM_SHA384: true,
+ TLS_RSA_WITH_AES_128_CBC_SHA: true,
+ TLS_RSA_WITH_AES_256_CBC_SHA: true,
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA: true,
+ },
+ },
+ lockedPrefs: {
+ "security.ssl3.ecdhe_rsa_aes_128_gcm_sha256": false,
+ "security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256": false,
+ "security.ssl3.ecdhe_ecdsa_chacha20_poly1305_sha256": false,
+ "security.ssl3.ecdhe_rsa_chacha20_poly1305_sha256": false,
+ "security.ssl3.ecdhe_ecdsa_aes_256_gcm_sha384": false,
+ "security.ssl3.ecdhe_rsa_aes_256_gcm_sha384": false,
+ "security.ssl3.ecdhe_rsa_aes_128_sha": false,
+ "security.ssl3.ecdhe_ecdsa_aes_128_sha": false,
+ "security.ssl3.ecdhe_rsa_aes_256_sha": false,
+ "security.ssl3.ecdhe_ecdsa_aes_256_sha": false,
+ "security.ssl3.dhe_rsa_aes_128_sha": false,
+ "security.ssl3.dhe_rsa_aes_256_sha": false,
+ "security.ssl3.rsa_aes_128_gcm_sha256": false,
+ "security.ssl3.rsa_aes_256_gcm_sha384": false,
+ "security.ssl3.rsa_aes_128_sha": false,
+ "security.ssl3.rsa_aes_256_sha": false,
+ "security.ssl3.deprecated.rsa_des_ede3_sha": false,
+ },
+ },
+
+ {
+ policies: {
+ WindowsSSO: true,
+ },
+ lockedPrefs: {
+ "network.http.windows-sso.enabled": true,
+ },
+ },
+
+ {
+ policies: {
+ Cookies: {
+ Behavior: "accept",
+ BehaviorPrivateBrowsing: "reject-foreign",
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "network.cookie.cookieBehavior": 0,
+ "network.cookie.cookieBehavior.pbmode": 1,
+ },
+ },
+
+ {
+ policies: {
+ Cookies: {
+ Behavior: "reject-foreign",
+ BehaviorPrivateBrowsing: "reject",
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "network.cookie.cookieBehavior": 1,
+ "network.cookie.cookieBehavior.pbmode": 2,
+ },
+ },
+
+ {
+ policies: {
+ Cookies: {
+ Behavior: "reject",
+ BehaviorPrivateBrowsing: "limit-foreign",
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "network.cookie.cookieBehavior": 2,
+ "network.cookie.cookieBehavior.pbmode": 3,
+ },
+ },
+
+ {
+ policies: {
+ Cookies: {
+ Behavior: "limit-foreign",
+ BehaviorPrivateBrowsing: "reject-tracker",
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "network.cookie.cookieBehavior": 3,
+ "network.cookie.cookieBehavior.pbmode": 4,
+ },
+ },
+
+ {
+ policies: {
+ Cookies: {
+ Behavior: "reject-tracker",
+ BehaviorPrivateBrowsing: "reject-tracker-and-partition-foreign",
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "network.cookie.cookieBehavior": 4,
+ "network.cookie.cookieBehavior.pbmode": 5,
+ },
+ },
+ {
+ policies: {
+ Cookies: {
+ Behavior: "reject-tracker-and-partition-foreign",
+ BehaviorPrivateBrowsing: "accept",
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "network.cookie.cookieBehavior": 5,
+ "network.cookie.cookieBehavior.pbmode": 0,
+ },
+ },
+
+ {
+ policies: {
+ UseSystemPrintDialog: true,
+ },
+ lockedPrefs: {
+ "print.prefer_system_dialog": true,
+ },
+ },
+
+ // Bug 1820195
+ {
+ policies: {
+ Preferences: {
+ "pdfjs.cursorToolOnLoad": {
+ Value: 1,
+ Status: "default",
+ },
+ "pdfjs.sidebarViewOnLoad": {
+ Value: 0,
+ Status: "default",
+ },
+ },
+ },
+ unlockedPrefs: {
+ "pdfjs.cursorToolOnLoad": 1,
+ "pdfjs.sidebarViewOnLoad": 0,
+ },
+ },
+
+ // Bug 1772503
+ {
+ policies: {
+ DisableFirefoxStudies: true,
+ },
+ lockedPrefs: {
+ "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons": false,
+ "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features": false,
+ },
+ },
+ {
+ policies: {
+ Preferences: {
+ "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons": {
+ Value: true,
+ },
+ "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features": {
+ Value: true,
+ },
+ },
+ },
+ lockedPrefs: {
+ "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons": true,
+ "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features": true,
+ },
+ },
+];
+
+add_task(async function test_policy_simple_prefs() {
+ for (let test of POLICIES_TESTS) {
+ await setupPolicyEngineWithJson({
+ policies: test.policies,
+ });
+
+ info("Checking policy: " + Object.keys(test.policies)[0]);
+
+ for (let [prefName, prefValue] of Object.entries(test.lockedPrefs || {})) {
+ checkLockedPref(prefName, prefValue);
+ }
+
+ for (let [prefName, prefValue] of Object.entries(
+ test.unlockedPrefs || {}
+ )) {
+ checkUnlockedPref(prefName, prefValue);
+ }
+ }
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_sorted_alphabetically.js b/browser/components/enterprisepolicies/tests/xpcshell/test_sorted_alphabetically.js
new file mode 100644
index 0000000000..0d246c850c
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_sorted_alphabetically.js
@@ -0,0 +1,48 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+function checkArrayIsSorted(array, msg) {
+ let sorted = true;
+ let sortedArray = array.slice().sort(function (a, b) {
+ return a.localeCompare(b);
+ });
+
+ for (let i = 0; i < array.length; i++) {
+ if (array[i] != sortedArray[i]) {
+ sorted = false;
+ break;
+ }
+ }
+ ok(sorted, msg);
+}
+
+add_task(async function test_policies_sorted() {
+ let { schema } = ChromeUtils.importESModule(
+ "resource:///modules/policies/schema.sys.mjs"
+ );
+ let { Policies } = ChromeUtils.importESModule(
+ "resource:///modules/policies/Policies.sys.mjs"
+ );
+
+ checkArrayIsSorted(
+ Object.keys(schema.properties),
+ "policies-schema.json is alphabetically sorted."
+ );
+ checkArrayIsSorted(
+ Object.keys(Policies),
+ "Policies.jsm is alphabetically sorted."
+ );
+});
+
+add_task(async function check_naming_conventions() {
+ let { schema } = ChromeUtils.importESModule(
+ "resource:///modules/policies/schema.sys.mjs"
+ );
+ equal(
+ Object.keys(schema.properties).some(key => key.includes("__")),
+ false,
+ "Can't use __ in a policy name as it's used as a delimiter"
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/test_telemetry.js b/browser/components/enterprisepolicies/tests/xpcshell/test_telemetry.js
new file mode 100644
index 0000000000..537465ebd5
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_telemetry.js
@@ -0,0 +1,102 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const { TelemetryTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/TelemetryTestUtils.sys.mjs"
+);
+const { AppConstants } = ChromeUtils.importESModule(
+ "resource://gre/modules/AppConstants.sys.mjs"
+);
+
+add_task(async function test_telemetry_basic() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisableAboutSupport: true,
+ },
+ });
+
+ TelemetryTestUtils.assertScalar(
+ TelemetryTestUtils.getProcessScalars("parent"),
+ "policies.is_enterprise",
+ true
+ );
+});
+
+add_task(async function test_telemetry_just_roots() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Certificates: {
+ ImportEnterpriseRoots: true,
+ },
+ },
+ });
+
+ TelemetryTestUtils.assertScalar(
+ TelemetryTestUtils.getProcessScalars("parent"),
+ "policies.is_enterprise",
+ AppConstants.IS_ESR
+ );
+});
+
+add_task(async function test_telemetry_roots_plus_policy() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisableAboutSupport: true,
+ Certificates: {
+ ImportEnterpriseRoots: true,
+ },
+ },
+ });
+
+ TelemetryTestUtils.assertScalar(
+ TelemetryTestUtils.getProcessScalars("parent"),
+ "policies.is_enterprise",
+ true
+ );
+});
+
+add_task(async function test_telemetry_esr() {
+ await setupPolicyEngineWithJson({});
+ TelemetryTestUtils.assertScalar(
+ TelemetryTestUtils.getProcessScalars("parent"),
+ "policies.is_enterprise",
+ AppConstants.IS_ESR
+ );
+});
+
+add_task(async function test_telemetry_esr_mac_eol() {
+ Services.prefs
+ .getDefaultBranch(null)
+ .setCharPref("distribution.id", "mozilla-mac-eol-esr115");
+ await setupPolicyEngineWithJson({});
+ TelemetryTestUtils.assertScalar(
+ TelemetryTestUtils.getProcessScalars("parent"),
+ "policies.is_enterprise",
+ false
+ );
+});
+
+add_task(async function test_telemetry_esr_win_eol() {
+ Services.prefs
+ .getDefaultBranch(null)
+ .setCharPref("distribution.id", "mozilla-win-eol-esr115");
+ await setupPolicyEngineWithJson({});
+ TelemetryTestUtils.assertScalar(
+ TelemetryTestUtils.getProcessScalars("parent"),
+ "policies.is_enterprise",
+ false
+ );
+});
+
+add_task(async function test_telemetry_esr_distro() {
+ Services.prefs
+ .getDefaultBranch(null)
+ .setCharPref("distribution.id", "any-other-distribution-id");
+ await setupPolicyEngineWithJson({});
+ TelemetryTestUtils.assertScalar(
+ TelemetryTestUtils.getProcessScalars("parent"),
+ "policies.is_enterprise",
+ AppConstants.IS_ESR
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/xpcshell/xpcshell.toml b/browser/components/enterprisepolicies/tests/xpcshell/xpcshell.toml
new file mode 100644
index 0000000000..69dd3e5103
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/xpcshell.toml
@@ -0,0 +1,55 @@
+[DEFAULT]
+skip-if = ["os == 'android'"] # bug 1730213
+firefox-appdir = "browser"
+head = "head.js"
+support-files = ["policytest_v0.1.xpi"]
+
+["test_3rdparty.js"]
+
+["test_addon_update.js"]
+
+["test_appupdatepin.js"]
+
+["test_appupdateurl.js"]
+
+["test_bug1658259.js"]
+
+["test_cleanup.js"]
+
+["test_clear_blocked_cookies.js"]
+
+["test_containers.js"]
+
+["test_defaultbrowsercheck.js"]
+
+["test_empty_policy.js"]
+
+["test_exempt_domain_file_type_pairs_from_file_type_download_warnings.js"]
+
+["test_extensions.js"]
+
+["test_extensionsettings.js"]
+
+["test_macosparser_unflatten.js"]
+run-if = ["os == 'mac'"]
+
+["test_permissions.js"]
+
+["test_policy_search_engine.js"]
+
+["test_popups_cookies_addons.js"]
+support-files = ["config_popups_cookies_addons.json"]
+
+["test_preferences.js"]
+
+["test_proxy.js"]
+
+["test_requestedlocales.js"]
+
+["test_runOnce_helper.js"]
+
+["test_simple_pref_policies.js"]
+
+["test_sorted_alphabetically.js"]
+
+["test_telemetry.js"]