summaryrefslogtreecommitdiffstats
path: root/browser/components/enterprisepolicies/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /browser/components/enterprisepolicies/tests
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'browser/components/enterprisepolicies/tests')
-rw-r--r--browser/components/enterprisepolicies/tests/browser/301.sjs8
-rw-r--r--browser/components/enterprisepolicies/tests/browser/302.sjs8
-rw-r--r--browser/components/enterprisepolicies/tests/browser/404.sjs3
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser.ini73
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policies_getActivePolicies.js52
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policies_notice_in_aboutpreferences.js19
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policies_setAndLockPref_API.js179
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_app_auto_update.js77
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_app_update.js41
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_background_app_update.js99
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_block_about.js50
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_block_about_support.js41
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_cookie_settings.js367
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_disable_feedback_commands.js63
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_disable_fxaccounts.js16
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_disable_masterpassword.js90
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_disable_password_reveal.js43
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_disable_pocket.js29
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_disable_popup_blocker.js149
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_disable_privatebrowsing.js32
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_disable_profile_import.js100
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_disable_profile_reset.js80
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_disable_safemode.js57
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_disable_shield.js68
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_disable_telemetry.js28
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_display_bookmarks.js86
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_display_menu.js84
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_downloads.js147
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_extensions.js117
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_extensionsettings.js261
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_extensionsettings2.js71
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_firefoxhome.js132
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_firefoxsuggest.js63
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_handlers.js183
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_masterpassword.js95
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_masterpassword_aboutlogins.js76
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_masterpassword_doorhanger.js76
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_offertosavelogins.js23
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_override_postupdatepage.js132
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_pageinfo_permissions.js76
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_passwordmanager.js25
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_search_engine.js109
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_searchbar.js36
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_set_homepage.js115
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_set_startpage.js68
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_support_menu.js68
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_usermessaging.js21
-rw-r--r--browser/components/enterprisepolicies/tests/browser/browser_policy_websitefilter.js186
-rw-r--r--browser/components/enterprisepolicies/tests/browser/disable_app_update/browser.ini9
-rw-r--r--browser/components/enterprisepolicies/tests/browser/disable_app_update/browser_policy_disable_app_update.js121
-rw-r--r--browser/components/enterprisepolicies/tests/browser/disable_app_update/config_disable_app_update.json5
-rw-r--r--browser/components/enterprisepolicies/tests/browser/disable_default_bookmarks/bookmarks_policies.json5
-rw-r--r--browser/components/enterprisepolicies/tests/browser/disable_default_bookmarks/browser.ini7
-rw-r--r--browser/components/enterprisepolicies/tests/browser/disable_default_bookmarks/browser_policy_no_default_bookmarks.js24
-rw-r--r--browser/components/enterprisepolicies/tests/browser/disable_developer_tools/browser.ini7
-rw-r--r--browser/components/enterprisepolicies/tests/browser/disable_developer_tools/browser_policy_disable_developer_tools.js87
-rw-r--r--browser/components/enterprisepolicies/tests/browser/disable_developer_tools/config_disable_developer_tools.json5
-rw-r--r--browser/components/enterprisepolicies/tests/browser/disable_forget_button/browser.ini7
-rw-r--r--browser/components/enterprisepolicies/tests/browser/disable_forget_button/browser_policy_disable_forgetbutton.js9
-rw-r--r--browser/components/enterprisepolicies/tests/browser/disable_forget_button/forget_button.json5
-rw-r--r--browser/components/enterprisepolicies/tests/browser/disable_fxscreenshots/browser.ini8
-rw-r--r--browser/components/enterprisepolicies/tests/browser/disable_fxscreenshots/browser_policy_disable_fxscreenshots.js35
-rw-r--r--browser/components/enterprisepolicies/tests/browser/disable_fxscreenshots/config_disable_fxscreenshots.json5
-rw-r--r--browser/components/enterprisepolicies/tests/browser/extensionsettings.html28
-rw-r--r--browser/components/enterprisepolicies/tests/browser/hardware_acceleration/browser.ini7
-rw-r--r--browser/components/enterprisepolicies/tests/browser/hardware_acceleration/browser_policy_hardware_acceleration.js13
-rw-r--r--browser/components/enterprisepolicies/tests/browser/hardware_acceleration/disable_hardware_acceleration.json5
-rw-r--r--browser/components/enterprisepolicies/tests/browser/head.js253
-rw-r--r--browser/components/enterprisepolicies/tests/browser/homepage_button/browser.ini7
-rw-r--r--browser/components/enterprisepolicies/tests/browser/homepage_button/browser_show_home_button_with_homepage_policy.js9
-rw-r--r--browser/components/enterprisepolicies/tests/browser/homepage_button/homepage_policies.json7
-rw-r--r--browser/components/enterprisepolicies/tests/browser/managedbookmarks/browser.ini8
-rw-r--r--browser/components/enterprisepolicies/tests/browser/managedbookmarks/browser_policy_managedbookmarks.js210
-rw-r--r--browser/components/enterprisepolicies/tests/browser/managedbookmarks/managedbookmarks.json44
-rw-r--r--browser/components/enterprisepolicies/tests/browser/opensearch.html8
-rw-r--r--browser/components/enterprisepolicies/tests/browser/opensearchEngine.xml12
-rw-r--r--browser/components/enterprisepolicies/tests/browser/policy_websitefilter_block.html10
-rw-r--r--browser/components/enterprisepolicies/tests/browser/policy_websitefilter_exception.html10
-rw-r--r--browser/components/enterprisepolicies/tests/browser/policy_websitefilter_savelink.html11
-rw-r--r--browser/components/enterprisepolicies/tests/browser/policytest_v0.1.xpibin0 -> 305 bytes
-rw-r--r--browser/components/enterprisepolicies/tests/browser/policytest_v0.2.xpibin0 -> 297 bytes
-rw-r--r--browser/components/enterprisepolicies/tests/browser/show_home_button/browser.ini5
-rw-r--r--browser/components/enterprisepolicies/tests/browser/show_home_button/browser_policy_show_home_button.js38
-rw-r--r--browser/components/enterprisepolicies/tests/browser/show_home_button/show_home_button_policies.json7
-rw-r--r--browser/components/enterprisepolicies/tests/moz.build20
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/config_popups_cookies_addons.json17
-rw-r--r--browser/components/enterprisepolicies/tests/xpcshell/head.js145
-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.js246
-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.js1044
-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.ini33
113 files changed, 9136 insertions, 0 deletions
diff --git a/browser/components/enterprisepolicies/tests/browser/301.sjs b/browser/components/enterprisepolicies/tests/browser/301.sjs
new file mode 100644
index 0000000000..adf0f0891d
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/301.sjs
@@ -0,0 +1,8 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response) {
+ response.setStatusLine(request.httpVersion, 301, "Moved Permanently");
+ response.setHeader("Location", "policy_websitefilter_block.html");
+}
diff --git a/browser/components/enterprisepolicies/tests/browser/302.sjs b/browser/components/enterprisepolicies/tests/browser/302.sjs
new file mode 100644
index 0000000000..4aee85baac
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/302.sjs
@@ -0,0 +1,8 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+function handleRequest(request, response) {
+ response.setStatusLine(request.httpVersion, 302, "Moved Temporarily");
+ response.setHeader("Location", "policy_websitefilter_block.html");
+}
diff --git a/browser/components/enterprisepolicies/tests/browser/404.sjs b/browser/components/enterprisepolicies/tests/browser/404.sjs
new file mode 100644
index 0000000000..923e8082b1
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/404.sjs
@@ -0,0 +1,3 @@
+function handleRequest(request, response) {
+ response.setStatusLine(request.httpVersion, 404, "Not Found");
+}
diff --git a/browser/components/enterprisepolicies/tests/browser/browser.ini b/browser/components/enterprisepolicies/tests/browser/browser.ini
new file mode 100644
index 0000000000..baba782d11
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser.ini
@@ -0,0 +1,73 @@
+[DEFAULT]
+support-files =
+ head.js
+ opensearch.html
+ opensearchEngine.xml
+ policytest_v0.1.xpi
+ policytest_v0.2.xpi
+ policy_websitefilter_block.html
+ policy_websitefilter_exception.html
+ policy_websitefilter_savelink.html
+ ../../../../../toolkit/components/antitracking/test/browser/page.html
+ ../../../../../toolkit/components/antitracking/test/browser/subResources.sjs
+ extensionsettings.html
+ 301.sjs
+ 302.sjs
+ 404.sjs
+
+[browser_policies_getActivePolicies.js]
+skip-if = os != 'mac'
+[browser_policies_notice_in_aboutpreferences.js]
+[browser_policies_setAndLockPref_API.js]
+[browser_policy_app_auto_update.js]
+skip-if = os == 'win' && msix # Updater is disabled in MSIX builds
+[browser_policy_app_update.js]
+skip-if = os == 'win' && msix # Updater is disabled in MSIX builds
+[browser_policy_background_app_update.js]
+skip-if = os == 'win' && msix # Updater is disabled in MSIX builds
+[browser_policy_block_about.js]
+[browser_policy_block_about_support.js]
+[browser_policy_block_set_desktop_background.js]
+[browser_policy_bookmarks.js]
+[browser_policy_cookie_settings.js]
+https_first_disabled = true
+[browser_policy_disable_feedback_commands.js]
+[browser_policy_disable_fxaccounts.js]
+skip-if = (verify && debug && (os == 'mac'))
+[browser_policy_disable_masterpassword.js]
+[browser_policy_disable_password_reveal.js]
+[browser_policy_disable_pocket.js]
+[browser_policy_disable_popup_blocker.js]
+[browser_policy_disable_privatebrowsing.js]
+[browser_policy_disable_profile_import.js]
+[browser_policy_disable_profile_reset.js]
+[browser_policy_disable_safemode.js]
+[browser_policy_disable_shield.js]
+[browser_policy_disable_telemetry.js]
+[browser_policy_display_bookmarks.js]
+[browser_policy_display_menu.js]
+[browser_policy_downloads.js]
+support-files =
+ !/browser/components/downloads/test/browser/foo.txt
+ !/browser/components/downloads/test/browser/foo.txt^headers^
+[browser_policy_extensions.js]
+[browser_policy_extensionsettings.js]
+https_first_disabled = true
+[browser_policy_extensionsettings2.js]
+[browser_policy_firefoxhome.js]
+[browser_policy_firefoxsuggest.js]
+[browser_policy_handlers.js]
+[browser_policy_masterpassword.js]
+[browser_policy_masterpassword_aboutlogins.js]
+[browser_policy_masterpassword_doorhanger.js]
+[browser_policy_offertosavelogins.js]
+[browser_policy_override_postupdatepage.js]
+[browser_policy_pageinfo_permissions.js]
+[browser_policy_passwordmanager.js]
+[browser_policy_search_engine.js]
+[browser_policy_searchbar.js]
+[browser_policy_set_homepage.js]
+[browser_policy_set_startpage.js]
+[browser_policy_support_menu.js]
+[browser_policy_usermessaging.js]
+[browser_policy_websitefilter.js]
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policies_getActivePolicies.js b/browser/components/enterprisepolicies/tests/browser/browser_policies_getActivePolicies.js
new file mode 100644
index 0000000000..547f5e7598
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policies_getActivePolicies.js
@@ -0,0 +1,52 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_active_policies() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisablePrivateBrowsing: true,
+ },
+ });
+
+ let expected = {
+ DisablePrivateBrowsing: true,
+ };
+
+ Assert.deepEqual(
+ await Services.policies.getActivePolicies(),
+ expected,
+ "Active policies parsed correctly"
+ );
+});
+
+add_task(async function test_wrong_policies() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ BlockAboutSupport: [true],
+ },
+ });
+
+ let expected = {};
+
+ Assert.deepEqual(
+ await Services.policies.getActivePolicies(),
+ expected,
+ "Wrong policies ignored"
+ );
+});
+
+add_task(async function test_content_process() {
+ await SpecialPowers.spawn(gBrowser.selectedBrowser, [], function () {
+ try {
+ Services.policies.getActivePolicies();
+ } catch (ex) {
+ is(
+ ex.result,
+ Cr.NS_ERROR_XPC_JSOBJECT_HAS_NO_FUNCTION_NAMED,
+ "Function getActivePolicies() doesn't have a valid definition in the content process"
+ );
+ }
+ });
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policies_notice_in_aboutpreferences.js b/browser/components/enterprisepolicies/tests/browser/browser_policies_notice_in_aboutpreferences.js
new file mode 100644
index 0000000000..75c17ddf36
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policies_notice_in_aboutpreferences.js
@@ -0,0 +1,19 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_notice_in_aboutprefences() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DummyPolicy: true,
+ },
+ });
+
+ await BrowserTestUtils.withNewTab("about:preferences", async browser => {
+ ok(
+ !browser.contentDocument.getElementById("policies-container").hidden,
+ "The Policies notice was made visible in about:preferences"
+ );
+ });
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policies_setAndLockPref_API.js b/browser/components/enterprisepolicies/tests/browser/browser_policies_setAndLockPref_API.js
new file mode 100644
index 0000000000..0cad8e5aa3
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policies_setAndLockPref_API.js
@@ -0,0 +1,179 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+let { Policies, setAndLockPref, PoliciesUtils } = ChromeUtils.importESModule(
+ "resource:///modules/policies/Policies.sys.mjs"
+);
+
+add_task(async function test_API_directly() {
+ await setupPolicyEngineWithJson("");
+ setAndLockPref("policies.test.boolPref", true);
+ checkLockedPref("policies.test.boolPref", true);
+
+ // Check that a previously-locked pref can be changed
+ // (it will be unlocked first).
+ setAndLockPref("policies.test.boolPref", false);
+ checkLockedPref("policies.test.boolPref", false);
+
+ setAndLockPref("policies.test.intPref", 2);
+ checkLockedPref("policies.test.intPref", 2);
+
+ setAndLockPref("policies.test.stringPref", "policies test");
+ checkLockedPref("policies.test.stringPref", "policies test");
+
+ PoliciesUtils.setDefaultPref(
+ "policies.test.lockedPref",
+ "policies test",
+ true
+ );
+ checkLockedPref("policies.test.lockedPref", "policies test");
+
+ // Test that user values do not override the prefs, and the get*Pref call
+ // still return the value set through setAndLockPref
+ Services.prefs.setBoolPref("policies.test.boolPref", true);
+ checkLockedPref("policies.test.boolPref", false);
+
+ Services.prefs.setIntPref("policies.test.intPref", 10);
+ checkLockedPref("policies.test.intPref", 2);
+
+ Services.prefs.setStringPref("policies.test.stringPref", "policies test");
+ checkLockedPref("policies.test.stringPref", "policies test");
+
+ try {
+ // Test that a non-integer value is correctly rejected, even though
+ // typeof(val) == "number"
+ setAndLockPref("policies.test.intPref", 1.5);
+ ok(false, "Integer value should be rejected");
+ } catch (ex) {
+ ok(true, "Integer value was rejected");
+ }
+});
+
+add_task(async function test_API_through_policies() {
+ // Ensure that the values received by the policies have the correct
+ // type to make sure things are properly working.
+
+ // Implement functions to handle the three simple policies
+ // that will be added to the schema.
+ Policies.bool_policy = {
+ onBeforeUIStartup(manager, param) {
+ setAndLockPref("policies.test2.boolPref", param);
+ },
+ };
+
+ Policies.int_policy = {
+ onBeforeUIStartup(manager, param) {
+ setAndLockPref("policies.test2.intPref", param);
+ },
+ };
+
+ Policies.string_policy = {
+ onBeforeUIStartup(manager, param) {
+ setAndLockPref("policies.test2.stringPref", param);
+ },
+ };
+
+ await setupPolicyEngineWithJson(
+ // policies.json
+ {
+ policies: {
+ bool_policy: true,
+ int_policy: 42,
+ string_policy: "policies test 2",
+ },
+ },
+
+ // custom schema
+ {
+ properties: {
+ bool_policy: {
+ type: "boolean",
+ },
+
+ int_policy: {
+ type: "integer",
+ },
+
+ string_policy: {
+ type: "string",
+ },
+ },
+ }
+ );
+
+ is(
+ Services.policies.status,
+ Ci.nsIEnterprisePolicies.ACTIVE,
+ "Engine is active"
+ );
+
+ // The expected values come from config_setAndLockPref.json
+ checkLockedPref("policies.test2.boolPref", true);
+ checkLockedPref("policies.test2.intPref", 42);
+ checkLockedPref("policies.test2.stringPref", "policies test 2");
+
+ delete Policies.bool_policy;
+ delete Policies.int_policy;
+ delete Policies.string_policy;
+});
+
+add_task(async function test_pref_tracker() {
+ // Tests the test harness functionality that tracks usage of
+ // the setAndLockPref and setDefualtPref APIs.
+
+ let defaults = Services.prefs.getDefaultBranch("");
+
+ // Test prefs that had a default value and got changed to another
+ defaults.setIntPref("test1.pref1", 10);
+ defaults.setStringPref("test1.pref2", "test");
+
+ setAndLockPref("test1.pref1", 20);
+ PoliciesUtils.setDefaultPref("test1.pref2", "NEW VALUE");
+ setAndLockPref("test1.pref3", "NEW VALUE");
+ PoliciesUtils.setDefaultPref("test1.pref4", 20);
+
+ PoliciesPrefTracker.restoreDefaultValues();
+
+ is(
+ Services.prefs.getIntPref("test1.pref1"),
+ 10,
+ "Expected value for test1.pref1"
+ );
+ is(
+ Services.prefs.getStringPref("test1.pref2"),
+ "test",
+ "Expected value for test1.pref2"
+ );
+ is(
+ Services.prefs.prefIsLocked("test1.pref1"),
+ false,
+ "test1.pref1 got unlocked"
+ );
+ ok(
+ !Services.prefs.getStringPref("test1.pref3", undefined),
+ "test1.pref3 should have had its value unset"
+ );
+ is(
+ Services.prefs.getIntPref("test1.pref4", -1),
+ -1,
+ "test1.pref4 should have had its value unset"
+ );
+
+ // Test a pref that had a default value and a user value
+ defaults.setIntPref("test2.pref1", 10);
+ Services.prefs.setIntPref("test2.pref1", 20);
+
+ setAndLockPref("test2.pref1", 20);
+
+ PoliciesPrefTracker.restoreDefaultValues();
+
+ is(Services.prefs.getIntPref("test2.pref1"), 20, "Correct user value");
+ is(defaults.getIntPref("test2.pref1"), 10, "Correct default value");
+ is(
+ Services.prefs.prefIsLocked("test2.pref1"),
+ false,
+ "felipe pref is not locked"
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_app_auto_update.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_app_auto_update.js
new file mode 100644
index 0000000000..0cae8369e4
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_app_auto_update.js
@@ -0,0 +1,77 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+ChromeUtils.defineESModuleGetters(this, {
+ UpdateUtils: "resource://gre/modules/UpdateUtils.sys.mjs",
+});
+
+async function test_app_update_auto(expectedEnabled, expectedLocked) {
+ let actualEnabled = await UpdateUtils.getAppUpdateAutoEnabled();
+ is(
+ actualEnabled,
+ expectedEnabled,
+ `Actual auto update enabled setting should match the expected value of ${expectedEnabled}`
+ );
+
+ let actualLocked = UpdateUtils.appUpdateAutoSettingIsLocked();
+ is(
+ actualLocked,
+ expectedLocked,
+ `Auto update enabled setting ${
+ expectedLocked ? "should" : "should not"
+ } be locked`
+ );
+
+ let setSuccess = true;
+ try {
+ await UpdateUtils.setAppUpdateAutoEnabled(actualEnabled);
+ } catch (error) {
+ setSuccess = false;
+ }
+ is(
+ setSuccess,
+ !expectedLocked,
+ `Setting auto update ${expectedLocked ? "should" : "should not"} fail`
+ );
+
+ await BrowserTestUtils.withNewTab("about:preferences", browser => {
+ is(
+ browser.contentDocument.getElementById("updateSettingsContainer").hidden,
+ expectedLocked,
+ `When auto update ${
+ expectedLocked ? "is" : "isn't"
+ } locked, the corresponding preferences entry ${
+ expectedLocked ? "should" : "shouldn't"
+ } be hidden`
+ );
+ });
+}
+
+add_task(async function test_app_auto_update_policy() {
+ let originalUpdateAutoValue = await UpdateUtils.getAppUpdateAutoEnabled();
+ registerCleanupFunction(async () => {
+ await UpdateUtils.setAppUpdateAutoEnabled(originalUpdateAutoValue);
+ });
+
+ await UpdateUtils.setAppUpdateAutoEnabled(true);
+ await test_app_update_auto(true, false);
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ AppAutoUpdate: false,
+ },
+ });
+ await test_app_update_auto(false, true);
+
+ await setupPolicyEngineWithJson({});
+ await UpdateUtils.setAppUpdateAutoEnabled(false);
+ await test_app_update_auto(false, false);
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ AppAutoUpdate: true,
+ },
+ });
+ await test_app_update_auto(true, true);
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_app_update.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_app_update.js
new file mode 100644
index 0000000000..14a9c92bc5
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_app_update.js
@@ -0,0 +1,41 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+ChromeUtils.defineESModuleGetters(this, {
+ UpdateUtils: "resource://gre/modules/UpdateUtils.sys.mjs",
+});
+var updateService = Cc["@mozilla.org/updates/update-service;1"].getService(
+ Ci.nsIApplicationUpdateService
+);
+
+// This test is intended to ensure that nsIUpdateService::canCheckForUpdates
+// is true before the "DisableAppUpdate" policy is applied. Testing that
+// nsIUpdateService::canCheckForUpdates is false after the "DisableAppUpdate"
+// policy is applied needs to occur in a different test since the policy does
+// not properly take effect unless it is applied during application startup.
+add_task(async function test_updates_pre_policy() {
+ // Turn off automatic update before we set app.update.disabledForTesting to
+ // false so that we don't cause an actual update.
+ let originalUpdateAutoValue = await UpdateUtils.getAppUpdateAutoEnabled();
+ await UpdateUtils.setAppUpdateAutoEnabled(false);
+ registerCleanupFunction(async () => {
+ await UpdateUtils.setAppUpdateAutoEnabled(originalUpdateAutoValue);
+ });
+
+ await SpecialPowers.pushPrefEnv({
+ set: [["app.update.disabledForTesting", false]],
+ });
+
+ is(
+ Services.policies.isAllowed("appUpdate"),
+ true,
+ "Since no policies have been set, appUpdate should be allowed by default"
+ );
+
+ is(
+ updateService.canCheckForUpdates,
+ true,
+ "Should be able to check for updates before any policies are in effect."
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_background_app_update.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_background_app_update.js
new file mode 100644
index 0000000000..a529e79be7
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_background_app_update.js
@@ -0,0 +1,99 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ UpdateUtils: "resource://gre/modules/UpdateUtils.sys.mjs",
+});
+
+const PREF_NAME = "app.update.background.enabled";
+
+async function test_background_update_pref(expectedEnabled, expectedLocked) {
+ let actualEnabled = await UpdateUtils.readUpdateConfigSetting(PREF_NAME);
+ is(
+ actualEnabled,
+ expectedEnabled,
+ `Actual background update enabled setting should be ${expectedEnabled}`
+ );
+
+ let actualLocked = UpdateUtils.appUpdateSettingIsLocked(PREF_NAME);
+ is(
+ actualLocked,
+ expectedLocked,
+ `Background update enabled setting ${
+ expectedLocked ? "should" : "should not"
+ } be locked`
+ );
+
+ let setSuccess = true;
+ try {
+ await UpdateUtils.writeUpdateConfigSetting(PREF_NAME, actualEnabled);
+ } catch (error) {
+ setSuccess = false;
+ }
+ is(
+ setSuccess,
+ !expectedLocked,
+ `Setting background update pref ${
+ expectedLocked ? "should" : "should not"
+ } fail`
+ );
+
+ if (AppConstants.MOZ_UPDATE_AGENT) {
+ let shouldShowUI =
+ !expectedLocked && UpdateUtils.PER_INSTALLATION_PREFS_SUPPORTED;
+ await BrowserTestUtils.withNewTab("about:preferences", browser => {
+ is(
+ browser.contentDocument.getElementById("backgroundUpdate").hidden,
+ !shouldShowUI,
+ `When background update ${
+ expectedLocked ? "is" : "isn't"
+ } locked, and per-installation prefs ${
+ UpdateUtils.PER_INSTALLATION_PREFS_SUPPORTED ? "are" : "aren't"
+ } supported, the corresponding preferences entry ${
+ shouldShowUI ? "shouldn't" : "should"
+ } be hidden`
+ );
+ });
+ } else {
+ // The backgroundUpdate element is #ifdef'ed out if MOZ_UPDATER and
+ // MOZ_UPDATE_AGENT are not both defined.
+ info(
+ "Warning: UI testing skipped because support for background update is " +
+ "not present"
+ );
+ }
+}
+
+add_task(async function test_background_app_update_policy() {
+ const origBackgroundUpdateVal = await UpdateUtils.readUpdateConfigSetting(
+ PREF_NAME
+ );
+ registerCleanupFunction(async () => {
+ await UpdateUtils.writeUpdateConfigSetting(
+ PREF_NAME,
+ origBackgroundUpdateVal
+ );
+ });
+
+ await UpdateUtils.writeUpdateConfigSetting(PREF_NAME, true);
+ await test_background_update_pref(true, false);
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ BackgroundAppUpdate: false,
+ },
+ });
+ await test_background_update_pref(false, true);
+
+ await setupPolicyEngineWithJson({});
+ await UpdateUtils.writeUpdateConfigSetting(PREF_NAME, false);
+ await test_background_update_pref(false, false);
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ BackgroundAppUpdate: true,
+ },
+ });
+ await test_background_update_pref(true, true);
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_block_about.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_block_about.js
new file mode 100644
index 0000000000..1c8956356f
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_block_about.js
@@ -0,0 +1,50 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const ABOUT_CONTRACT = "@mozilla.org/network/protocol/about;1?what=";
+
+const policiesToTest = [
+ {
+ policies: {
+ BlockAboutAddons: true,
+ },
+ urls: ["about:addons", "about:ADDONS"],
+ },
+ {
+ policies: {
+ BlockAboutConfig: true,
+ },
+ urls: ["about:config", "about:Config"],
+ },
+ {
+ policies: {
+ BlockAboutProfiles: true,
+ },
+ urls: ["about:profiles", "about:pRofiles"],
+ },
+ {
+ policies: {
+ BlockAboutSupport: true,
+ },
+ urls: ["about:support", "about:suPPort"],
+ },
+];
+
+add_task(async function testAboutTask() {
+ for (let policyToTest of policiesToTest) {
+ let policyJSON = { policies: {} };
+ policyJSON.policies = policyToTest.policies;
+ for (let url of policyToTest.urls) {
+ if (url.startsWith("about")) {
+ let feature = url.split(":")[1].toLowerCase();
+ let aboutModule = Cc[ABOUT_CONTRACT + feature].getService(
+ Ci.nsIAboutModule
+ );
+ let chromeURL = aboutModule.getChromeURI(Services.io.newURI(url)).spec;
+ await testPageBlockedByPolicy(chromeURL, policyJSON);
+ }
+ await testPageBlockedByPolicy(url, policyJSON);
+ }
+ }
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_block_about_support.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_block_about_support.js
new file mode 100644
index 0000000000..925aa0cdfd
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_block_about_support.js
@@ -0,0 +1,41 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+add_setup(async function () {
+ await setupPolicyEngineWithJson({
+ policies: {
+ BlockAboutSupport: true,
+ },
+ });
+});
+
+add_task(async function test_help_menu() {
+ buildHelpMenu();
+ let troubleshootingInfoMenu = document.getElementById("troubleShooting");
+ is(
+ troubleshootingInfoMenu.getAttribute("disabled"),
+ "true",
+ "The `More Troubleshooting Information` item should be disabled"
+ );
+});
+
+add_task(async function test_about_memory() {
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:memory"
+ );
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ let aboutSupportLink = content.document.querySelector(
+ "a[href='about:support']"
+ );
+
+ Assert.ok(
+ !aboutSupportLink,
+ "The link to about:support at the bottom of the page should not exist"
+ );
+ });
+
+ await BrowserTestUtils.removeTab(tab);
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_cookie_settings.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_cookie_settings.js
new file mode 100644
index 0000000000..b928e8c93b
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_cookie_settings.js
@@ -0,0 +1,367 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const { UrlClassifierTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/UrlClassifierTestUtils.sys.mjs"
+);
+Services.cookies.QueryInterface(Ci.nsICookieService);
+
+function restore_prefs() {
+ Services.prefs.clearUserPref("network.cookie.cookieBehavior");
+ Services.prefs.clearUserPref(
+ "network.cookieJarSettings.unblocked_for_testing"
+ );
+ Services.prefs.clearUserPref(
+ "network.cookie.rejectForeignWithExceptions.enabled"
+ );
+}
+
+registerCleanupFunction(restore_prefs);
+
+async function fake_profile_change() {
+ await new Promise(resolve => {
+ Services.obs.addObserver(function waitForDBClose() {
+ Services.obs.removeObserver(waitForDBClose, "cookie-db-closed");
+ resolve();
+ }, "cookie-db-closed");
+ Services.cookies
+ .QueryInterface(Ci.nsIObserver)
+ .observe(null, "profile-before-change", null);
+ });
+ await new Promise(resolve => {
+ Services.obs.addObserver(function waitForDBOpen() {
+ Services.obs.removeObserver(waitForDBOpen, "cookie-db-read");
+ resolve();
+ }, "cookie-db-read");
+ Services.cookies
+ .QueryInterface(Ci.nsIObserver)
+ .observe(null, "profile-do-change", "");
+ });
+}
+
+async function test_cookie_settings({
+ cookiesEnabled,
+ thirdPartyCookiesEnabled,
+ rejectTrackers,
+ cookieJarSettingsLocked,
+}) {
+ let firstPartyURI = NetUtil.newURI("https://example.com/");
+ let thirdPartyURI = NetUtil.newURI("https://example.org/");
+ let channel = NetUtil.newChannel({
+ uri: firstPartyURI,
+ loadUsingSystemPrincipal: true,
+ });
+ channel.QueryInterface(
+ Ci.nsIHttpChannelInternal
+ ).forceAllowThirdPartyCookie = true;
+ Services.cookies.removeAll();
+ Services.cookies.setCookieStringFromHttp(
+ firstPartyURI,
+ "key=value; SameSite=None; Secure;",
+ channel
+ );
+ Services.cookies.setCookieStringFromHttp(
+ thirdPartyURI,
+ "key=value; SameSite=None; Secure;",
+ channel
+ );
+
+ let expectedFirstPartyCookies = 1;
+ let expectedThirdPartyCookies = 1;
+ if (!cookiesEnabled) {
+ expectedFirstPartyCookies = 0;
+ }
+ if (!cookiesEnabled || !thirdPartyCookiesEnabled) {
+ expectedThirdPartyCookies = 0;
+ }
+ is(
+ Services.cookies.countCookiesFromHost(firstPartyURI.host),
+ expectedFirstPartyCookies,
+ "Number of first-party cookies should match expected"
+ );
+ is(
+ Services.cookies.countCookiesFromHost(thirdPartyURI.host),
+ expectedThirdPartyCookies,
+ "Number of third-party cookies should match expected"
+ );
+
+ // Add a cookie so we can check if it persists past the end of the session
+ // but, first remove existing cookies set by this host to put us in a known state
+ Services.cookies.removeAll();
+ Services.cookies.setCookieStringFromHttp(
+ firstPartyURI,
+ "key=value; max-age=1000; SameSite=None; Secure;",
+ channel
+ );
+
+ await fake_profile_change();
+
+ // Now check if the cookie persisted or not
+ let expectedCookieCount = 1;
+ if (!cookiesEnabled) {
+ expectedCookieCount = 0;
+ }
+ is(
+ Services.cookies.countCookiesFromHost(firstPartyURI.host),
+ expectedCookieCount,
+ "Number of cookies was not what expected after restarting session"
+ );
+
+ is(
+ Services.prefs.prefIsLocked("network.cookie.cookieBehavior"),
+ cookieJarSettingsLocked,
+ "Cookie behavior pref lock status should be what is expected"
+ );
+
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:preferences"
+ );
+
+ BrowserTestUtils.removeTab(tab);
+
+ if (rejectTrackers) {
+ tab = await BrowserTestUtils.addTab(
+ gBrowser,
+ "http://example.net/browser/browser/components/enterprisepolicies/tests/browser/page.html"
+ );
+ let browser = gBrowser.getBrowserForTab(tab);
+ await BrowserTestUtils.browserLoaded(browser);
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ // Load the script twice
+ {
+ let src = content.document.createElement("script");
+ let p = new content.Promise((resolve, reject) => {
+ src.onload = resolve;
+ src.onerror = reject;
+ });
+ content.document.body.appendChild(src);
+ src.src =
+ "https://tracking.example.org/browser/browser/components/enterprisepolicies/tests/browser/subResources.sjs?what=script";
+ await p;
+ }
+ {
+ let src = content.document.createElement("script");
+ let p = new content.Promise(resolve => {
+ src.onload = resolve;
+ });
+ content.document.body.appendChild(src);
+ src.src =
+ "https://tracking.example.org/browser/browser/components/enterprisepolicies/tests/browser/subResources.sjs?what=script";
+ await p;
+ }
+ });
+ BrowserTestUtils.removeTab(tab);
+ await fetch(
+ "https://tracking.example.org/browser/browser/components/enterprisepolicies/tests/browser/subResources.sjs?result&what=script"
+ )
+ .then(r => r.text())
+ .then(text => {
+ is(text, "0", '"Reject Tracker" pref should match what is expected');
+ });
+ }
+}
+
+add_task(async function prepare_tracker_tables() {
+ await UrlClassifierTestUtils.addTestTrackers();
+});
+
+add_task(async function test_initial_state() {
+ Services.prefs.setBoolPref(
+ "network.cookieJarSettings.unblocked_for_testing",
+ true
+ );
+ Services.prefs.setBoolPref(
+ "network.cookie.rejectForeignWithExceptions.enabled",
+ false
+ );
+
+ await test_cookie_settings({
+ cookiesEnabled: true,
+ thirdPartyCookiesEnabled: true,
+ cookieJarSettingsLocked: false,
+ });
+ restore_prefs();
+});
+
+add_task(async function test_undefined_unlocked() {
+ Services.prefs.setIntPref("network.cookie.cookieBehavior", 3);
+ Services.prefs.setBoolPref(
+ "network.cookieJarSettings.unblocked_for_testing",
+ true
+ );
+ Services.prefs.setBoolPref(
+ "network.cookie.rejectForeignWithExceptions.enabled",
+ false
+ );
+ await setupPolicyEngineWithJson({
+ policies: {
+ Cookies: {},
+ },
+ });
+ is(
+ Services.prefs.getIntPref("network.cookie.cookieBehavior", undefined),
+ 3,
+ "An empty cookie policy should not have changed the cookieBehavior preference"
+ );
+ restore_prefs();
+});
+
+add_task(async function test_disabled() {
+ Services.prefs.setBoolPref(
+ "network.cookieJarSettings.unblocked_for_testing",
+ true
+ );
+ Services.prefs.setBoolPref(
+ "network.cookie.rejectForeignWithExceptions.enabled",
+ false
+ );
+ await setupPolicyEngineWithJson({
+ policies: {
+ Cookies: {
+ Default: false,
+ },
+ },
+ });
+
+ await test_cookie_settings({
+ cookiesEnabled: false,
+ thirdPartyCookiesEnabled: true,
+ cookieJarSettingsLocked: false,
+ });
+ restore_prefs();
+});
+
+add_task(async function test_third_party_disabled() {
+ Services.prefs.setBoolPref(
+ "network.cookieJarSettings.unblocked_for_testing",
+ true
+ );
+ Services.prefs.setBoolPref(
+ "network.cookie.rejectForeignWithExceptions.enabled",
+ false
+ );
+ await setupPolicyEngineWithJson({
+ policies: {
+ Cookies: {
+ AcceptThirdParty: "never",
+ },
+ },
+ });
+
+ await test_cookie_settings({
+ cookiesEnabled: true,
+ thirdPartyCookiesEnabled: false,
+ cookieJarSettingsLocked: false,
+ });
+ restore_prefs();
+});
+
+add_task(async function test_disabled_and_third_party_disabled() {
+ Services.prefs.setBoolPref(
+ "network.cookieJarSettings.unblocked_for_testing",
+ true
+ );
+ Services.prefs.setBoolPref(
+ "network.cookie.rejectForeignWithExceptions.enabled",
+ false
+ );
+ await setupPolicyEngineWithJson({
+ policies: {
+ Cookies: {
+ Default: false,
+ AcceptThirdParty: "never",
+ },
+ },
+ });
+
+ await test_cookie_settings({
+ cookiesEnabled: false,
+ thirdPartyCookiesEnabled: false,
+ cookieJarSettingsLocked: false,
+ });
+ restore_prefs();
+});
+
+add_task(async function test_disabled_and_third_party_disabled_locked() {
+ Services.prefs.setBoolPref(
+ "network.cookieJarSettings.unblocked_for_testing",
+ true
+ );
+ Services.prefs.setBoolPref(
+ "network.cookie.rejectForeignWithExceptions.enabled",
+ false
+ );
+ await setupPolicyEngineWithJson({
+ policies: {
+ Cookies: {
+ Default: false,
+ AcceptThirdParty: "never",
+ Locked: true,
+ },
+ },
+ });
+
+ await test_cookie_settings({
+ cookiesEnabled: false,
+ thirdPartyCookiesEnabled: false,
+ cookieJarSettingsLocked: true,
+ });
+ restore_prefs();
+});
+
+add_task(async function test_undefined_locked() {
+ Services.prefs.setBoolPref(
+ "network.cookieJarSettings.unblocked_for_testing",
+ true
+ );
+ Services.prefs.setBoolPref(
+ "network.cookie.rejectForeignWithExceptions.enabled",
+ false
+ );
+ await setupPolicyEngineWithJson({
+ policies: {
+ Cookies: {
+ Locked: true,
+ },
+ },
+ });
+
+ await test_cookie_settings({
+ cookiesEnabled: true,
+ thirdPartyCookiesEnabled: true,
+ cookieJarSettingsLocked: true,
+ });
+ restore_prefs();
+});
+
+add_task(async function test_cookie_reject_trackers() {
+ Services.prefs.setBoolPref(
+ "network.cookieJarSettings.unblocked_for_testing",
+ true
+ );
+ Services.prefs.setBoolPref(
+ "network.cookie.rejectForeignWithExceptions.enabled",
+ false
+ );
+ await setupPolicyEngineWithJson({
+ policies: {
+ Cookies: {
+ RejectTracker: true,
+ },
+ },
+ });
+
+ await test_cookie_settings({
+ cookiesEnabled: true,
+ thirdPartyCookiesEnabled: true,
+ rejectTrackers: true,
+ cookieJarSettingsLocked: false,
+ });
+ restore_prefs();
+});
+
+add_task(async function prepare_tracker_tables() {
+ await UrlClassifierTestUtils.cleanupTestTrackers();
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_feedback_commands.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_feedback_commands.js
new file mode 100644
index 0000000000..b89788e1cf
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_feedback_commands.js
@@ -0,0 +1,63 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+/* the buidHelpMenu() function comes from browser/base/content/utilityOverlay.js */
+
+const NORMAL_PAGE = "http://example.com";
+const PHISH_PAGE = "http://www.itisatrap.org/firefox/its-a-trap.html";
+
+async function checkItemsAreDisabled(url) {
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url,
+ // The phishing page doesn't send a load notification
+ waitForLoad: false,
+ waitForStateStop: true,
+ },
+ async function checkItems() {
+ buildHelpMenu();
+
+ let reportMenu = document.getElementById(
+ "menu_HelpPopup_reportPhishingtoolmenu"
+ );
+ is(
+ reportMenu.getAttribute("disabled"),
+ "true",
+ "The `Report Deceptive Site` item should be disabled"
+ );
+
+ let errorMenu = document.getElementById(
+ "menu_HelpPopup_reportPhishingErrortoolmenu"
+ );
+ is(
+ errorMenu.getAttribute("disabled"),
+ "true",
+ "The `This isn’t a deceptive site` item should be disabled"
+ );
+ }
+ );
+}
+
+add_task(async function test_policy_feedback_commands() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisableFeedbackCommands: true,
+ },
+ });
+
+ /* from browser/base/content/utilityOverlay.js */
+ buildHelpMenu();
+
+ let feedbackPageMenu = document.getElementById("feedbackPage");
+ is(
+ feedbackPageMenu.getAttribute("disabled"),
+ "true",
+ "The `Submit Feedback...` item should be disabled"
+ );
+
+ await checkItemsAreDisabled(NORMAL_PAGE);
+ await checkItemsAreDisabled(PHISH_PAGE);
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_fxaccounts.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_fxaccounts.js
new file mode 100644
index 0000000000..7872647042
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_fxaccounts.js
@@ -0,0 +1,16 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_policy_disable_fxaccounts() {
+ is(gSync.FXA_ENABLED, true, "Sync is enabled before setting the policy.");
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisableFirefoxAccounts: true,
+ },
+ });
+
+ is(gSync.FXA_ENABLED, false, "Sync is disabled after setting the policy.");
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_masterpassword.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_masterpassword.js
new file mode 100644
index 0000000000..7f3748fdc5
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_masterpassword.js
@@ -0,0 +1,90 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const MASTER_PASSWORD = "omgsecret!";
+const mpToken = Cc["@mozilla.org/security/pk11tokendb;1"]
+ .getService(Ci.nsIPK11TokenDB)
+ .getInternalKeyToken();
+
+async function checkDeviceManager({ buttonIsDisabled }) {
+ let deviceManagerWindow = window.openDialog(
+ "chrome://pippki/content/device_manager.xhtml",
+ "",
+ ""
+ );
+ await BrowserTestUtils.waitForEvent(deviceManagerWindow, "load");
+
+ let tree = deviceManagerWindow.document.getElementById("device_tree");
+ ok(tree, "The device tree exists");
+
+ // Find and select the item related to the internal key token
+ for (let i = 0; i < tree.view.rowCount; i++) {
+ tree.view.selection.select(i);
+
+ try {
+ let selected_token = deviceManagerWindow.selected_slot.getToken();
+ if (selected_token.isInternalKeyToken) {
+ break;
+ }
+ } catch (e) {}
+ }
+
+ // Check to see if the button was updated correctly
+ let changePwButton =
+ deviceManagerWindow.document.getElementById("change_pw_button");
+ is(
+ changePwButton.getAttribute("disabled") == "true",
+ buttonIsDisabled,
+ "Change Password button is in the correct state: " + buttonIsDisabled
+ );
+
+ await BrowserTestUtils.closeWindow(deviceManagerWindow);
+}
+
+async function checkAboutPreferences({ checkboxIsDisabled }) {
+ await BrowserTestUtils.withNewTab(
+ "about:preferences#privacy",
+ async browser => {
+ is(
+ browser.contentDocument.getElementById("useMasterPassword").disabled,
+ checkboxIsDisabled,
+ "Master Password checkbox is in the correct state: " +
+ checkboxIsDisabled
+ );
+ }
+ );
+}
+
+add_task(async function test_policy_disable_masterpassword() {
+ ok(!mpToken.hasPassword, "Starting the test with no password");
+
+ // No password and no policy: access to setting a primary password
+ // should be enabled.
+ await checkDeviceManager({ buttonIsDisabled: false });
+ await checkAboutPreferences({ checkboxIsDisabled: false });
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisableMasterPasswordCreation: true,
+ },
+ });
+
+ // With the `DisableMasterPasswordCreation: true` policy active, the
+ // UI entry points for creating a Primary Password should be disabled.
+ await checkDeviceManager({ buttonIsDisabled: true });
+ await checkAboutPreferences({ checkboxIsDisabled: true });
+
+ mpToken.changePassword("", MASTER_PASSWORD);
+ ok(mpToken.hasPassword, "Master password was set");
+
+ // If a Primary Password is already set, there's no point in disabling
+ // the
+ await checkDeviceManager({ buttonIsDisabled: false });
+ await checkAboutPreferences({ checkboxIsDisabled: false });
+
+ // Clean up
+ mpToken.changePassword(MASTER_PASSWORD, "");
+ ok(!mpToken.hasPassword, "Master password was cleaned up");
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_password_reveal.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_password_reveal.js
new file mode 100644
index 0000000000..503d421da7
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_password_reveal.js
@@ -0,0 +1,43 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_hidden_reveal_password() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisablePasswordReveal: true,
+ },
+ });
+
+ let aboutLoginsTab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ url: "about:logins",
+ });
+
+ let browser = gBrowser.selectedBrowser;
+
+ await SpecialPowers.spawn(browser, [], () => {
+ let loginList = Cu.waiveXrays(content.document.querySelector("login-list"));
+ let createButton = loginList._createLoginButton;
+ ok(
+ !createButton.disabled,
+ "Create button should not be disabled initially"
+ );
+ let loginItem = Cu.waiveXrays(content.document.querySelector("login-item"));
+
+ createButton.click();
+
+ let passwordReveal = loginItem.shadowRoot.querySelector(
+ ".reveal-password-checkbox"
+ );
+ is(passwordReveal.hidden, true, "Password reveal button should be hidden");
+
+ // Bug 1696948
+ let passwordInput = loginItem.shadowRoot.querySelector(
+ "input[name='password']"
+ );
+ isnot(passwordInput, null, "Password field should be in the DOM");
+ });
+ BrowserTestUtils.removeTab(aboutLoginsTab);
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_pocket.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_pocket.js
new file mode 100644
index 0000000000..414b855f8c
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_pocket.js
@@ -0,0 +1,29 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const PREF_POCKET = "extensions.pocket.enabled";
+
+async function checkPocket(shouldBeEnabled) {
+ return BrowserTestUtils.waitForCondition(() => {
+ return (
+ !!CustomizableUI.getWidget("save-to-pocket-button") == shouldBeEnabled
+ );
+ }, "Expecting Pocket to be " + shouldBeEnabled);
+}
+
+add_task(async function test_disable_firefox_screenshots() {
+ await BrowserTestUtils.withNewTab("data:text/html,Test", async function () {
+ // Sanity check to make sure Pocket is enabled on tests
+ await checkPocket(true);
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisablePocket: true,
+ },
+ });
+
+ await checkPocket(false);
+ });
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_popup_blocker.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_popup_blocker.js
new file mode 100644
index 0000000000..b9573c7614
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_popup_blocker.js
@@ -0,0 +1,149 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+function restore_prefs() {
+ Services.prefs.clearUserPref("dom.disable_open_during_load");
+}
+
+let ORIGINAL_PREF_VALUE = undefined;
+add_setup(async function () {
+ // It seems that this pref is given a special testing value for some reason.
+ // Unset that value for this test, but save the old value
+ if (Services.prefs.prefHasUserValue("dom.disable_open_during_load")) {
+ ORIGINAL_PREF_VALUE = Services.prefs.getBoolPref(
+ "dom.disable_open_during_load"
+ );
+ Services.prefs.clearUserPref("dom.disable_open_during_load");
+ }
+});
+registerCleanupFunction(async function cleanup_prefs() {
+ if (ORIGINAL_PREF_VALUE === undefined) {
+ Services.prefs.clearUserPref("dom.disable_open_during_load");
+ } else {
+ Services.prefs.setBoolPref(
+ "dom.disable_open_during_load",
+ ORIGINAL_PREF_VALUE
+ );
+ }
+});
+
+async function test_popup_blocker_disabled({ disabled, locked }) {
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:preferences#privacy"
+ );
+ await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [{ disabled, locked }],
+ // eslint-disable-next-line no-shadow
+ async function ({ disabled, locked }) {
+ let checkbox = content.document.getElementById("popupPolicy");
+ is(
+ checkbox.checked,
+ !disabled,
+ "Checkbox checked state should match policy's Block status"
+ );
+ is(
+ checkbox.disabled,
+ locked,
+ "Checkbox disabled state should match policy's Locked status"
+ );
+ }
+ );
+ BrowserTestUtils.removeTab(tab);
+
+ is(
+ Services.prefs.prefIsLocked("dom.disable_open_during_load"),
+ locked,
+ "Flash pref lock state should match policy lock state"
+ );
+}
+
+add_task(async function test_initial_state() {
+ await test_popup_blocker_disabled({ disabled: false, locked: false });
+});
+
+add_task(async function test_empty_policy() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ PopupBlocking: {},
+ },
+ });
+
+ await test_popup_blocker_disabled({ disabled: false, locked: false });
+
+ restore_prefs();
+});
+
+add_task(async function test_block() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ PopupBlocking: {
+ Default: true,
+ },
+ },
+ });
+
+ await test_popup_blocker_disabled({ disabled: false, locked: false });
+
+ restore_prefs();
+});
+
+add_task(async function test_block_locked() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ PopupBlocking: {
+ Default: true,
+ Locked: true,
+ },
+ },
+ });
+
+ await test_popup_blocker_disabled({ disabled: false, locked: true });
+
+ restore_prefs();
+});
+
+add_task(async function test_locked() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ PopupBlocking: {
+ Locked: true,
+ },
+ },
+ });
+
+ await test_popup_blocker_disabled({ disabled: false, locked: true });
+
+ restore_prefs();
+});
+
+add_task(async function test_disabled() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ PopupBlocking: {
+ Default: false,
+ },
+ },
+ });
+
+ await test_popup_blocker_disabled({ disabled: true, locked: false });
+
+ restore_prefs();
+});
+
+add_task(async function test_disabled_locked() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ PopupBlocking: {
+ Default: false,
+ Locked: true,
+ },
+ },
+ });
+
+ await test_popup_blocker_disabled({ disabled: true, locked: true });
+
+ restore_prefs();
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_privatebrowsing.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_privatebrowsing.js
new file mode 100644
index 0000000000..044282f473
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_privatebrowsing.js
@@ -0,0 +1,32 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_setup(async function () {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisablePrivateBrowsing: true,
+ },
+ });
+});
+
+add_task(async function test_privatebrowsing_disabled() {
+ is(
+ PrivateBrowsingUtils.enabled,
+ false,
+ "Private browsing should be disabled"
+ );
+ let newWin = await BrowserTestUtils.openNewBrowserWindow();
+ let privateBrowsingCommand = newWin.document.getElementById(
+ "Tools:PrivateBrowsing"
+ );
+ is(
+ privateBrowsingCommand.hidden,
+ true,
+ "The private browsing command should be hidden"
+ );
+ await BrowserTestUtils.closeWindow(newWin);
+
+ await testPageBlockedByPolicy("about:privatebrowsing");
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_profile_import.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_profile_import.js
new file mode 100644
index 0000000000..9993e578e0
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_profile_import.js
@@ -0,0 +1,100 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+async function openLibrary() {
+ return new Promise(resolve => {
+ let library = window.openDialog(
+ "chrome://browser/content/places/places.xhtml",
+ "",
+ "chrome,toolbar=yes,dialog=no,resizable"
+ );
+ waitForFocus(() => resolve(library), library);
+ });
+}
+
+add_task(async function test_disable_profile_import() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisableProfileImport: true,
+ },
+ });
+ let library = await openLibrary();
+
+ let menu = library.document.getElementById("maintenanceButtonPopup");
+ let promisePopupShown = BrowserTestUtils.waitForEvent(menu, "popupshown");
+ menu.openPopup();
+ await promisePopupShown;
+
+ let profileImportButton = library.document.getElementById("browserImport");
+ is(
+ profileImportButton.disabled,
+ true,
+ "Profile Import button should be disabled"
+ );
+
+ let promisePopupHidden = BrowserTestUtils.waitForEvent(menu, "popuphidden");
+ menu.hidePopup();
+ await promisePopupHidden;
+
+ await BrowserTestUtils.closeWindow(library);
+
+ checkLockedPref("browser.newtabpage.activity-stream.migrationExpired", true);
+});
+
+add_task(async function test_file_menu() {
+ gFileMenu.updateImportCommandEnabledState();
+
+ let command = document.getElementById("cmd_file_importFromAnotherBrowser");
+ ok(
+ command.getAttribute("disabled"),
+ "The `Import from Another Browser…` File menu item command should be disabled"
+ );
+
+ if (Services.appinfo.OS == "Darwin") {
+ // We would need to have a lot of boilerplate to open the menus on Windows
+ // and Linux to test this there.
+ let menuitem = document.getElementById("menu_importFromAnotherBrowser");
+ ok(
+ menuitem.disabled,
+ "The `Import from Another Browser…` File menu item should be disabled"
+ );
+ }
+});
+
+add_task(async function test_import_button() {
+ await PlacesUIUtils.maybeAddImportButton();
+ ok(
+ !document.getElementById("import-button"),
+ "Import button should be hidden."
+ );
+});
+
+add_task(async function test_prefs_entrypoint() {
+ await SpecialPowers.pushPrefEnv({
+ set: [["browser.migrate.preferences-entrypoint.enabled", true]],
+ });
+
+ let finalPaneEvent = Services.prefs.getBoolPref("identity.fxaccounts.enabled")
+ ? "sync-pane-loaded"
+ : "privacy-pane-loaded";
+ let finalPrefPaneLoaded = TestUtils.topicObserved(finalPaneEvent, () => true);
+ await BrowserTestUtils.withNewTab(
+ "about:preferences#general-migrate",
+ async browser => {
+ await finalPrefPaneLoaded;
+ await browser.contentWindow.customElements.whenDefined(
+ "migration-wizard"
+ );
+ let doc = browser.contentDocument;
+ ok(
+ !doc.getElementById("dataMigrationGroup"),
+ "Should remove import entrypoint in prefs if disabled via policy."
+ );
+ ok(
+ !doc.getElementById("migrationWizardDialog").open,
+ "Should not have opened the migration wizard."
+ );
+ }
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_profile_reset.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_profile_reset.js
new file mode 100644
index 0000000000..09bcdb2d85
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_profile_reset.js
@@ -0,0 +1,80 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+let { ResetProfile } = ChromeUtils.importESModule(
+ "resource://gre/modules/ResetProfile.sys.mjs"
+);
+
+// For this test to work properly, this profile actually needs to be
+// "reset-able", which requires that it be recognized by the profile service
+add_setup(async function () {
+ let profileDirectory = Services.dirsvc.get("ProfD", Ci.nsIFile);
+ let profileName = profileDirectory.leafName;
+ let profileService = Cc["@mozilla.org/toolkit/profile-service;1"].getService(
+ Ci.nsIToolkitProfileService
+ );
+ let createdProfile = profileService.createProfile(
+ profileDirectory,
+ profileName
+ );
+ profileService.flush();
+ registerCleanupFunction(async function cleanup() {
+ // Pass false to remove it from the profile service without deleting files.
+ createdProfile.remove(false);
+ });
+});
+
+async function test_reset_disabled({ disabled }) {
+ is(
+ ResetProfile.resetSupported(),
+ !disabled,
+ "Reset should only be supported if policy has not been applied"
+ );
+ is(
+ Services.prefs.getBoolPref("browser.disableResetPrompt", undefined),
+ disabled,
+ "Reset prompt should only be shown if policy has not been applied"
+ );
+ is(
+ Services.prefs.prefIsLocked("browser.disableResetPrompt"),
+ disabled,
+ "Reset prompt pref should be locked if the policy has been applied"
+ );
+
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:support"
+ );
+ await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [{ disabled }],
+ async function ({
+ // eslint-disable-next-line no-shadow
+ disabled,
+ }) {
+ let resetBox = content.document.getElementById("reset-box");
+ let elementStyle = content.window.getComputedStyle(resetBox);
+ let expectedDisplayValue = disabled ? "none" : "block";
+ is(
+ elementStyle.display,
+ expectedDisplayValue,
+ "about:support Reset button box should be hidden"
+ );
+ }
+ );
+ await BrowserTestUtils.removeTab(tab);
+}
+
+add_task(async function test_initial_conditions() {
+ await test_reset_disabled({ disabled: false });
+});
+
+add_task(async function test_policy_disable_reset() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisableProfileRefresh: true,
+ },
+ });
+ await test_reset_disabled({ disabled: true });
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_safemode.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_safemode.js
new file mode 100644
index 0000000000..a2787079d0
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_safemode.js
@@ -0,0 +1,57 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+add_setup(async function () {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisableSafeMode: true,
+ },
+ });
+});
+
+add_task(async function test_help_menu() {
+ buildHelpMenu();
+ let safeModeMenu = document.getElementById("helpSafeMode");
+ is(
+ safeModeMenu.getAttribute("disabled"),
+ "true",
+ "The `Restart with Add-ons Disabled...` item should be disabled"
+ );
+});
+
+add_task(async function test_safemode_from_about_support() {
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:support"
+ );
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ let button = content.document.getElementById("restart-in-safe-mode-button");
+ is(
+ button.getAttribute("disabled"),
+ "true",
+ "The `Restart with Add-ons Disabled...` button should be disabled"
+ );
+ });
+
+ await BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_safemode_from_about_profiles() {
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:profiles"
+ );
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ let button = content.document.getElementById("restart-in-safe-mode-button");
+ is(
+ button.getAttribute("disabled"),
+ "true",
+ "The `Restart with Add-ons Disabled...` button should be disabled"
+ );
+ });
+
+ await BrowserTestUtils.removeTab(tab);
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_shield.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_shield.js
new file mode 100644
index 0000000000..ef36a0d36c
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_shield.js
@@ -0,0 +1,68 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_policy_disable_shield() {
+ const { RecipeRunner } = ChromeUtils.importESModule(
+ "resource://normandy/lib/RecipeRunner.sys.mjs"
+ );
+ const { BaseAction } = ChromeUtils.importESModule(
+ "resource://normandy/actions/BaseAction.sys.mjs"
+ );
+ const { BaseStudyAction } = ChromeUtils.importESModule(
+ "resource://normandy/actions/BaseStudyAction.sys.mjs"
+ );
+
+ const baseAction = new BaseAction();
+ const baseStudyAction = new BaseStudyAction();
+
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["app.normandy.api_url", "https://localhost/selfsupport-dummy/"],
+ ["app.shield.optoutstudies.enabled", true],
+ ],
+ });
+
+ ok(RecipeRunner, "RecipeRunner exists");
+
+ RecipeRunner.checkPrefs();
+ ok(RecipeRunner.enabled, "RecipeRunner is enabled");
+
+ baseAction._preExecution();
+ is(
+ baseAction.state,
+ BaseAction.STATE_PREPARING,
+ "Base action is not disabled"
+ );
+
+ baseStudyAction._preExecution();
+ is(
+ baseStudyAction.state,
+ BaseAction.STATE_PREPARING,
+ "Base study action is not disabled"
+ );
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisableFirefoxStudies: true,
+ },
+ });
+
+ RecipeRunner.checkPrefs();
+ ok(RecipeRunner.enabled, "RecipeRunner is still enabled");
+
+ baseAction._preExecution();
+ is(
+ baseAction.state,
+ BaseAction.STATE_PREPARING,
+ "Base action is not disabled"
+ );
+
+ baseStudyAction._preExecution();
+ is(
+ baseStudyAction.state,
+ BaseAction.STATE_DISABLED,
+ "Base study action is disabled"
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_telemetry.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_telemetry.js
new file mode 100644
index 0000000000..3070df0d88
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_disable_telemetry.js
@@ -0,0 +1,28 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_policy_disable_telemetry() {
+ const { TelemetryReportingPolicy } = ChromeUtils.importESModule(
+ "resource://gre/modules/TelemetryReportingPolicy.sys.mjs"
+ );
+
+ ok(TelemetryReportingPolicy, "TelemetryReportingPolicy exists");
+ is(TelemetryReportingPolicy.canUpload(), true, "Telemetry is enabled");
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisableTelemetry: true,
+ },
+ });
+
+ is(TelemetryReportingPolicy.canUpload(), false, "Telemetry is disabled");
+ is(
+ Services.prefs.getBoolPref("toolkit.telemetry.archive.enabled"),
+ false,
+ "Telemetry archive should be disabled."
+ );
+
+ await testPageBlockedByPolicy("about:telemetry");
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_display_bookmarks.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_display_bookmarks.js
new file mode 100644
index 0000000000..8c43cbc8e1
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_display_bookmarks.js
@@ -0,0 +1,86 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Since testing will apply the policy after the browser has already started,
+// we will need to open a new window to actually see the toolbar
+
+add_task(async function test_personaltoolbar_shown_old() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisplayBookmarksToolbar: true,
+ },
+ });
+ let newWin = await BrowserTestUtils.openNewBrowserWindow();
+ let menuBar = newWin.document.getElementById("PersonalToolbar");
+ is(
+ menuBar.getAttribute("collapsed"),
+ "false",
+ "The bookmarks toolbar should not be hidden"
+ );
+
+ await BrowserTestUtils.closeWindow(newWin);
+});
+
+add_task(async function test_personaltoolbar_shown() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisplayBookmarksToolbar: "always",
+ },
+ });
+
+ let newWin = await BrowserTestUtils.openNewBrowserWindow();
+ let menuBar = newWin.document.getElementById("PersonalToolbar");
+ is(
+ menuBar.getAttribute("collapsed"),
+ "false",
+ "The bookmarks toolbar should not be hidden"
+ );
+
+ await BrowserTestUtils.closeWindow(newWin);
+});
+
+add_task(async function test_personaltoolbar_hidden() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisplayBookmarksToolbar: "never",
+ },
+ });
+
+ let newWin = await BrowserTestUtils.openNewBrowserWindow();
+ let menuBar = newWin.document.getElementById("PersonalToolbar");
+ is(
+ menuBar.getAttribute("collapsed"),
+ "true",
+ "The bookmarks toolbar should be hidden"
+ );
+
+ await BrowserTestUtils.closeWindow(newWin);
+});
+
+add_task(async function test_personaltoolbar_newtabonly() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisplayBookmarksToolbar: "newtab",
+ },
+ });
+
+ let newWin = await BrowserTestUtils.openNewBrowserWindow();
+ let menuBar = newWin.document.getElementById("PersonalToolbar");
+ is(
+ menuBar.getAttribute("collapsed"),
+ "true",
+ "The bookmarks toolbar should be hidden"
+ );
+
+ await BrowserTestUtils.openNewForegroundTab(newWin.gBrowser, "about:newtab");
+ menuBar = newWin.document.getElementById("PersonalToolbar");
+ is(
+ menuBar.getAttribute("collapsed"),
+ "false",
+ "The bookmarks toolbar should not be hidden"
+ );
+
+ await BrowserTestUtils.closeWindow(newWin);
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_display_menu.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_display_menu.js
new file mode 100644
index 0000000000..9560a1aaf1
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_display_menu.js
@@ -0,0 +1,84 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_menu_shown_boolean() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisplayMenuBar: true,
+ },
+ });
+
+ // Since testing will apply the policy after the browser has already started,
+ // we will need to open a new window to actually see the menu bar
+ let newWin = await BrowserTestUtils.openNewBrowserWindow();
+ let menubar = newWin.document.getElementById("toolbar-menubar");
+ is(
+ menubar.getAttribute("autohide"),
+ "false",
+ "The menu bar should not be hidden"
+ );
+
+ await BrowserTestUtils.closeWindow(newWin);
+});
+
+add_task(async function test_menu_shown_string() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisplayMenuBar: "default-on",
+ },
+ });
+
+ // Since testing will apply the policy after the browser has already started,
+ // we will need to open a new window to actually see the menu bar
+ let newWin = await BrowserTestUtils.openNewBrowserWindow();
+ let menubar = newWin.document.getElementById("toolbar-menubar");
+ is(
+ menubar.getAttribute("autohide"),
+ "false",
+ "The menu bar should not be hidden"
+ );
+
+ await BrowserTestUtils.closeWindow(newWin);
+});
+
+add_task(async function test_menubar_on() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisplayMenuBar: "always",
+ },
+ });
+
+ let newWin = await BrowserTestUtils.openNewBrowserWindow();
+ let menubar = newWin.document.getElementById("toolbar-menubar");
+ is(
+ menubar.hasAttribute("inactive"),
+ false,
+ "Menu bar should not have inactive"
+ );
+ is(
+ menubar.hasAttribute("toolbarname"),
+ false,
+ "Menu bar should not have a toolbarname"
+ );
+ await BrowserTestUtils.closeWindow(newWin);
+});
+
+add_task(async function test_menubar_off() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DisplayMenuBar: "never",
+ },
+ });
+
+ let newWin = await BrowserTestUtils.openNewBrowserWindow();
+ let menubar = newWin.document.getElementById("toolbar-menubar");
+ is(menubar.hasAttribute("inactive"), true, "Menu bar should have inactive");
+ is(
+ menubar.hasAttribute("toolbarname"),
+ false,
+ "Menu bar should not have a toolbarname"
+ );
+ await BrowserTestUtils.closeWindow(newWin);
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_downloads.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_downloads.js
new file mode 100644
index 0000000000..163745aaaf
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_downloads.js
@@ -0,0 +1,147 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const UCT_URI = "chrome://mozapps/content/downloads/unknownContentType.xhtml";
+
+add_task(async function test_defaultdownload() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DefaultDownloadDirectory: "${home}/Downloads",
+ PromptForDownloadLocation: false,
+ },
+ });
+
+ await BrowserTestUtils.withNewTab("about:preferences", async browser => {
+ is(
+ browser.contentDocument.getElementById("alwaysAsk").disabled,
+ true,
+ "alwaysAsk should be disabled."
+ );
+ let home = Services.dirsvc.get("Home", Ci.nsIFile).path;
+ is(
+ Services.prefs.getStringPref("browser.download.dir"),
+ home + "/Downloads",
+ "browser.download.dir should be ${home}/Downloads."
+ );
+ is(
+ Services.prefs.getBoolPref("browser.download.useDownloadDir"),
+ true,
+ "browser.download.useDownloadDir should be true."
+ );
+ is(
+ Services.prefs.prefIsLocked("browser.download.useDownloadDir"),
+ true,
+ "browser.download.useDownloadDir should be locked."
+ );
+ });
+});
+
+add_task(async function test_download() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ DownloadDirectory: "${home}/Documents",
+ },
+ });
+
+ await BrowserTestUtils.withNewTab("about:preferences", async browser => {
+ is(
+ browser.contentDocument.getElementById("alwaysAsk").disabled,
+ true,
+ "alwaysAsk should be disabled."
+ );
+ is(
+ browser.contentDocument.getElementById("downloadFolder").disabled,
+ true,
+ "downloadFolder should be disabled."
+ );
+ is(
+ browser.contentDocument.getElementById("chooseFolder").disabled,
+ true,
+ "chooseFolder should be disabled."
+ );
+ let home = Services.dirsvc.get("Home", Ci.nsIFile).path;
+ is(
+ Services.prefs.getStringPref("browser.download.dir"),
+ home + "/Documents",
+ "browser.download.dir should be ${home}/Documents."
+ );
+ is(
+ Services.prefs.getBoolPref("browser.download.useDownloadDir"),
+ true,
+ "browser.download.useDownloadDir should be true."
+ );
+ is(
+ Services.prefs.prefIsLocked("browser.download.useDownloadDir"),
+ true,
+ "browser.download.useDownloadDir should be locked."
+ );
+ });
+});
+
+async function setDownloadDir() {
+ let tmpDir = PathUtils.join(
+ PathUtils.tempDir,
+ "testsavedir" + Math.floor(Math.random() * 2 ** 32)
+ );
+ // Create this dir if it doesn't exist (ignores existing dirs)
+ await IOUtils.makeDirectory(tmpDir);
+ registerCleanupFunction(async function () {
+ try {
+ await IOUtils.remove(tmpDir, { recursive: true });
+ } catch (e) {
+ console.error(e);
+ }
+ });
+ Services.prefs.setIntPref("browser.download.folderList", 2);
+ Services.prefs.setCharPref("browser.download.dir", tmpDir);
+ return tmpDir;
+}
+
+add_task(async function test_tmpdir_download() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ StartDownloadsInTempDirectory: true,
+ },
+ });
+
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.download.always_ask_before_handling_new_types", true],
+ ["browser.helperApps.deleteTempFileOnExit", true],
+ ],
+ });
+
+ let dlDir = new FileUtils.File(await setDownloadDir());
+ registerCleanupFunction(() => {
+ Services.prefs.clearUserPref("browser.download.dir");
+ Services.prefs.clearUserPref("browser.download.folderList");
+ });
+
+ // Wait for the download prompting dialog
+ let dialogPromise = BrowserTestUtils.domWindowOpenedAndLoaded(
+ null,
+ win => win.document.documentURI == UCT_URI
+ );
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url: "https://example.com/browser/browser/components/downloads/test/browser/foo.txt",
+ waitForLoad: false,
+ waitForStop: true,
+ },
+ async function () {
+ let dialogWin = await dialogPromise;
+ let tempFile = dialogWin.dialog.mLauncher.targetFile;
+ isnot(
+ tempFile.parent.path,
+ dlDir.path,
+ "Should not have put temp file in the downloads dir."
+ );
+
+ dialogWin.close();
+ }
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_extensions.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_extensions.js
new file mode 100644
index 0000000000..7d1313548b
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_extensions.js
@@ -0,0 +1,117 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const ADDON_ID = "policytest@mozilla.com";
+const BASE_URL =
+ "http://mochi.test:8888/browser/browser/components/enterprisepolicies/tests/browser";
+
+async function isExtensionLocked(win, addonID) {
+ let addonCard = await TestUtils.waitForCondition(() => {
+ return win.document.querySelector(`addon-card[addon-id="${addonID}"]`);
+ }, `Get addon-card for "${addonID}"`);
+ let disableBtn = addonCard.querySelector('[action="toggle-disabled"]');
+ let removeBtn = addonCard.querySelector('panel-item[action="remove"]');
+ ok(removeBtn.disabled, "Remove button should be disabled");
+ ok(disableBtn.hidden, "Disable button should be hidden");
+}
+
+add_task(async function test_addon_install() {
+ let installPromise = waitForAddonInstall(ADDON_ID);
+ await setupPolicyEngineWithJson({
+ policies: {
+ Extensions: {
+ Install: [`${BASE_URL}/policytest_v0.1.xpi`],
+ Locked: [ADDON_ID],
+ },
+ },
+ });
+ await installPromise;
+ let addon = await AddonManager.getAddonByID(ADDON_ID);
+ isnot(addon, null, "Addon not installed.");
+ is(addon.version, "0.1", "Addon version is correct");
+
+ Assert.deepEqual(
+ addon.installTelemetryInfo,
+ { source: "enterprise-policy" },
+ "Got the expected addon.installTelemetryInfo"
+ );
+});
+
+add_task(async function test_addon_locked() {
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
+ const win = await BrowserOpenAddonsMgr("addons://list/extension");
+
+ await isExtensionLocked(win, ADDON_ID);
+
+ BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_addon_reinstall() {
+ // Test that uninstalling and reinstalling the same addon ID works as expected.
+ // This can be used to update an addon.
+
+ let uninstallPromise = waitForAddonUninstall(ADDON_ID);
+ let installPromise = waitForAddonInstall(ADDON_ID);
+ await setupPolicyEngineWithJson({
+ policies: {
+ Extensions: {
+ Uninstall: [ADDON_ID],
+ Install: [`${BASE_URL}/policytest_v0.2.xpi`],
+ },
+ },
+ });
+
+ // Older version was uninstalled
+ await uninstallPromise;
+
+ // New version was installed
+ await installPromise;
+
+ let addon = await AddonManager.getAddonByID(ADDON_ID);
+ isnot(
+ addon,
+ null,
+ "Addon still exists because the policy was used to update it."
+ );
+ is(addon.version, "0.2", "New version is correct");
+});
+
+add_task(async function test_addon_uninstall() {
+ EnterprisePolicyTesting.resetRunOnceState();
+
+ let uninstallPromise = waitForAddonUninstall(ADDON_ID);
+ await setupPolicyEngineWithJson({
+ policies: {
+ Extensions: {
+ Uninstall: [ADDON_ID],
+ },
+ },
+ });
+ await uninstallPromise;
+ let addon = await AddonManager.getAddonByID(ADDON_ID);
+ is(addon, null, "Addon should be uninstalled.");
+});
+
+add_task(async function test_addon_download_failure() {
+ // Test that if the download fails, the runOnce pref
+ // is cleared so that the download will happen again.
+
+ let installPromise = waitForAddonInstall(ADDON_ID);
+ await setupPolicyEngineWithJson({
+ policies: {
+ Extensions: {
+ Install: [`${BASE_URL}/policytest_invalid.xpi`],
+ },
+ },
+ });
+
+ await installPromise;
+ is(
+ Services.prefs.prefHasUserValue(
+ "browser.policies.runOncePerModification.extensionsInstall"
+ ),
+ false,
+ "runOnce pref should be unset"
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_extensionsettings.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_extensionsettings.js
new file mode 100644
index 0000000000..08dbcff6e2
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_extensionsettings.js
@@ -0,0 +1,261 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const BASE_URL =
+ "http://mochi.test:8888/browser/browser/components/enterprisepolicies/tests/browser/";
+
+/**
+ * Wait for the given PopupNotification to display
+ *
+ * @param {string} name
+ * The name of the notification to wait for.
+ *
+ * @returns {Promise}
+ * Resolves with the notification window.
+ */
+function promisePopupNotificationShown(name) {
+ return new Promise(resolve => {
+ function popupshown() {
+ let notification = PopupNotifications.getNotification(name);
+ if (!notification) {
+ return;
+ }
+
+ ok(notification, `${name} notification shown`);
+ ok(PopupNotifications.isPanelOpen, "notification panel open");
+
+ PopupNotifications.panel.removeEventListener("popupshown", popupshown);
+ resolve(PopupNotifications.panel.firstElementChild);
+ }
+
+ PopupNotifications.panel.addEventListener("popupshown", popupshown);
+ });
+}
+
+add_setup(async function setupTestEnvironment() {
+ // Once InstallTrigger is removed, the tests targeting InstallTrigger should
+ // be removed or adapted to don't use InstallTrigger.
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["extensions.InstallTrigger.enabled", true],
+ ["extensions.InstallTriggerImpl.enabled", true],
+ // Relax the user input requirements while running this test.
+ ["xpinstall.userActivation.required", false],
+ ],
+ });
+});
+
+add_task(async function test_install_source_blocked_link() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "*": {
+ install_sources: ["http://blocks.other.install.sources/*"],
+ },
+ },
+ },
+ });
+ let popupPromise = promisePopupNotificationShown(
+ "addon-install-policy-blocked"
+ );
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ opening: BASE_URL + "extensionsettings.html",
+ waitForStateStop: true,
+ });
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], () => {
+ content.document.getElementById("policytest").click();
+ });
+ await popupPromise;
+ BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_install_source_blocked_installtrigger() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "*": {
+ install_sources: ["http://blocks.other.install.sources/*"],
+ blocked_install_message: "blocked_install_message",
+ },
+ },
+ },
+ });
+ let popupPromise = promisePopupNotificationShown(
+ "addon-install-policy-blocked"
+ );
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ opening: BASE_URL + "extensionsettings.html",
+ waitForStateStop: true,
+ });
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], () => {
+ content.document.getElementById("policytest_installtrigger").click();
+ });
+ let popup = await popupPromise;
+ let description = popup.querySelector(".popup-notification-description");
+ ok(
+ description.textContent.endsWith("blocked_install_message"),
+ "Custom install message present"
+ );
+ BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_install_source_blocked_otherdomain() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "*": {
+ install_sources: ["http://mochi.test/*"],
+ },
+ },
+ },
+ });
+ let popupPromise = promisePopupNotificationShown(
+ "addon-install-policy-blocked"
+ );
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ opening: BASE_URL + "extensionsettings.html",
+ waitForStateStop: true,
+ });
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], () => {
+ content.document.getElementById("policytest_otherdomain").click();
+ });
+ await popupPromise;
+ BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_install_source_blocked_direct() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "*": {
+ install_sources: ["http://blocks.other.install.sources/*"],
+ },
+ },
+ },
+ });
+ let popupPromise = promisePopupNotificationShown(
+ "addon-install-policy-blocked"
+ );
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ opening: BASE_URL + "extensionsettings.html",
+ waitForStateStop: true,
+ });
+
+ await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [{ baseUrl: BASE_URL }],
+ async function ({ baseUrl }) {
+ content.document.location.href = baseUrl + "policytest_v0.1.xpi";
+ }
+ );
+ await popupPromise;
+ BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_install_source_allowed_link() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "*": {
+ install_sources: ["http://mochi.test/*"],
+ },
+ },
+ },
+ });
+ let popupPromise = promisePopupNotificationShown("addon-webext-permissions");
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ opening: BASE_URL + "extensionsettings.html",
+ waitForStateStop: true,
+ });
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], () => {
+ content.document.getElementById("policytest").click();
+ });
+ await popupPromise;
+ BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_install_source_allowed_installtrigger() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "*": {
+ install_sources: ["http://mochi.test/*"],
+ },
+ },
+ },
+ });
+ let popupPromise = promisePopupNotificationShown("addon-webext-permissions");
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ opening: BASE_URL + "extensionsettings.html",
+ waitForStateStop: true,
+ });
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], () => {
+ content.document.getElementById("policytest_installtrigger").click();
+ });
+ await popupPromise;
+ BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_install_source_allowed_otherdomain() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "*": {
+ install_sources: ["http://mochi.test/*", "http://example.org/*"],
+ },
+ },
+ },
+ });
+ let popupPromise = promisePopupNotificationShown("addon-webext-permissions");
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ opening: BASE_URL + "extensionsettings.html",
+ waitForStateStop: true,
+ });
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], () => {
+ content.document.getElementById("policytest_otherdomain").click();
+ });
+ await popupPromise;
+ BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_install_source_allowed_direct() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "*": {
+ install_sources: ["http://mochi.test/*"],
+ },
+ },
+ },
+ });
+ let popupPromise = promisePopupNotificationShown("addon-webext-permissions");
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ opening: BASE_URL + "extensionsettings.html",
+ waitForStateStop: true,
+ });
+
+ await SpecialPowers.spawn(
+ tab.linkedBrowser,
+ [{ baseUrl: BASE_URL }],
+ async function ({ baseUrl }) {
+ content.document.location.href = baseUrl + "policytest_v0.1.xpi";
+ }
+ );
+ await popupPromise;
+ BrowserTestUtils.removeTab(tab);
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_extensionsettings2.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_extensionsettings2.js
new file mode 100644
index 0000000000..612448ee4e
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_extensionsettings2.js
@@ -0,0 +1,71 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const ADDON_ID = "policytest@mozilla.com";
+const BASE_URL =
+ "http://mochi.test:8888/browser/browser/components/enterprisepolicies/tests/browser";
+
+async function isExtensionLockedAndUpdateDisabled(win, addonID) {
+ let addonCard = await BrowserTestUtils.waitForCondition(() => {
+ return win.document.querySelector(`addon-card[addon-id="${addonID}"]`);
+ }, `Get addon-card for "${addonID}"`);
+ let disableBtn = addonCard.querySelector('[action="toggle-disabled"]');
+ let removeBtn = addonCard.querySelector('panel-item[action="remove"]');
+ ok(removeBtn.disabled, "Remove button should be disabled");
+ ok(disableBtn.hidden, "Disable button should be hidden");
+ let updateRow = addonCard.querySelector(".addon-detail-row-updates");
+ is(updateRow.hidden, true, "Update row should be hidden");
+}
+
+add_task(async function test_addon_install() {
+ let installPromise = waitForAddonInstall(ADDON_ID);
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "policytest@mozilla.com": {
+ install_url: `${BASE_URL}/policytest_v0.1.xpi`,
+ installation_mode: "force_installed",
+ updates_disabled: true,
+ },
+ },
+ },
+ });
+ await installPromise;
+ let addon = await AddonManager.getAddonByID(ADDON_ID);
+ isnot(addon, null, "Addon not installed.");
+ is(addon.version, "0.1", "Addon version is correct");
+
+ Assert.deepEqual(
+ addon.installTelemetryInfo,
+ { source: "enterprise-policy" },
+ "Got the expected addon.installTelemetryInfo"
+ );
+});
+
+add_task(async function test_addon_locked_update_disabled() {
+ let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser);
+ const win = await BrowserOpenAddonsMgr(
+ "addons://detail/" + encodeURIComponent(ADDON_ID)
+ );
+
+ await isExtensionLockedAndUpdateDisabled(win, ADDON_ID);
+
+ BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_addon_uninstall() {
+ let uninstallPromise = waitForAddonUninstall(ADDON_ID);
+ await setupPolicyEngineWithJson({
+ policies: {
+ ExtensionSettings: {
+ "policytest@mozilla.com": {
+ installation_mode: "blocked",
+ },
+ },
+ },
+ });
+ await uninstallPromise;
+ let addon = await AddonManager.getAddonByID(ADDON_ID);
+ is(addon, null, "Addon should be uninstalled.");
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_firefoxhome.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_firefoxhome.js
new file mode 100644
index 0000000000..67afe70c2f
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_firefoxhome.js
@@ -0,0 +1,132 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_setup(async function () {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ ["browser.newtabpage.activity-stream.feeds.section.highlights", true],
+ ],
+ });
+});
+
+add_task(async function test_firefox_home_without_policy_without_pocket() {
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ opening: "about:home",
+ waitForStateStop: true,
+ });
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], function () {
+ let search = content.document.querySelector(".search-wrapper");
+ isnot(search, null, "Search section should be there.");
+ let topsites = content.document.querySelector(
+ "section[data-section-id='topsites']"
+ );
+ isnot(topsites, null, "Top Sites section should be there.");
+ let highlights = content.document.querySelector(
+ "section[data-section-id='highlights']"
+ );
+ isnot(highlights, null, "Highlights section should be there.");
+ });
+ BrowserTestUtils.removeTab(tab);
+ await SpecialPowers.popPrefEnv();
+});
+
+add_task(async function test_firefox_home_with_policy() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ [
+ "browser.newtabpage.activity-stream.discoverystream.endpointSpocsClear",
+ "",
+ ],
+ ],
+ });
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ FirefoxHome: {
+ Search: false,
+ TopSites: false,
+ Highlights: false,
+ Snippets: false,
+ },
+ },
+ });
+
+ let tab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ opening: "about:home",
+ waitForStateStop: true,
+ });
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], function () {
+ let search = content.document.querySelector(".search-wrapper");
+ is(search, null, "Search section should not be there.");
+ let topsites = content.document.querySelector(
+ "section[data-section-id='topsites']"
+ );
+ is(topsites, null, "Top Sites section should not be there.");
+ let highlights = content.document.querySelector(
+ "section[data-section-id='highlights']"
+ );
+ is(highlights, null, "Highlights section should not be there.");
+ });
+ BrowserTestUtils.removeTab(tab);
+ await SpecialPowers.popPrefEnv();
+});
+
+add_task(async function test_firefoxhome_preferences_set() {
+ await SpecialPowers.pushPrefEnv({
+ set: [
+ [
+ "browser.newtabpage.activity-stream.discoverystream.endpointSpocsClear",
+ "",
+ ],
+ ],
+ });
+
+ await setupPolicyEngineWithJson({
+ policies: {
+ FirefoxHome: {
+ Search: false,
+ TopSites: false,
+ SponsoredTopSites: false,
+ Highlights: false,
+ Pocket: false,
+ SponsoredPocket: false,
+ Snippets: false,
+ Locked: true,
+ },
+ },
+ });
+
+ await BrowserTestUtils.withNewTab("about:preferences#home", async browser => {
+ let data = {
+ Search: "browser.newtabpage.activity-stream.showSearch",
+ TopSites: "browser.newtabpage.activity-stream.feeds.topsites",
+ SponsoredTopSites:
+ "browser.newtabpage.activity-stream.showSponsoredTopSites",
+ Highlights: "browser.newtabpage.activity-stream.feeds.section.highlights",
+ Pocket: "browser.newtabpage.activity-stream.feeds.section.topstories",
+ SponsoredPocket: "browser.newtabpage.activity-stream.showSponsored",
+ Snippets: "browser.newtabpage.activity-stream.feeds.snippets",
+ };
+ for (let [section, preference] of Object.entries(data)) {
+ is(
+ browser.contentDocument.querySelector(
+ `checkbox[preference='${preference}']`
+ ).disabled,
+ true,
+ `${section} checkbox should be disabled`
+ );
+ }
+ });
+ await setupPolicyEngineWithJson({
+ policies: {
+ FirefoxHome: {},
+ },
+ });
+ await SpecialPowers.popPrefEnv();
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_firefoxsuggest.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_firefoxsuggest.js
new file mode 100644
index 0000000000..e6f7b02772
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_firefoxsuggest.js
@@ -0,0 +1,63 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_firefox_suggest_with_policy() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ FirefoxSuggest: {
+ WebSuggestions: false,
+ SponsoredSuggestions: true,
+ ImproveSuggest: true,
+ Locked: true,
+ },
+ },
+ });
+
+ await BrowserTestUtils.withNewTab(
+ "about:preferences#privacy",
+ async browser => {
+ is(
+ browser.contentDocument.getElementById(
+ "firefoxSuggestNonsponsoredToggle"
+ ).pressed,
+ false,
+ "Web suggestions is disabled"
+ );
+ is(
+ browser.contentDocument.getElementById("firefoxSuggestSponsoredToggle")
+ .pressed,
+ true,
+ "Sponsored suggestions is enabled"
+ );
+ is(
+ browser.contentDocument.getElementById(
+ "firefoxSuggestDataCollectionToggle"
+ ).pressed,
+ true,
+ "Improve suggest is enabled"
+ );
+ is(
+ browser.contentDocument.getElementById(
+ "firefoxSuggestNonsponsoredToggle"
+ ).disabled,
+ true,
+ "Web suggestions is disabled"
+ );
+ is(
+ browser.contentDocument.getElementById("firefoxSuggestSponsoredToggle")
+ .disabled,
+ true,
+ "Sponsored suggestions is enabled"
+ );
+ is(
+ browser.contentDocument.getElementById(
+ "firefoxSuggestDataCollectionToggle"
+ ).disabled,
+ true,
+ "Improve suggest is enabled"
+ );
+ }
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_handlers.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_handlers.js
new file mode 100644
index 0000000000..45debf73c9
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_handlers.js
@@ -0,0 +1,183 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const gMIMEService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
+
+const gExternalProtocolService = Cc[
+ "@mozilla.org/uriloader/external-protocol-service;1"
+].getService(Ci.nsIExternalProtocolService);
+
+const gHandlerService = Cc[
+ "@mozilla.org/uriloader/handler-service;1"
+].getService(Ci.nsIHandlerService);
+
+// This seems odd, but for test purposes, this just has to be a file that we know exists,
+// and by using this file, we don't have to worry about different platforms.
+let exeFile = Services.dirsvc.get("XREExeF", Ci.nsIFile);
+
+add_task(async function test_valid_handlers() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Handlers: {
+ mimeTypes: {
+ "application/marimba": {
+ action: "useHelperApp",
+ ask: true,
+ handlers: [
+ {
+ name: "Launch",
+ path: exeFile.path,
+ },
+ ],
+ },
+ },
+ schemes: {
+ fake_scheme: {
+ action: "useHelperApp",
+ ask: false,
+ handlers: [
+ {
+ name: "Name",
+ uriTemplate: "https://www.example.org/?%s",
+ },
+ ],
+ },
+ },
+ extensions: {
+ txt: {
+ action: "saveToDisk",
+ ask: false,
+ },
+ },
+ },
+ },
+ });
+
+ let handlerInfo = gMIMEService.getFromTypeAndExtension(
+ "application/marimba",
+ ""
+ );
+ is(handlerInfo.preferredAction, handlerInfo.useHelperApp);
+ is(handlerInfo.alwaysAskBeforeHandling, true);
+ is(handlerInfo.preferredApplicationHandler.name, "Launch");
+ is(handlerInfo.preferredApplicationHandler.executable.path, exeFile.path);
+
+ handlerInfo.preferredApplicationHandler = null;
+ gHandlerService.store(handlerInfo);
+
+ handlerInfo = handlerInfo = gMIMEService.getFromTypeAndExtension(
+ "application/marimba",
+ ""
+ );
+ is(handlerInfo.preferredApplicationHandler, null);
+
+ gHandlerService.remove(handlerInfo);
+
+ handlerInfo = gExternalProtocolService.getProtocolHandlerInfo("fake_scheme");
+ is(handlerInfo.preferredAction, handlerInfo.useHelperApp);
+ is(handlerInfo.alwaysAskBeforeHandling, false);
+ is(handlerInfo.preferredApplicationHandler.name, "Name");
+ is(
+ handlerInfo.preferredApplicationHandler.uriTemplate,
+ "https://www.example.org/?%s"
+ );
+
+ handlerInfo.preferredApplicationHandler = null;
+ gHandlerService.store(handlerInfo);
+
+ handlerInfo = gExternalProtocolService.getProtocolHandlerInfo("fake_scheme");
+ is(handlerInfo.preferredApplicationHandler, null);
+
+ gHandlerService.remove(handlerInfo);
+
+ handlerInfo = gMIMEService.getFromTypeAndExtension("", "txt");
+ is(handlerInfo.preferredAction, handlerInfo.saveToDisk);
+ is(handlerInfo.alwaysAskBeforeHandling, false);
+
+ handlerInfo.preferredApplicationHandler = null;
+ gHandlerService.store(handlerInfo);
+ handlerInfo = gMIMEService.getFromTypeAndExtension("", "txt");
+ is(handlerInfo.preferredApplicationHandler, null);
+
+ gHandlerService.remove(handlerInfo);
+});
+
+add_task(async function test_no_handler() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Handlers: {
+ schemes: {
+ no_handler: {
+ action: "useHelperApp",
+ },
+ },
+ },
+ },
+ });
+
+ let handlerInfo =
+ gExternalProtocolService.getProtocolHandlerInfo("no_handler");
+ is(handlerInfo.preferredAction, handlerInfo.alwaysAsk);
+ is(handlerInfo.alwaysAskBeforeHandling, true);
+ is(handlerInfo.preferredApplicationHandler, null);
+
+ gHandlerService.remove(handlerInfo);
+});
+
+add_task(async function test_bad_web_handler1() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Handlers: {
+ schemes: {
+ bas_web_handler1: {
+ action: "useHelperApp",
+ handlers: [
+ {
+ name: "Name",
+ uriTemplate: "http://www.example.org/?%s",
+ },
+ ],
+ },
+ },
+ },
+ },
+ });
+
+ let handlerInfo =
+ gExternalProtocolService.getProtocolHandlerInfo("bad_web_handler1");
+ is(handlerInfo.preferredAction, handlerInfo.alwaysAsk);
+ is(handlerInfo.alwaysAskBeforeHandling, true);
+ is(handlerInfo.preferredApplicationHandler, null);
+
+ gHandlerService.remove(handlerInfo);
+});
+
+add_task(async function test_bad_web_handler2() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Handlers: {
+ schemes: {
+ bas_web_handler1: {
+ action: "useHelperApp",
+ handlers: [
+ {
+ name: "Name",
+ uriTemplate: "http://www.example.org/",
+ },
+ ],
+ },
+ },
+ },
+ },
+ });
+
+ let handlerInfo =
+ gExternalProtocolService.getProtocolHandlerInfo("bad_web_handler1");
+ is(handlerInfo.preferredAction, handlerInfo.alwaysAsk);
+ is(handlerInfo.alwaysAskBeforeHandling, true);
+ is(handlerInfo.preferredApplicationHandler, null);
+
+ gHandlerService.remove(handlerInfo);
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_masterpassword.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_masterpassword.js
new file mode 100644
index 0000000000..872eb5a652
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_masterpassword.js
@@ -0,0 +1,95 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+let { LoginTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/LoginTestUtils.sys.mjs"
+);
+
+// Test that once a password is set, you can't unset it
+add_task(async function test_policy_masterpassword_set() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ PrimaryPassword: true,
+ },
+ });
+
+ LoginTestUtils.primaryPassword.enable();
+
+ await BrowserTestUtils.withNewTab(
+ "about:preferences#privacy",
+ async browser => {
+ is(
+ browser.contentDocument.getElementById("useMasterPassword").disabled,
+ true,
+ "Master Password checkbox should be disabled"
+ );
+ }
+ );
+
+ LoginTestUtils.primaryPassword.disable();
+});
+
+// Test that password can't be removed in changemp.xhtml
+add_task(async function test_policy_nochangemp() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ PrimaryPassword: true,
+ },
+ });
+
+ LoginTestUtils.primaryPassword.enable();
+
+ let changeMPWindow = window.openDialog(
+ "chrome://mozapps/content/preferences/changemp.xhtml",
+ "",
+ ""
+ );
+ await BrowserTestUtils.waitForEvent(changeMPWindow, "load");
+
+ is(
+ changeMPWindow.document.getElementById("admin").hidden,
+ true,
+ "Admin message should not be visible because there is a password."
+ );
+
+ changeMPWindow.document.getElementById("oldpw").value =
+ LoginTestUtils.primaryPassword.masterPassword;
+
+ is(
+ changeMPWindow.document.getElementById("changemp").getButton("accept")
+ .disabled,
+ true,
+ "OK button should not be enabled if there is an old password."
+ );
+
+ await BrowserTestUtils.closeWindow(changeMPWindow);
+
+ LoginTestUtils.primaryPassword.disable();
+});
+
+// Test that admin message shows
+add_task(async function test_policy_admin() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ PrimaryPassword: true,
+ },
+ });
+
+ let changeMPWindow = window.openDialog(
+ "chrome://mozapps/content/preferences/changemp.xhtml",
+ "",
+ ""
+ );
+ await BrowserTestUtils.waitForEvent(changeMPWindow, "load");
+
+ is(
+ changeMPWindow.document.getElementById("admin").hidden,
+ false,
+ true,
+ "Admin message should not be hidden because there is not a password."
+ );
+
+ await BrowserTestUtils.closeWindow(changeMPWindow);
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_masterpassword_aboutlogins.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_masterpassword_aboutlogins.js
new file mode 100644
index 0000000000..91cc9ebc2e
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_masterpassword_aboutlogins.js
@@ -0,0 +1,76 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+let { LoginTestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/LoginTestUtils.sys.mjs"
+);
+
+// Test that create in about:logins asks for primary password
+add_task(async function test_policy_admin() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ PrimaryPassword: true,
+ },
+ });
+
+ let aboutLoginsTab = await BrowserTestUtils.openNewForegroundTab({
+ gBrowser,
+ url: "about:logins",
+ });
+
+ let browser = gBrowser.selectedBrowser;
+
+ // Fake the subdialog
+ let dialogURL = "";
+ let originalOpenDialog = window.openDialog;
+ window.openDialog = function (aDialogURL, unused, unused2, aCallback) {
+ dialogURL = aDialogURL;
+ if (aCallback) {
+ aCallback();
+ }
+ };
+
+ await SpecialPowers.spawn(browser, [], async () => {
+ let loginList = Cu.waiveXrays(content.document.querySelector("login-list"));
+ let createButton = loginList._createLoginButton;
+ ok(
+ !createButton.disabled,
+ "Create button should not be disabled initially"
+ );
+ let loginItem = Cu.waiveXrays(content.document.querySelector("login-item"));
+
+ createButton.click();
+
+ let usernameInput = loginItem.shadowRoot.querySelector(
+ "input[name='username']"
+ );
+ let originInput = loginItem.shadowRoot.querySelector(
+ "input[name='origin']"
+ );
+ let passwordInput = loginItem.shadowRoot.querySelector(
+ "input[name='password']"
+ );
+
+ originInput.value = "https://www.example.org";
+ usernameInput.value = "testuser1";
+ passwordInput.value = "testpass1";
+
+ let saveChangesButton = loginItem.shadowRoot.querySelector(
+ ".save-changes-button"
+ );
+ saveChangesButton.click();
+ });
+ await TestUtils.waitForCondition(
+ () => dialogURL,
+ "wait for open to get called asynchronously"
+ );
+ is(
+ dialogURL,
+ "chrome://mozapps/content/preferences/changemp.xhtml",
+ "clicking on the save-changes-button should open the masterpassword dialog"
+ );
+ window.openDialog = originalOpenDialog;
+ BrowserTestUtils.removeTab(aboutLoginsTab);
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_masterpassword_doorhanger.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_masterpassword_doorhanger.js
new file mode 100644
index 0000000000..224ad1d275
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_masterpassword_doorhanger.js
@@ -0,0 +1,76 @@
+/**
+ * Test that the doorhanger notification for password saving is populated with
+ * the correct values in various password capture cases.
+ */
+
+Services.scriptloader.loadSubScript(
+ "chrome://mochitests/content/browser/toolkit/components/passwordmgr/test/browser/head.js",
+ this
+);
+
+add_task(async function test_policy_masterpassword_doorhanger() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ PrimaryPassword: true,
+ },
+ });
+
+ let username = "username";
+ let password = "password";
+
+ await BrowserTestUtils.withNewTab(
+ {
+ gBrowser,
+ url:
+ "https://example.com/browser/toolkit/components/" +
+ "passwordmgr/test/browser/form_basic.html",
+ },
+ async function (browser) {
+ await SimpleTest.promiseFocus(browser.ownerGlobal);
+
+ // Update the form with credentials from the test case.
+ info(`update form with username: ${username}, password: ${password}`);
+ await changeContentFormValues(browser, {
+ "#form-basic-username": username,
+ "#form-basic-password": password,
+ });
+
+ // Submit the form with the new credentials. This will cause the doorhanger
+ // notification to be displayed.
+ let formSubmittedPromise = listenForTestNotification("ShowDoorhanger");
+ await SpecialPowers.spawn(browser, [], async function () {
+ let doc = this.content.document;
+ doc.getElementById("form-basic").submit();
+ });
+ await formSubmittedPromise;
+
+ let expectedDoorhanger = "password-save";
+
+ info("Waiting for doorhanger of type: " + expectedDoorhanger);
+ let notif = await waitForDoorhanger(browser, expectedDoorhanger);
+
+ // Fake the subdialog
+ let dialogURL = "";
+ let originalOpenDialog = window.openDialog;
+ window.openDialog = function (aDialogURL, unused, unused2, aCallback) {
+ dialogURL = aDialogURL;
+ if (aCallback) {
+ aCallback();
+ }
+ };
+
+ await clickDoorhangerButton(notif, REMEMBER_BUTTON);
+
+ await TestUtils.waitForCondition(
+ () => dialogURL,
+ "wait for open to get called asynchronously"
+ );
+ is(
+ dialogURL,
+ "chrome://mozapps/content/preferences/changemp.xhtml",
+ "clicking on the checkbox should open the masterpassword dialog"
+ );
+ window.openDialog = originalOpenDialog;
+ }
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_offertosavelogins.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_offertosavelogins.js
new file mode 100644
index 0000000000..5ad1fe44d1
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_offertosavelogins.js
@@ -0,0 +1,23 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_policy_offertosavelogins() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ OfferToSaveLogins: false,
+ },
+ });
+
+ await BrowserTestUtils.withNewTab(
+ "about:preferences#privacy",
+ async browser => {
+ is(
+ browser.contentDocument.getElementById("savePasswords").disabled,
+ true,
+ "Save passwords is disabled"
+ );
+ }
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_override_postupdatepage.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_override_postupdatepage.js
new file mode 100644
index 0000000000..2208ee955f
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_override_postupdatepage.js
@@ -0,0 +1,132 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+// This test was based on the test browser_bug538331.js
+
+const UPDATE_PROVIDED_PAGE = "https://default.example.com/";
+const POLICY_PROVIDED_PAGE = "https://policy.example.com/";
+
+const PREF_MSTONE = "browser.startup.homepage_override.mstone";
+
+/*
+ * The important parts for this test are:
+ * - actions="showURL"
+ * - openURL="${UPDATE_PROVIDED_PAGE}"
+ */
+const XML_UPDATE = `<?xml version="1.0"?>
+<updates xmlns="http://www.mozilla.org/2005/app-update">
+ <update appVersion="1.0" buildID="20080811053724" channel="nightly"
+ displayVersion="Version 1.0" installDate="1238441400314"
+ isCompleteUpdate="true" name="Update Test 1.0" type="minor"
+ detailsURL="http://example.com/" previousAppVersion="1.0"
+ serviceURL="https://example.com/" statusText="The Update was successfully installed"
+ foregroundDownload="true"
+ actions="showURL"
+ openURL="${UPDATE_PROVIDED_PAGE}">
+ <patch type="complete" URL="http://example.com/" size="775" selected="true" state="succeeded"/>
+ </update>
+</updates>`;
+
+add_task(async function test_override_postupdate_page() {
+ let originalMstone = Services.prefs.getCharPref(PREF_MSTONE);
+ // Set the preferences needed for the test: they will be cleared up
+ // after it runs.
+ await SpecialPowers.pushPrefEnv({ set: [[PREF_MSTONE, originalMstone]] });
+
+ registerCleanupFunction(async () => {
+ let activeUpdateFile = getActiveUpdateFile();
+ activeUpdateFile.remove(false);
+ reloadUpdateManagerData(true);
+ });
+
+ writeUpdatesToXMLFile(XML_UPDATE);
+ reloadUpdateManagerData(false);
+
+ is(
+ getPostUpdatePage(),
+ UPDATE_PROVIDED_PAGE,
+ "Post-update page was provided by active-update.xml."
+ );
+
+ // Now perform the same action but set the policy to override this page
+ await setupPolicyEngineWithJson({
+ policies: {
+ OverridePostUpdatePage: POLICY_PROVIDED_PAGE,
+ },
+ });
+
+ is(
+ getPostUpdatePage(),
+ POLICY_PROVIDED_PAGE,
+ "Post-update page was provided by policy."
+ );
+});
+
+function getPostUpdatePage() {
+ Services.prefs.setCharPref(PREF_MSTONE, "PreviousMilestone");
+ return Cc["@mozilla.org/browser/clh;1"].getService(Ci.nsIBrowserHandler)
+ .defaultArgs;
+}
+
+/**
+ * Removes the updates.xml file and returns the nsIFile for the
+ * active-update.xml file.
+ *
+ * @return The nsIFile for the active-update.xml file.
+ */
+function getActiveUpdateFile() {
+ let updateRootDir = Services.dirsvc.get("UpdRootD", Ci.nsIFile);
+ let updatesFile = updateRootDir.clone();
+ updatesFile.append("updates.xml");
+ if (updatesFile.exists()) {
+ // The following is non-fatal.
+ try {
+ updatesFile.remove(false);
+ } catch (e) {}
+ }
+ let activeUpdateFile = updateRootDir.clone();
+ activeUpdateFile.append("active-update.xml");
+ return activeUpdateFile;
+}
+
+/**
+ * Reloads the update xml files.
+ *
+ * @param skipFiles (optional)
+ * If true, the update xml files will not be read and the metadata will
+ * be reset. If false (the default), the update xml files will be read
+ * to populate the update metadata.
+ */
+function reloadUpdateManagerData(skipFiles = false) {
+ Cc["@mozilla.org/updates/update-manager;1"]
+ .getService(Ci.nsIUpdateManager)
+ .QueryInterface(Ci.nsIObserver)
+ .observe(null, "um-reload-update-data", skipFiles ? "skip-files" : "");
+}
+
+/**
+ * Writes the updates specified to the active-update.xml file.
+ *
+ * @param aText
+ * The updates represented as a string to write to the active-update.xml
+ * file.
+ */
+function writeUpdatesToXMLFile(aText) {
+ const PERMS_FILE = 0o644;
+
+ const MODE_WRONLY = 0x02;
+ const MODE_CREATE = 0x08;
+ const MODE_TRUNCATE = 0x20;
+
+ let activeUpdateFile = getActiveUpdateFile();
+ if (!activeUpdateFile.exists()) {
+ activeUpdateFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, PERMS_FILE);
+ }
+ let fos = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(
+ Ci.nsIFileOutputStream
+ );
+ let flags = MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE;
+ fos.init(activeUpdateFile, flags, PERMS_FILE, 0);
+ fos.write(aText, aText.length);
+ fos.close();
+}
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_pageinfo_permissions.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_pageinfo_permissions.js
new file mode 100644
index 0000000000..4921464782
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_pageinfo_permissions.js
@@ -0,0 +1,76 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const TEST_ORIGIN = "https://example.com";
+
+/* Verifies that items on the page info page are properly disabled
+ when the corresponding policies are locked */
+add_task(async function test_pageinfo_permissions() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Permissions: {
+ Camera: {
+ BlockNewRequests: true,
+ Locked: true,
+ },
+ Microphone: {
+ BlockNewRequests: true,
+ Locked: true,
+ },
+ Location: {
+ BlockNewRequests: true,
+ Locked: true,
+ },
+ Notifications: {
+ BlockNewRequests: true,
+ Locked: true,
+ },
+ VirtualReality: {
+ BlockNewRequests: true,
+ Locked: true,
+ },
+ Autoplay: {
+ Default: "block-audio",
+ Locked: true,
+ },
+ },
+ InstallAddonsPermission: {
+ Default: false,
+ },
+ PopupBlocking: {
+ Locked: true,
+ },
+ Cookies: {
+ Locked: true,
+ },
+ },
+ });
+
+ let permissions = [
+ "geo",
+ "autoplay-media",
+ "install",
+ "popup",
+ "desktop-notification",
+ "cookie",
+ "camera",
+ "microphone",
+ "xr",
+ ];
+
+ await BrowserTestUtils.withNewTab(TEST_ORIGIN, async function (browser) {
+ let pageInfo = BrowserPageInfo(TEST_ORIGIN, "permTab");
+ await BrowserTestUtils.waitForEvent(pageInfo, "load");
+
+ for (let i = 0; i < permissions.length; i++) {
+ let permission = permissions[i];
+ let checkbox = await TestUtils.waitForCondition(() =>
+ pageInfo.document.getElementById(`${permission}Def`)
+ );
+
+ ok(checkbox.disabled, `${permission} checkbox should be disabled`);
+ }
+
+ pageInfo.close();
+ });
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_passwordmanager.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_passwordmanager.js
new file mode 100644
index 0000000000..f62d6cbf50
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_passwordmanager.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_pwmanager_blocked() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ PasswordManagerEnabled: false,
+ },
+ });
+
+ await BrowserTestUtils.withNewTab(
+ "about:preferences#privacy",
+ async browser => {
+ is(
+ browser.contentDocument.getElementById("showPasswords").disabled,
+ true,
+ "showPasswords should be disabled."
+ );
+ }
+ );
+
+ await testPageBlockedByPolicy("about:logins");
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_search_engine.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_search_engine.js
new file mode 100644
index 0000000000..c0b7b20535
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_search_engine.js
@@ -0,0 +1,109 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ CustomizableUITestUtils:
+ "resource://testing-common/CustomizableUITestUtils.sys.mjs",
+});
+
+let gCUITestUtils = new CustomizableUITestUtils(window);
+
+add_task(async function test_setup() {
+ await gCUITestUtils.addSearchBar();
+ registerCleanupFunction(() => {
+ gCUITestUtils.removeSearchBar();
+ });
+});
+
+// |shouldWork| should be true if opensearch is expected to work and false if
+// it is not.
+async function test_opensearch(shouldWork) {
+ let searchBar = BrowserSearch.searchBar;
+
+ let rootDir = getRootDirectory(gTestPath);
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ rootDir + "opensearch.html"
+ );
+ let searchPopup = document.getElementById("PopupSearchAutoComplete");
+ let promiseSearchPopupShown = BrowserTestUtils.waitForEvent(
+ searchPopup,
+ "popupshown"
+ );
+ let searchBarButton = searchBar.querySelector(".searchbar-search-button");
+
+ searchBarButton.click();
+ await promiseSearchPopupShown;
+ let oneOffsContainer = searchPopup.searchOneOffsContainer;
+ let engineElement = oneOffsContainer.querySelector(
+ ".searchbar-engine-one-off-add-engine"
+ );
+ if (shouldWork) {
+ ok(engineElement, "There should be search engines available to add");
+ ok(
+ searchBar.getAttribute("addengines"),
+ "Search bar should have addengines attribute"
+ );
+ } else {
+ is(
+ engineElement,
+ null,
+ "There should be no search engines available to add"
+ );
+ ok(
+ !searchBar.getAttribute("addengines"),
+ "Search bar should not have addengines attribute"
+ );
+ }
+ await BrowserTestUtils.removeTab(tab);
+}
+
+add_task(async function test_opensearch_works() {
+ // Clear out policies so we can test with no policies applied
+ await setupPolicyEngineWithJson({
+ policies: {},
+ });
+ // Ensure that opensearch works before we make sure that it can be properly
+ // disabled
+ await test_opensearch(true);
+});
+
+add_task(async function setup_prevent_installs() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ SearchEngines: {
+ PreventInstalls: true,
+ },
+ },
+ });
+});
+
+add_task(async function test_prevent_install_ui() {
+ // Check that about:preferences does not prompt user to install search engines
+ // if that feature is disabled
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:preferences#search"
+ );
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ let linkContainer = content.document.getElementById("addEnginesBox");
+ if (!linkContainer.hidden) {
+ await ContentTaskUtils.waitForMutationCondition(
+ linkContainer,
+ { attributeFilter: ["hidden"] },
+ () => linkContainer.hidden
+ );
+ }
+ ok(
+ linkContainer.hidden,
+ '"Find more search engines" link should be hidden'
+ );
+ });
+ await BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_opensearch_disabled() {
+ // Check that search engines cannot be added via opensearch
+ await test_opensearch(false);
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_searchbar.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_searchbar.js
new file mode 100644
index 0000000000..af892f2813
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_searchbar.js
@@ -0,0 +1,36 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_setup(async function () {
+ await setupPolicyEngineWithJson({
+ policies: {
+ SearchBar: "separate",
+ },
+ });
+});
+
+add_task(async function test_menu_shown() {
+ let newWin = await BrowserTestUtils.openNewBrowserWindow();
+ let placement = CustomizableUI.getPlacementOfWidget("search-container");
+ isnot(placement, null, "Search bar has a placement");
+ is(
+ placement.area,
+ CustomizableUI.AREA_NAVBAR,
+ "Search bar is in the nav bar"
+ );
+ await BrowserTestUtils.closeWindow(newWin);
+});
+
+add_task(async function test_menu_shown() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ SearchBar: "unified",
+ },
+ });
+ let newWin = await BrowserTestUtils.openNewBrowserWindow();
+ let placement = CustomizableUI.getPlacementOfWidget("search-container");
+ is(placement, null, "Search bar has no placement");
+ await BrowserTestUtils.closeWindow(newWin);
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_set_homepage.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_set_homepage.js
new file mode 100644
index 0000000000..0c586fc45f
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_set_homepage.js
@@ -0,0 +1,115 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+registerCleanupFunction(function restore_pref_values() {
+ // These two prefs are set as user prefs in case the "Locked"
+ // option from this policy was not used. In this case, it won't
+ // be tracked nor restored by the PoliciesPrefTracker.
+ Services.prefs.clearUserPref("browser.startup.homepage");
+});
+
+add_task(async function homepage_test_simple() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Homepage: {
+ URL: "http://example1.com/",
+ },
+ },
+ });
+ await check_homepage({ expectedURL: "http://example1.com/" });
+});
+
+add_task(async function homepage_test_repeat_same_policy_value() {
+ // Simulate homepage change after policy applied
+ Services.prefs.setStringPref(
+ "browser.startup.homepage",
+ "http://example2.com/"
+ );
+ Services.prefs.setIntPref("browser.startup.page", 3);
+
+ // Policy should have no effect. Homepage has not been locked and policy value
+ // has not changed. We should be respecting the homepage that the user gave.
+ await setupPolicyEngineWithJson({
+ policies: {
+ Homepage: {
+ URL: "http://example1.com/",
+ },
+ },
+ });
+ await check_homepage({
+ expectedURL: "http://example2.com/",
+ expectedPageVal: 3,
+ });
+ Services.prefs.clearUserPref("browser.startup.page");
+ Services.prefs.clearUserPref("browser.startup.homepage");
+});
+
+add_task(async function homepage_test_empty_additional() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Homepage: {
+ URL: "http://example1.com/",
+ Additional: [],
+ },
+ },
+ });
+ await check_homepage({ expectedURL: "http://example1.com/" });
+});
+
+add_task(async function homepage_test_single_additional() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Homepage: {
+ URL: "http://example1.com/",
+ Additional: ["http://example2.com/"],
+ },
+ },
+ });
+ await check_homepage({
+ expectedURL: "http://example1.com/|http://example2.com/",
+ });
+});
+
+add_task(async function homepage_test_multiple_additional() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Homepage: {
+ URL: "http://example1.com/",
+ Additional: ["http://example2.com/", "http://example3.com/"],
+ },
+ },
+ });
+ await check_homepage({
+ expectedURL:
+ "http://example1.com/|http://example2.com/|http://example3.com/",
+ });
+});
+
+add_task(async function homepage_test_locked() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Homepage: {
+ URL: "http://example4.com/",
+ Additional: ["http://example5.com/", "http://example6.com/"],
+ Locked: true,
+ },
+ },
+ });
+ await check_homepage({
+ expectedURL:
+ "http://example4.com/|http://example5.com/|http://example6.com/",
+ locked: true,
+ });
+});
+
+add_task(async function homepage_test_anchor_link() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Homepage: {
+ URL: "http://example1.com/#test",
+ },
+ },
+ });
+ await check_homepage({ expectedURL: "http://example1.com/#test" });
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_set_startpage.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_set_startpage.js
new file mode 100644
index 0000000000..bc28cdd51a
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_set_startpage.js
@@ -0,0 +1,68 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+add_setup(async function () {
+ // browser.startup.page is set by unittest-required/user.js,
+ // but we need the default value
+ await SpecialPowers.pushPrefEnv({
+ clear: [["browser.startup.page"]],
+ });
+});
+
+add_task(async function homepage_test_startpage_homepage() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Homepage: {
+ URL: "http://example1.com/#test",
+ StartPage: "homepage",
+ },
+ },
+ });
+ await check_homepage({
+ expectedURL: "http://example1.com/#test",
+ expectedPageVal: 1,
+ });
+});
+
+add_task(async function homepage_test_startpage_homepage_locked() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Homepage: {
+ URL: "http://example1.com/#test",
+ StartPage: "homepage-locked",
+ Locked: true,
+ },
+ },
+ });
+ await check_homepage({
+ expectedURL: "http://example1.com/#test",
+ expectedPageVal: 1,
+ locked: true,
+ });
+});
+
+add_task(async function homepage_test_startpage_none() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Homepage: {
+ StartPage: "none",
+ },
+ },
+ });
+ await check_homepage({
+ expectedURL: "chrome://browser/content/blanktab.html",
+ expectedPageVal: 1,
+ });
+});
+
+add_task(async function homepage_test_startpage_restore() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ Homepage: {
+ StartPage: "previous-session",
+ },
+ },
+ });
+ await check_homepage({ expectedPageVal: 3 });
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_support_menu.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_support_menu.js
new file mode 100644
index 0000000000..d0a833484a
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_support_menu.js
@@ -0,0 +1,68 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+add_setup(async function () {
+ await setupPolicyEngineWithJson({
+ policies: {
+ SupportMenu: {
+ Title: "Title",
+ URL: "https://example.com/",
+ AccessKey: "T",
+ },
+ },
+ });
+});
+
+add_task(async function test_help_menu() {
+ is(
+ Services.policies.getSupportMenu().URL.href,
+ "https://example.com/",
+ "The policy should have the correct URL."
+ );
+ buildHelpMenu();
+ let supportMenu = document.getElementById("helpPolicySupport");
+ is(supportMenu.hidden, false, "The policy menu should be visible.");
+ is(
+ supportMenu.getAttribute("label"),
+ "Title",
+ "The policy menu should have the correct title."
+ );
+ is(
+ supportMenu.getAttribute("accesskey"),
+ "T",
+ "The policy menu should have the correct access key."
+ );
+});
+
+add_task(async function test_help_menu_app_menu() {
+ is(
+ Services.policies.getSupportMenu().URL.href,
+ "https://example.com/",
+ "The policy should have the correct URL."
+ );
+ let menuButton = document.getElementById("PanelUI-menu-button");
+ menuButton.click();
+ await BrowserTestUtils.waitForEvent(window.PanelUI.mainView, "ViewShown");
+
+ let helpButtonId = "appMenu-help-button2";
+ document.getElementById(helpButtonId).click();
+ await BrowserTestUtils.waitForEvent(
+ document.getElementById("PanelUI-helpView"),
+ "ViewShown"
+ );
+
+ let supportMenu = document.getElementById("appMenu_helpPolicySupport");
+ is(supportMenu.hidden, false, "The policy menu should be visible.");
+ is(
+ supportMenu.getAttribute("label"),
+ "Title",
+ "The policy menu should have the correct title."
+ );
+ is(
+ supportMenu.getAttribute("accesskey"),
+ "T",
+ "The policy menu should have the correct access key."
+ );
+ window.PanelUI.hide();
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_usermessaging.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_usermessaging.js
new file mode 100644
index 0000000000..d8a3381779
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_usermessaging.js
@@ -0,0 +1,21 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_notice_in_aboutprefences() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ UserMessaging: {
+ MoreFromMozilla: false,
+ },
+ },
+ });
+
+ await BrowserTestUtils.withNewTab("about:preferences", async browser => {
+ let moreFromMozillaCategory = browser.contentDocument.getElementById(
+ "category-more-from-mozilla"
+ );
+ ok(moreFromMozillaCategory.hidden, "The category is hidden");
+ });
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/browser_policy_websitefilter.js b/browser/components/enterprisepolicies/tests/browser/browser_policy_websitefilter.js
new file mode 100644
index 0000000000..be51e76dce
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_websitefilter.js
@@ -0,0 +1,186 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const SUPPORT_FILES_PATH =
+ "http://mochi.test:8888/browser/browser/components/enterprisepolicies/tests/browser/";
+const BLOCKED_PAGE = "policy_websitefilter_block.html";
+const EXCEPTION_PAGE = "policy_websitefilter_exception.html";
+const SAVELINKAS_PAGE = "policy_websitefilter_savelink.html";
+
+async function clearWebsiteFilter() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ WebsiteFilter: {
+ Block: [],
+ Exceptions: [],
+ },
+ },
+ });
+}
+
+add_task(async function test_http() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ WebsiteFilter: {
+ Block: ["*://mochi.test/*policy_websitefilter_*"],
+ Exceptions: ["*://mochi.test/*_websitefilter_exception*"],
+ },
+ },
+ });
+
+ await checkBlockedPage(SUPPORT_FILES_PATH + BLOCKED_PAGE, true);
+ await checkBlockedPage(
+ "view-source:" + SUPPORT_FILES_PATH + BLOCKED_PAGE,
+ true
+ );
+ await checkBlockedPage(
+ "about:reader?url=" + SUPPORT_FILES_PATH + BLOCKED_PAGE,
+ true
+ );
+ await checkBlockedPage(
+ "about:READER?url=" + SUPPORT_FILES_PATH + BLOCKED_PAGE,
+ true
+ );
+ await checkBlockedPage(SUPPORT_FILES_PATH + EXCEPTION_PAGE, false);
+
+ await checkBlockedPage(SUPPORT_FILES_PATH + "301.sjs", true);
+
+ await checkBlockedPage(SUPPORT_FILES_PATH + "302.sjs", true);
+ await clearWebsiteFilter();
+});
+
+add_task(async function test_http_mixed_case() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ WebsiteFilter: {
+ Block: ["*://mochi.test/*policy_websitefilter_*"],
+ Exceptions: ["*://mochi.test/*_websitefilter_exception*"],
+ },
+ },
+ });
+
+ await checkBlockedPage(SUPPORT_FILES_PATH + BLOCKED_PAGE.toUpperCase(), true);
+ await checkBlockedPage(
+ SUPPORT_FILES_PATH + EXCEPTION_PAGE.toUpperCase(),
+ false
+ );
+ await clearWebsiteFilter();
+});
+
+add_task(async function test_file() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ WebsiteFilter: {
+ Block: ["file:///*"],
+ },
+ },
+ });
+
+ await checkBlockedPage("file:///this_should_be_blocked", true);
+ await clearWebsiteFilter();
+});
+
+add_task(async function test_savelink() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ WebsiteFilter: {
+ Block: ["*://mochi.test/*policy_websitefilter_block*"],
+ },
+ },
+ });
+
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ SUPPORT_FILES_PATH + SAVELINKAS_PAGE
+ );
+
+ let contextMenu = document.getElementById("contentAreaContextMenu");
+ let promiseContextMenuOpen = BrowserTestUtils.waitForEvent(
+ contextMenu,
+ "popupshown"
+ );
+ await BrowserTestUtils.synthesizeMouse(
+ "#savelink_blocked",
+ 0,
+ 0,
+ {
+ type: "contextmenu",
+ button: 2,
+ centered: true,
+ },
+ gBrowser.selectedBrowser
+ );
+ await promiseContextMenuOpen;
+
+ let saveLink = document.getElementById("context-savelink");
+ is(saveLink.disabled, true, "Save Link As should be disabled");
+
+ let promiseContextMenuHidden = BrowserTestUtils.waitForEvent(
+ contextMenu,
+ "popuphidden"
+ );
+ contextMenu.hidePopup();
+ await promiseContextMenuHidden;
+
+ promiseContextMenuOpen = BrowserTestUtils.waitForEvent(
+ contextMenu,
+ "popupshown"
+ );
+ await BrowserTestUtils.synthesizeMouse(
+ "#savelink_notblocked",
+ 0,
+ 0,
+ {
+ type: "contextmenu",
+ button: 2,
+ centered: true,
+ },
+ gBrowser.selectedBrowser
+ );
+ await promiseContextMenuOpen;
+
+ saveLink = document.getElementById("context-savelink");
+ is(saveLink.disabled, false, "Save Link As should not be disabled");
+
+ promiseContextMenuHidden = BrowserTestUtils.waitForEvent(
+ contextMenu,
+ "popuphidden"
+ );
+ contextMenu.hidePopup();
+ await promiseContextMenuHidden;
+
+ BrowserTestUtils.removeTab(tab);
+ await clearWebsiteFilter();
+});
+
+add_task(async function test_http_json_policy() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ WebsiteFilter: `{
+ "Block": ["*://mochi.test/*policy_websitefilter_*"],
+ "Exceptions": ["*://mochi.test/*_websitefilter_exception*"]
+ }`,
+ },
+ });
+
+ await checkBlockedPage(SUPPORT_FILES_PATH + BLOCKED_PAGE, true);
+ await checkBlockedPage(
+ "view-source:" + SUPPORT_FILES_PATH + BLOCKED_PAGE,
+ true
+ );
+ await checkBlockedPage(
+ "about:reader?url=" + SUPPORT_FILES_PATH + BLOCKED_PAGE,
+ true
+ );
+ await checkBlockedPage(
+ "about:READER?url=" + SUPPORT_FILES_PATH + BLOCKED_PAGE,
+ true
+ );
+ await checkBlockedPage(SUPPORT_FILES_PATH + EXCEPTION_PAGE, false);
+
+ await checkBlockedPage(SUPPORT_FILES_PATH + "301.sjs", true);
+
+ await checkBlockedPage(SUPPORT_FILES_PATH + "302.sjs", true);
+ await clearWebsiteFilter();
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/disable_app_update/browser.ini b/browser/components/enterprisepolicies/tests/browser/disable_app_update/browser.ini
new file mode 100644
index 0000000000..d311bcf910
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/disable_app_update/browser.ini
@@ -0,0 +1,9 @@
+[DEFAULT]
+prefs =
+ app.update.disabledForTesting=false
+ browser.policies.alternatePath='<test-root>/browser/components/enterprisepolicies/tests/browser/disable_app_update/config_disable_app_update.json'
+support-files =
+ config_disable_app_update.json
+skip-if = os == 'win' && msix # Updater is disabled in MSIX builds
+
+[browser_policy_disable_app_update.js]
diff --git a/browser/components/enterprisepolicies/tests/browser/disable_app_update/browser_policy_disable_app_update.js b/browser/components/enterprisepolicies/tests/browser/disable_app_update/browser_policy_disable_app_update.js
new file mode 100644
index 0000000000..e6ad7ab3c5
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/disable_app_update/browser_policy_disable_app_update.js
@@ -0,0 +1,121 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+ChromeUtils.defineESModuleGetters(this, {
+ UrlbarTestUtils: "resource://testing-common/UrlbarTestUtils.sys.mjs",
+});
+
+var updateService = Cc["@mozilla.org/updates/update-service;1"].getService(
+ Ci.nsIApplicationUpdateService
+);
+
+add_task(async function test_updates_post_policy() {
+ is(
+ Services.policies.isAllowed("appUpdate"),
+ false,
+ "appUpdate should be disabled by policy."
+ );
+
+ is(
+ updateService.canCheckForUpdates,
+ false,
+ "Should not be able to check for updates with DisableAppUpdate enabled."
+ );
+});
+
+add_task(async function test_update_preferences_ui() {
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:preferences"
+ );
+
+ await SpecialPowers.spawn(tab.linkedBrowser, [], async function () {
+ let setting = content.document.getElementById("updateSettingsContainer");
+ is(
+ setting.hidden,
+ true,
+ "Update choices should be disabled when app update is locked by policy"
+ );
+ });
+
+ BrowserTestUtils.removeTab(tab);
+});
+
+add_task(async function test_update_about_ui() {
+ let aboutDialog = await waitForAboutDialog();
+ let panelId = "policyDisabled";
+
+ await BrowserTestUtils.waitForCondition(
+ () => aboutDialog.gAppUpdater?.selectedPanel?.id == panelId,
+ 'Waiting for expected panel ID - expected "' + panelId + '"'
+ );
+ is(
+ aboutDialog.gAppUpdater.selectedPanel.id,
+ panelId,
+ "The About Dialog panel Id should equal " + panelId
+ );
+
+ // Make sure that we still remain on the "disabled by policy" panel after
+ // `AppUpdater.stop()` is called.
+ aboutDialog.gAppUpdater._appUpdater.stop();
+ is(
+ aboutDialog.gAppUpdater.selectedPanel.id,
+ panelId,
+ "The About Dialog panel Id should still equal " + panelId
+ );
+
+ aboutDialog.close();
+});
+
+/**
+ * Waits for the About Dialog to load.
+ *
+ * @return A promise that returns the domWindow for the About Dialog and
+ * resolves when the About Dialog loads.
+ */
+function waitForAboutDialog() {
+ return new Promise(resolve => {
+ var listener = {
+ onOpenWindow: aXULWindow => {
+ Services.wm.removeListener(listener);
+
+ async function aboutDialogOnLoad() {
+ domwindow.removeEventListener("load", aboutDialogOnLoad, true);
+ let chromeURI = "chrome://browser/content/aboutDialog.xhtml";
+ is(
+ domwindow.document.location.href,
+ chromeURI,
+ "About dialog appeared"
+ );
+ resolve(domwindow);
+ }
+
+ var domwindow = aXULWindow.docShell.domWindow;
+ domwindow.addEventListener("load", aboutDialogOnLoad, true);
+ },
+ onCloseWindow: aXULWindow => {},
+ };
+
+ Services.wm.addListener(listener);
+ openAboutDialog();
+ });
+}
+
+add_task(async function test_no_update_intervention() {
+ await BrowserTestUtils.withNewTab("about:blank", async () => {
+ let context = await UrlbarTestUtils.promiseAutocompleteResultPopup({
+ window,
+ value: "update firefox",
+ waitForFocus,
+ fireInputEvent: true,
+ });
+ for (let result of context.results) {
+ Assert.notEqual(result.type, UrlbarUtils.RESULT_TYPE.TIP);
+ }
+ await UrlbarTestUtils.promisePopupClose(window, () =>
+ window.gURLBar.blur()
+ );
+ });
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/disable_app_update/config_disable_app_update.json b/browser/components/enterprisepolicies/tests/browser/disable_app_update/config_disable_app_update.json
new file mode 100644
index 0000000000..f36622021f
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/disable_app_update/config_disable_app_update.json
@@ -0,0 +1,5 @@
+{
+ "policies": {
+ "DisableAppUpdate": true
+ }
+}
diff --git a/browser/components/enterprisepolicies/tests/browser/disable_default_bookmarks/bookmarks_policies.json b/browser/components/enterprisepolicies/tests/browser/disable_default_bookmarks/bookmarks_policies.json
new file mode 100644
index 0000000000..117768efb3
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/disable_default_bookmarks/bookmarks_policies.json
@@ -0,0 +1,5 @@
+{
+ "policies": {
+ "NoDefaultBookmarks": true
+ }
+}
diff --git a/browser/components/enterprisepolicies/tests/browser/disable_default_bookmarks/browser.ini b/browser/components/enterprisepolicies/tests/browser/disable_default_bookmarks/browser.ini
new file mode 100644
index 0000000000..b7469c550e
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/disable_default_bookmarks/browser.ini
@@ -0,0 +1,7 @@
+[DEFAULT]
+prefs =
+ browser.policies.alternatePath='<test-root>/browser/components/enterprisepolicies/tests/browser/disable_default_bookmarks/bookmarks_policies.json'
+support-files =
+ bookmarks_policies.json
+
+[browser_policy_no_default_bookmarks.js]
diff --git a/browser/components/enterprisepolicies/tests/browser/disable_default_bookmarks/browser_policy_no_default_bookmarks.js b/browser/components/enterprisepolicies/tests/browser/disable_default_bookmarks/browser_policy_no_default_bookmarks.js
new file mode 100644
index 0000000000..aecd088ab3
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/disable_default_bookmarks/browser_policy_no_default_bookmarks.js
@@ -0,0 +1,24 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// This test must run in a separate folder because the
+// No Default Bookmarks policy needs to be present on
+// the first run of the profile, and not dinamically loaded
+// like most of the policies tested in the main test folder.
+
+add_task(async function test_no_default_bookmarks() {
+ let firstBookmarkOnToolbar = await PlacesUtils.bookmarks.fetch({
+ parentGuid: PlacesUtils.bookmarks.toolbarGuid,
+ index: 0,
+ });
+
+ let firstBookmarkOnMenu = await PlacesUtils.bookmarks.fetch({
+ parentGuid: PlacesUtils.bookmarks.menuGuid,
+ index: 0,
+ });
+
+ is(firstBookmarkOnToolbar, null, "No bookmarks on toolbar");
+ is(firstBookmarkOnMenu, null, "No bookmarks on menu");
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/disable_developer_tools/browser.ini b/browser/components/enterprisepolicies/tests/browser/disable_developer_tools/browser.ini
new file mode 100644
index 0000000000..3db44612f8
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/disable_developer_tools/browser.ini
@@ -0,0 +1,7 @@
+[DEFAULT]
+prefs =
+ browser.policies.alternatePath='<test-root>/browser/components/enterprisepolicies/tests/browser/disable_developer_tools/config_disable_developer_tools.json'
+support-files =
+ config_disable_developer_tools.json
+
+[browser_policy_disable_developer_tools.js]
diff --git a/browser/components/enterprisepolicies/tests/browser/disable_developer_tools/browser_policy_disable_developer_tools.js b/browser/components/enterprisepolicies/tests/browser/disable_developer_tools/browser_policy_disable_developer_tools.js
new file mode 100644
index 0000000000..f0281f6f46
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/disable_developer_tools/browser_policy_disable_developer_tools.js
@@ -0,0 +1,87 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const { EnterprisePolicyTesting } = ChromeUtils.importESModule(
+ "resource://testing-common/EnterprisePolicyTesting.sys.mjs"
+);
+var updateService = Cc["@mozilla.org/updates/update-service;1"].getService(
+ Ci.nsIApplicationUpdateService
+);
+
+add_task(async function test_updates_post_policy() {
+ is(
+ Services.policies.isAllowed("devtools"),
+ false,
+ "devtools should be disabled by policy."
+ );
+
+ is(
+ Services.prefs.getBoolPref("devtools.policy.disabled"),
+ true,
+ "devtools dedicated disabled pref is set to true"
+ );
+
+ Services.prefs.setBoolPref("devtools.policy.disabled", false);
+
+ is(
+ Services.prefs.getBoolPref("devtools.policy.disabled"),
+ true,
+ "devtools dedicated disabled pref can not be updated"
+ );
+
+ await testPageBlockedByPolicy("about:devtools-toolbox");
+ await testPageBlockedByPolicy("about:debugging");
+ await testPageBlockedByPolicy("about:profiling");
+
+ let testURL = "data:text/html;charset=utf-8,test";
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ testURL,
+ false
+ );
+
+ let menuButton = document.getElementById("PanelUI-menu-button");
+ menuButton.click();
+ await BrowserTestUtils.waitForEvent(window.PanelUI.mainView, "ViewShown");
+ let moreToolsButtonId = "appMenu-more-button2";
+ document.getElementById(moreToolsButtonId).click();
+ await BrowserTestUtils.waitForEvent(
+ document.getElementById("appmenu-moreTools"),
+ "ViewShown"
+ );
+ is(
+ document.getElementById("appmenu-developer-tools-view").children.length,
+ 2,
+ "The developer tools are properly populated"
+ );
+ window.PanelUI.hide();
+
+ BrowserTestUtils.removeTab(tab);
+});
+
+// Copied from ../head.js. head.js was never intended to be used with tests
+// that use a JSON file versus calling setupPolicyEngineWithJson so I have
+// to copy this function here versus including it.
+async function testPageBlockedByPolicy(page, policyJSON) {
+ if (policyJSON) {
+ await EnterprisePolicyTesting.setupPolicyEngineWithJson(policyJSON);
+ }
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async browser => {
+ BrowserTestUtils.loadURIString(browser, page);
+ await BrowserTestUtils.browserLoaded(browser, false, page, true);
+ await SpecialPowers.spawn(browser, [page], async function (innerPage) {
+ ok(
+ content.document.documentURI.startsWith(
+ "about:neterror?e=blockedByPolicy"
+ ),
+ content.document.documentURI +
+ " should start with about:neterror?e=blockedByPolicy"
+ );
+ });
+ }
+ );
+}
diff --git a/browser/components/enterprisepolicies/tests/browser/disable_developer_tools/config_disable_developer_tools.json b/browser/components/enterprisepolicies/tests/browser/disable_developer_tools/config_disable_developer_tools.json
new file mode 100644
index 0000000000..08c393dec6
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/disable_developer_tools/config_disable_developer_tools.json
@@ -0,0 +1,5 @@
+{
+ "policies": {
+ "DisableDeveloperTools": true
+ }
+}
diff --git a/browser/components/enterprisepolicies/tests/browser/disable_forget_button/browser.ini b/browser/components/enterprisepolicies/tests/browser/disable_forget_button/browser.ini
new file mode 100644
index 0000000000..689f54987e
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/disable_forget_button/browser.ini
@@ -0,0 +1,7 @@
+[DEFAULT]
+prefs =
+ browser.policies.alternatePath='<test-root>/browser/components/enterprisepolicies/tests/browser/disable_forget_button/forget_button.json'
+support-files =
+ forget_button.json
+
+[browser_policy_disable_forgetbutton.js]
diff --git a/browser/components/enterprisepolicies/tests/browser/disable_forget_button/browser_policy_disable_forgetbutton.js b/browser/components/enterprisepolicies/tests/browser/disable_forget_button/browser_policy_disable_forgetbutton.js
new file mode 100644
index 0000000000..723aad5d75
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/disable_forget_button/browser_policy_disable_forgetbutton.js
@@ -0,0 +1,9 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_policy_disable_forget_button() {
+ let widget = CustomizableUI.getWidget("panic-button");
+ isnot(widget.type, "view", "Forget Button was not created");
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/disable_forget_button/forget_button.json b/browser/components/enterprisepolicies/tests/browser/disable_forget_button/forget_button.json
new file mode 100644
index 0000000000..30baf64df4
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/disable_forget_button/forget_button.json
@@ -0,0 +1,5 @@
+{
+ "policies": {
+ "DisableForgetButton": true
+ }
+}
diff --git a/browser/components/enterprisepolicies/tests/browser/disable_fxscreenshots/browser.ini b/browser/components/enterprisepolicies/tests/browser/disable_fxscreenshots/browser.ini
new file mode 100644
index 0000000000..9c828828c0
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/disable_fxscreenshots/browser.ini
@@ -0,0 +1,8 @@
+[DEFAULT]
+prefs =
+ browser.policies.alternatePath='<test-root>/browser/components/enterprisepolicies/tests/browser/disable_fxscreenshots/config_disable_fxscreenshots.json'
+ extensions.screenshots.disabled=false
+support-files =
+ config_disable_fxscreenshots.json
+
+[browser_policy_disable_fxscreenshots.js]
diff --git a/browser/components/enterprisepolicies/tests/browser/disable_fxscreenshots/browser_policy_disable_fxscreenshots.js b/browser/components/enterprisepolicies/tests/browser/disable_fxscreenshots/browser_policy_disable_fxscreenshots.js
new file mode 100644
index 0000000000..e2b9232aa3
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/disable_fxscreenshots/browser_policy_disable_fxscreenshots.js
@@ -0,0 +1,35 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const PREF_DISABLE_FX_SCREENSHOTS = "extensions.screenshots.disabled";
+
+async function checkScreenshots(shouldBeEnabled) {
+ return BrowserTestUtils.waitForCondition(() => {
+ return (
+ !!PageActions.actionForID("screenshots_mozilla_org") == shouldBeEnabled
+ );
+ }, "Expecting screenshots to be " + shouldBeEnabled);
+}
+
+add_task(async function test_disable_firefox_screenshots() {
+ // Dynamically toggling the PREF_DISABLE_FX_SCREENSHOTS is very finicky, because
+ // that pref is being watched, and it makes the Firefox Screenshots system add-on
+ // to start or stop, causing intermittency.
+ //
+ // Firefox Screenshots is disabled by default on tests (in
+ // testing/profiles/common/user.js). What we do here to test this policy is to enable
+ // it on this specific test folder (through browser.ini) and then we let the policy
+ // engine be responsible for disabling Firefox Screenshots in this case.
+
+ is(
+ Services.prefs.getBoolPref(PREF_DISABLE_FX_SCREENSHOTS),
+ true,
+ "Screenshots pref is disabled"
+ );
+
+ await BrowserTestUtils.withNewTab("data:text/html,Test", async function () {
+ await checkScreenshots(false);
+ });
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/disable_fxscreenshots/config_disable_fxscreenshots.json b/browser/components/enterprisepolicies/tests/browser/disable_fxscreenshots/config_disable_fxscreenshots.json
new file mode 100644
index 0000000000..4caf055394
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/disable_fxscreenshots/config_disable_fxscreenshots.json
@@ -0,0 +1,5 @@
+{
+ "policies": {
+ "DisableFirefoxScreenshots": true
+ }
+}
diff --git a/browser/components/enterprisepolicies/tests/browser/extensionsettings.html b/browser/components/enterprisepolicies/tests/browser/extensionsettings.html
new file mode 100644
index 0000000000..da70ebdf59
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/extensionsettings.html
@@ -0,0 +1,28 @@
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<script type="text/javascript">
+function installTrigger(url) {
+ try {
+ InstallTrigger.install({extension: url});
+ } catch (err) {
+ dump(`Failed to execute InstallTrigger.install: ${err}\n`);
+ }
+ return false;
+}
+</script>
+</head>
+<body>
+<p>
+<a id="policytest" href="policytest_v0.1.xpi">policytest@mozilla.com</a>
+</p>
+<p>
+<a id="policytest_installtrigger" onclick="return installTrigger(this.href);" href="policytest_v0.1.xpi">policytest@mozilla.com</a>
+</p>
+<p>
+<a id="policytest_otherdomain" href="http://example.org:80/browser/browser/components/enterprisepolicies/tests/browser/policytest_v0.1.xpi">policytest@mozilla.com</a>
+</p>
+</body>
+</html>
diff --git a/browser/components/enterprisepolicies/tests/browser/hardware_acceleration/browser.ini b/browser/components/enterprisepolicies/tests/browser/hardware_acceleration/browser.ini
new file mode 100644
index 0000000000..9f7b977e6c
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/hardware_acceleration/browser.ini
@@ -0,0 +1,7 @@
+[DEFAULT]
+prefs =
+ browser.policies.alternatePath='<test-root>/browser/components/enterprisepolicies/tests/browser/hardware_acceleration/disable_hardware_acceleration.json'
+support-files =
+ disable_hardware_acceleration.json
+
+[browser_policy_hardware_acceleration.js]
diff --git a/browser/components/enterprisepolicies/tests/browser/hardware_acceleration/browser_policy_hardware_acceleration.js b/browser/components/enterprisepolicies/tests/browser/hardware_acceleration/browser_policy_hardware_acceleration.js
new file mode 100644
index 0000000000..436bd410d1
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/hardware_acceleration/browser_policy_hardware_acceleration.js
@@ -0,0 +1,13 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_policy_hardware_acceleration() {
+ let winUtils = Services.wm.getMostRecentWindow("").windowUtils;
+ let layerManager = winUtils.layerManagerType;
+ ok(
+ layerManager == "Basic" || layerManager == "WebRender (Software)",
+ "Hardware acceleration disabled"
+ );
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/hardware_acceleration/disable_hardware_acceleration.json b/browser/components/enterprisepolicies/tests/browser/hardware_acceleration/disable_hardware_acceleration.json
new file mode 100644
index 0000000000..acbdc0a3f4
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/hardware_acceleration/disable_hardware_acceleration.json
@@ -0,0 +1,5 @@
+{
+ "policies": {
+ "HardwareAcceleration": false
+ }
+}
diff --git a/browser/components/enterprisepolicies/tests/browser/head.js b/browser/components/enterprisepolicies/tests/browser/head.js
new file mode 100644
index 0000000000..b1b5207f1d
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/head.js
@@ -0,0 +1,253 @@
+/* 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 { EnterprisePolicyTesting, PoliciesPrefTracker } =
+ ChromeUtils.importESModule(
+ "resource://testing-common/EnterprisePolicyTesting.sys.mjs"
+ );
+
+ChromeUtils.defineModuleGetter(
+ this,
+ "HomePage",
+ "resource:///modules/HomePage.jsm"
+);
+
+PoliciesPrefTracker.start();
+
+async function setupPolicyEngineWithJson(json, customSchema) {
+ PoliciesPrefTracker.restoreDefaultValues();
+ if (typeof json != "object") {
+ let filePath = getTestFilePath(json ? json : "non-existing-file.json");
+ return EnterprisePolicyTesting.setupPolicyEngineWithJson(
+ filePath,
+ customSchema
+ );
+ }
+ return EnterprisePolicyTesting.setupPolicyEngineWithJson(json, customSchema);
+}
+
+function checkLockedPref(prefName, prefValue) {
+ EnterprisePolicyTesting.checkPolicyPref(prefName, prefValue, true);
+}
+
+function checkUnlockedPref(prefName, prefValue) {
+ EnterprisePolicyTesting.checkPolicyPref(prefName, prefValue, false);
+}
+
+// Checks that a page was blocked by seeing if it was replaced with about:neterror
+async function checkBlockedPage(url, expectedBlocked) {
+ let newTab = BrowserTestUtils.addTab(gBrowser);
+ gBrowser.selectedTab = newTab;
+
+ if (expectedBlocked) {
+ let promise = BrowserTestUtils.waitForErrorPage(gBrowser.selectedBrowser);
+ BrowserTestUtils.loadURIString(gBrowser, url);
+ await promise;
+ is(
+ newTab.linkedBrowser.documentURI.spec.startsWith(
+ "about:neterror?e=blockedByPolicy"
+ ),
+ true,
+ "Should be blocked by policy"
+ );
+ } else {
+ let promise = BrowserTestUtils.browserStopped(gBrowser, url);
+ BrowserTestUtils.loadURIString(gBrowser, url);
+ await promise;
+
+ is(
+ newTab.linkedBrowser.documentURI.spec,
+ url,
+ "Should not be blocked by policy"
+ );
+ }
+ BrowserTestUtils.removeTab(newTab);
+}
+
+async function check_homepage({
+ expectedURL,
+ expectedPageVal = -1,
+ locked = false,
+}) {
+ if (expectedURL) {
+ is(HomePage.get(), expectedURL, "Homepage URL should match expected");
+ is(
+ Services.prefs.prefIsLocked("browser.startup.homepage"),
+ locked,
+ "Lock status of browser.startup.homepage should match expected"
+ );
+ }
+ if (expectedPageVal != -1) {
+ is(
+ Services.prefs.getIntPref("browser.startup.page", -1),
+ expectedPageVal,
+ "Pref page value should match expected"
+ );
+ is(
+ Services.prefs.prefIsLocked("browser.startup.page"),
+ locked,
+ "Lock status of browser.startup.page should match expected"
+ );
+ }
+
+ // Test that UI is disabled when the Locked property is enabled
+ let tab = await BrowserTestUtils.openNewForegroundTab(
+ gBrowser,
+ "about:preferences"
+ );
+ await ContentTask.spawn(
+ tab.linkedBrowser,
+ { expectedURL, expectedPageVal, locked },
+ // eslint-disable-next-line no-shadow
+ async function ({ expectedURL, expectedPageVal, locked }) {
+ if (expectedPageVal != -1) {
+ // Only check restore checkbox for StartPage
+ let browserRestoreSessionCheckbox = content.document.getElementById(
+ "browserRestoreSession"
+ );
+ is(
+ browserRestoreSessionCheckbox.disabled,
+ locked,
+ "Disabled status of session restore status should match expected"
+ );
+ let shouldBeChecked = expectedPageVal === 3;
+ is(
+ browserRestoreSessionCheckbox.checked,
+ shouldBeChecked,
+ "Session restore status checkbox should be: " +
+ (shouldBeChecked ? "checked" : "unchecked")
+ );
+ }
+
+ if (!expectedURL) {
+ // If only StartPage was changed, no need to check these
+ return;
+ }
+ await content.gotoPref("paneHome");
+
+ let homepageTextbox = content.document.getElementById("homePageUrl");
+ // Unfortunately this test does not work because the new UI does not fill
+ // default values into the URL box at the moment.
+ // is(homepageTextbox.value, expectedURL,
+ // "Homepage URL should match expected");
+
+ // Wait for rendering to be finished
+ await ContentTaskUtils.waitForCondition(
+ () =>
+ content.document.getElementById("useCurrentBtn").disabled === locked
+ );
+
+ is(
+ homepageTextbox.disabled,
+ locked,
+ "Homepage URL text box disabled status should match expected"
+ );
+ is(
+ content.document.getElementById("homeMode").disabled,
+ locked,
+ "Home mode drop down disabled status should match expected"
+ );
+ is(
+ content.document.getElementById("useCurrentBtn").disabled,
+ locked,
+ '"Use current page" button disabled status should match expected'
+ );
+ is(
+ content.document.getElementById("useBookmarkBtn").disabled,
+ locked,
+ '"Use bookmark" button disabled status should match expected'
+ );
+ is(
+ content.document.getElementById("restoreDefaultHomePageBtn").disabled,
+ locked,
+ '"Restore defaults" button disabled status should match expected'
+ );
+ }
+ );
+ await BrowserTestUtils.removeTab(tab);
+}
+
+add_setup(async function policies_headjs_startWithCleanSlate() {
+ if (Services.policies.status != Ci.nsIEnterprisePolicies.INACTIVE) {
+ await setupPolicyEngineWithJson("");
+ }
+ is(
+ Services.policies.status,
+ Ci.nsIEnterprisePolicies.INACTIVE,
+ "Engine is inactive at the start of the test"
+ );
+});
+
+registerCleanupFunction(async function policies_headjs_finishWithCleanSlate() {
+ if (Services.policies.status != Ci.nsIEnterprisePolicies.INACTIVE) {
+ await setupPolicyEngineWithJson("");
+ }
+ is(
+ Services.policies.status,
+ Ci.nsIEnterprisePolicies.INACTIVE,
+ "Engine is inactive at the end of the test"
+ );
+
+ EnterprisePolicyTesting.resetRunOnceState();
+ PoliciesPrefTracker.stop();
+});
+
+function waitForAddonInstall(addonId) {
+ return new Promise(resolve => {
+ let listener = {
+ onInstallEnded(install, addon) {
+ if (addon.id == addonId) {
+ AddonManager.removeInstallListener(listener);
+ resolve();
+ }
+ },
+ onDownloadFailed() {
+ AddonManager.removeInstallListener(listener);
+ resolve();
+ },
+ onInstallFailed() {
+ AddonManager.removeInstallListener(listener);
+ resolve();
+ },
+ };
+ AddonManager.addInstallListener(listener);
+ });
+}
+
+function waitForAddonUninstall(addonId) {
+ return new Promise(resolve => {
+ let listener = {};
+ listener.onUninstalled = addon => {
+ if (addon.id == addonId) {
+ AddonManager.removeAddonListener(listener);
+ resolve();
+ }
+ };
+ AddonManager.addAddonListener(listener);
+ });
+}
+
+async function testPageBlockedByPolicy(page, policyJSON) {
+ if (policyJSON) {
+ await EnterprisePolicyTesting.setupPolicyEngineWithJson(policyJSON);
+ }
+ await BrowserTestUtils.withNewTab(
+ { gBrowser, url: "about:blank" },
+ async browser => {
+ BrowserTestUtils.loadURIString(browser, page);
+ await BrowserTestUtils.browserLoaded(browser, false, page, true);
+ await SpecialPowers.spawn(browser, [page], async function (innerPage) {
+ ok(
+ content.document.documentURI.startsWith(
+ "about:neterror?e=blockedByPolicy"
+ ),
+ content.document.documentURI +
+ " should start with about:neterror?e=blockedByPolicy"
+ );
+ });
+ }
+ );
+}
diff --git a/browser/components/enterprisepolicies/tests/browser/homepage_button/browser.ini b/browser/components/enterprisepolicies/tests/browser/homepage_button/browser.ini
new file mode 100644
index 0000000000..d2b15850a3
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/homepage_button/browser.ini
@@ -0,0 +1,7 @@
+[DEFAULT]
+prefs =
+ browser.policies.alternatePath='<test-root>/browser/components/enterprisepolicies/tests/browser/homepage_button/homepage_policies.json'
+support-files =
+ homepage_policies.json
+
+[browser_show_home_button_with_homepage_policy.js]
diff --git a/browser/components/enterprisepolicies/tests/browser/homepage_button/browser_show_home_button_with_homepage_policy.js b/browser/components/enterprisepolicies/tests/browser/homepage_button/browser_show_home_button_with_homepage_policy.js
new file mode 100644
index 0000000000..c1eafb0a52
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/homepage_button/browser_show_home_button_with_homepage_policy.js
@@ -0,0 +1,9 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_homepage_button_with_homepage() {
+ let homeButton = window.document.getElementById("home-button");
+ isnot(homeButton, null, "The home button should be visible");
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/homepage_button/homepage_policies.json b/browser/components/enterprisepolicies/tests/browser/homepage_button/homepage_policies.json
new file mode 100644
index 0000000000..960e68348e
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/homepage_button/homepage_policies.json
@@ -0,0 +1,7 @@
+{
+ "policies": {
+ "Homepage": {
+ "URL": "http://example1.com/"
+ }
+ }
+}
diff --git a/browser/components/enterprisepolicies/tests/browser/managedbookmarks/browser.ini b/browser/components/enterprisepolicies/tests/browser/managedbookmarks/browser.ini
new file mode 100644
index 0000000000..7b6dff29ce
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/managedbookmarks/browser.ini
@@ -0,0 +1,8 @@
+[DEFAULT]
+prefs =
+ browser.policies.alternatePath='<test-root>/browser/components/enterprisepolicies/tests/browser/managedbookmarks/managedbookmarks.json'
+support-files =
+ managedbookmarks.json
+
+skip-if = (os == "linux") # Popup timeout issue - see Bug 1742167
+[browser_policy_managedbookmarks.js]
diff --git a/browser/components/enterprisepolicies/tests/browser/managedbookmarks/browser_policy_managedbookmarks.js b/browser/components/enterprisepolicies/tests/browser/managedbookmarks/browser_policy_managedbookmarks.js
new file mode 100644
index 0000000000..494f49978c
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/managedbookmarks/browser_policy_managedbookmarks.js
@@ -0,0 +1,210 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_policy_managedbookmarks() {
+ let managedBookmarksMenu =
+ window.document.getElementById("managed-bookmarks");
+
+ is(
+ managedBookmarksMenu.hidden,
+ false,
+ "Managed bookmarks button should be visible."
+ );
+ is(
+ managedBookmarksMenu.label,
+ "Folder 1",
+ "Managed bookmarks buttons should have correct label"
+ );
+
+ let popupShownPromise = BrowserTestUtils.waitForEvent(
+ managedBookmarksMenu.menupopup,
+ "popupshown",
+ false
+ );
+ let popupHiddenPromise = BrowserTestUtils.waitForEvent(
+ managedBookmarksMenu.menupopup,
+ "popuphidden",
+ false
+ );
+ managedBookmarksMenu.open = true;
+ await popupShownPromise;
+
+ is(
+ managedBookmarksMenu.menupopup.children[0].label,
+ "Bookmark 1",
+ "Bookmark should have correct label"
+ );
+ is(
+ managedBookmarksMenu.menupopup.children[0].link,
+ "https://example.com/",
+ "Bookmark should have correct link"
+ );
+ is(
+ managedBookmarksMenu.menupopup.children[1].label,
+ "Bookmark 2",
+ "Bookmark should have correct label"
+ );
+ is(
+ managedBookmarksMenu.menupopup.children[1].link,
+ "https://bookmark2.example.com/",
+ "Bookmark should have correct link"
+ );
+ let subFolder = managedBookmarksMenu.menupopup.children[2];
+ is(subFolder.label, "Folder 2", "Subfolder should have correct label");
+ is(
+ subFolder.menupopup.children[0].label,
+ "Bookmark 3",
+ "Bookmark should have correct label"
+ );
+ is(
+ subFolder.menupopup.children[0].link,
+ "https://bookmark3.example.com/",
+ "Bookmark should have correct link"
+ );
+ is(
+ subFolder.menupopup.children[1].label,
+ "Bookmark 4",
+ "Bookmark should have correct link"
+ );
+ is(
+ subFolder.menupopup.children[1].link,
+ "https://bookmark4.example.com/",
+ "Bookmark should have correct label"
+ );
+ subFolder = managedBookmarksMenu.menupopup.children[3];
+ await TestUtils.waitForCondition(() => {
+ // Need to wait for Fluent to translate
+ return subFolder.label == "Subfolder";
+ }, "Subfolder should have correct label");
+ is(
+ subFolder.menupopup.children[0].label,
+ "Bookmark 5",
+ "Bookmark should have correct label"
+ );
+ is(
+ subFolder.menupopup.children[0].link,
+ "https://bookmark5.example.com/",
+ "Bookmark should have correct link"
+ );
+ is(
+ subFolder.menupopup.children[1].label,
+ "Bookmark 6",
+ "Bookmark should have correct link"
+ );
+ is(
+ subFolder.menupopup.children[1].link,
+ "https://bookmark6.example.com/",
+ "Bookmark should have correct label"
+ );
+
+ managedBookmarksMenu.open = false;
+ await popupHiddenPromise;
+});
+
+add_task(async function test_open_managedbookmark() {
+ let managedBookmarksMenu =
+ window.document.getElementById("managed-bookmarks");
+
+ let promise = BrowserTestUtils.waitForEvent(
+ managedBookmarksMenu.menupopup,
+ "popupshown",
+ false
+ );
+ managedBookmarksMenu.open = true;
+ await promise;
+
+ let context = document.getElementById("placesContext");
+ let openContextMenuPromise = BrowserTestUtils.waitForEvent(
+ context,
+ "popupshown"
+ );
+ EventUtils.synthesizeMouseAtCenter(
+ managedBookmarksMenu.menupopup.children[0],
+ {
+ button: 2,
+ type: "contextmenu",
+ }
+ );
+ await openContextMenuPromise;
+ info("Opened context menu");
+
+ ok(
+ document.getElementById("placesContext_open:newprivatewindow").hidden,
+ "Private Browsing menu should be hidden"
+ );
+ ok(
+ document.getElementById("placesContext_openContainer:tabs").hidden,
+ "Open in Tabs should be hidden"
+ );
+ ok(
+ document.getElementById("placesContext_delete").hidden,
+ "Delete should be hidden"
+ );
+
+ let tabCreatedPromise = BrowserTestUtils.waitForNewTab(gBrowser, null, true);
+
+ let openInNewTabOption = document.getElementById("placesContext_open:newtab");
+ context.activateItem(openInNewTabOption);
+ info("Click open in new tab");
+
+ let lastOpenedTab = await tabCreatedPromise;
+ Assert.equal(
+ lastOpenedTab.linkedBrowser.currentURI.spec,
+ "https://example.com/",
+ "Should have opened the correct URI"
+ );
+ await BrowserTestUtils.removeTab(lastOpenedTab);
+});
+
+add_task(async function test_copy_managedbookmark() {
+ let managedBookmarksMenu =
+ window.document.getElementById("managed-bookmarks");
+
+ let promise = BrowserTestUtils.waitForEvent(
+ managedBookmarksMenu.menupopup,
+ "popupshown",
+ false
+ );
+ managedBookmarksMenu.open = true;
+ await promise;
+
+ let context = document.getElementById("placesContext");
+ let openContextMenuPromise = BrowserTestUtils.waitForEvent(
+ context,
+ "popupshown"
+ );
+ EventUtils.synthesizeMouseAtCenter(
+ managedBookmarksMenu.menupopup.children[0],
+ {
+ button: 2,
+ type: "contextmenu",
+ }
+ );
+ await openContextMenuPromise;
+ info("Opened context menu");
+
+ let copyOption = document.getElementById("placesContext_copy");
+
+ await new Promise((resolve, reject) => {
+ SimpleTest.waitForClipboard(
+ "https://example.com/",
+ () => {
+ context.activateItem(copyOption);
+ },
+ resolve,
+ () => {
+ ok(false, "Clipboard copy failed");
+ reject();
+ }
+ );
+ });
+
+ let popupHidden = BrowserTestUtils.waitForEvent(
+ managedBookmarksMenu.menupopup,
+ "popuphidden"
+ );
+ managedBookmarksMenu.menupopup.hidePopup();
+ await popupHidden;
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/managedbookmarks/managedbookmarks.json b/browser/components/enterprisepolicies/tests/browser/managedbookmarks/managedbookmarks.json
new file mode 100644
index 0000000000..e93d910d87
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/managedbookmarks/managedbookmarks.json
@@ -0,0 +1,44 @@
+{
+ "policies": {
+ "DisablePrivateBrowsing": true,
+ "DisplayBookmarksToolbar": true,
+ "ManagedBookmarks": [
+ {
+ "toplevel_name": "Folder 1"
+ },
+ {
+ "name": "Bookmark 1",
+ "url": "https://example.com/"
+ },
+ {
+ "name": "Bookmark 2",
+ "url": "https://bookmark2.example.com/"
+ },
+ {
+ "children": [
+ {
+ "name": "Bookmark 3",
+ "url": "https://bookmark3.example.com/"
+ },
+ {
+ "name": "Bookmark 4",
+ "url": "https://bookmark4.example.com/"
+ }
+ ],
+ "name": "Folder 2"
+ },
+ {
+ "children": [
+ {
+ "name": "Bookmark 5",
+ "url": "https://bookmark5.example.com/"
+ },
+ {
+ "name": "Bookmark 6",
+ "url": "https://bookmark6.example.com/"
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/browser/components/enterprisepolicies/tests/browser/opensearch.html b/browser/components/enterprisepolicies/tests/browser/opensearch.html
new file mode 100644
index 0000000000..b3f12d6bd4
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/opensearch.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<link rel="search" type="application/opensearchdescription+xml" title="newEngine" href="http://mochi.test:8888/browser/browser/components/enterprisepolicies/tests/browser/opensearchEngine.xml">
+</head>
+<body></body>
+</html>
diff --git a/browser/components/enterprisepolicies/tests/browser/opensearchEngine.xml b/browser/components/enterprisepolicies/tests/browser/opensearchEngine.xml
new file mode 100644
index 0000000000..21ddc4b9a9
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/opensearchEngine.xml
@@ -0,0 +1,12 @@
+<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"
+ xmlns:moz="http://www.mozilla.org/2006/browser/search/">
+ <ShortName>Foo</ShortName>
+ <Description>Foo Search</Description>
+ <InputEncoding>utf-8</InputEncoding>
+ <Image width="16" height="16">data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGklEQVQoz2NgGB6AnZ1dUlJSXl4eSDIyMhLW4Ovr%2B%2Fr168uXL69Zs4YoG%2BLi4i5dusTExMTGxsbNzd3f37937976%2BnpmZmagbHR09J49e5YvX66kpATVEBYW9ubNm2nTphkbG7e2tp44cQLIuHfvXm5urpaWFlDKysqqu7v73LlzECMYIiIiHj58mJCQoKKicvXq1bS0NKBgW1vbjh074uPjgeqAXE1NzSdPnvDz84M0AEUvXLgAsW379u1z5swBen3jxo2zZ892cHB4%2BvQp0KlAfwI1cHJyghQFBwfv2rULokFXV%2FfixYu7d%2B8GGqGgoMDKyrpu3br9%2B%2FcDuXl5eVA%2FAEWBfoWHAdAYoNuAYQ0XAeoUERFhGDYAAPoUaT2dfWJuAAAAAElFTkSuQmCC</Image>
+ <Url type="text/html" method="GET" template="http://mochi.test:8888/browser/browser/components/search/test/?search">
+ <Param name="test" value="{searchTerms}"/>
+ </Url>
+ <moz:SearchForm>http://mochi.test:8888/browser/browser/components/search/test/</moz:SearchForm>
+ <moz:Alias>fooalias</moz:Alias>
+</OpenSearchDescription>
diff --git a/browser/components/enterprisepolicies/tests/browser/policy_websitefilter_block.html b/browser/components/enterprisepolicies/tests/browser/policy_websitefilter_block.html
new file mode 100644
index 0000000000..dd6596615d
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/policy_websitefilter_block.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title>This page should be blocked</title>
+ </head>
+ <body>
+ This page should not be seen.
+ </body>
+</html>
diff --git a/browser/components/enterprisepolicies/tests/browser/policy_websitefilter_exception.html b/browser/components/enterprisepolicies/tests/browser/policy_websitefilter_exception.html
new file mode 100644
index 0000000000..bf389aac31
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/policy_websitefilter_exception.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title>This page should not be blocked</title>
+ </head>
+ <body>
+ This page should be seen.
+ </body>
+</html>
diff --git a/browser/components/enterprisepolicies/tests/browser/policy_websitefilter_savelink.html b/browser/components/enterprisepolicies/tests/browser/policy_websitefilter_savelink.html
new file mode 100644
index 0000000000..d2ec93eac5
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/policy_websitefilter_savelink.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="UTF-8">
+ <title>Save Link As test</title>
+ </head>
+ <body>
+ <a id="savelink_blocked" href="http://mochi.test:8888/browser/browser/components/enterprisepolicies/tests/browser/policy_websitefilter_block.html">Should not be saveable</a><br/>
+ <a id="savelink_notblocked" href="http://mochi.test:8888/browser/browser/components/enterprisepolicies/tests/browser/policy_websitefilter_no_block.html">Should be saveable</a>
+</body>
+</html>
diff --git a/browser/components/enterprisepolicies/tests/browser/policytest_v0.1.xpi b/browser/components/enterprisepolicies/tests/browser/policytest_v0.1.xpi
new file mode 100644
index 0000000000..ee2a6289ee
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/policytest_v0.1.xpi
Binary files differ
diff --git a/browser/components/enterprisepolicies/tests/browser/policytest_v0.2.xpi b/browser/components/enterprisepolicies/tests/browser/policytest_v0.2.xpi
new file mode 100644
index 0000000000..59d589eba9
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/policytest_v0.2.xpi
Binary files differ
diff --git a/browser/components/enterprisepolicies/tests/browser/show_home_button/browser.ini b/browser/components/enterprisepolicies/tests/browser/show_home_button/browser.ini
new file mode 100644
index 0000000000..3e6114506d
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/show_home_button/browser.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+support-files =
+ ../head.js
+
+[browser_policy_show_home_button.js]
diff --git a/browser/components/enterprisepolicies/tests/browser/show_home_button/browser_policy_show_home_button.js b/browser/components/enterprisepolicies/tests/browser/show_home_button/browser_policy_show_home_button.js
new file mode 100644
index 0000000000..c1d7242dc0
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/show_home_button/browser_policy_show_home_button.js
@@ -0,0 +1,38 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/* import-globals-from ../head.js */
+
+"use strict";
+
+add_task(async function test_home_button_shown_boolean() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ ShowHomeButton: true,
+ },
+ });
+
+ // Since testing will apply the policy after the browser has already started,
+ // we will need to open a new window to actually see the menu bar
+ let newWin = await BrowserTestUtils.openNewBrowserWindow();
+ let homeButton = newWin.document.getElementById("home-button");
+ isnot(homeButton, null, "The home button should be visible");
+
+ await BrowserTestUtils.closeWindow(newWin);
+});
+
+add_task(async function test_home_button_hidden_boolean() {
+ await setupPolicyEngineWithJson({
+ policies: {
+ ShowHomeButton: false,
+ },
+ });
+
+ // Since testing will apply the policy after the browser has already started,
+ // we will need to open a new window to actually see the menu bar
+ let newWin = await BrowserTestUtils.openNewBrowserWindow();
+ let homeButton = newWin.document.getElementById("home-button");
+ is(homeButton, null, "The home button should be gone");
+
+ await BrowserTestUtils.closeWindow(newWin);
+});
diff --git a/browser/components/enterprisepolicies/tests/browser/show_home_button/show_home_button_policies.json b/browser/components/enterprisepolicies/tests/browser/show_home_button/show_home_button_policies.json
new file mode 100644
index 0000000000..960e68348e
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/show_home_button/show_home_button_policies.json
@@ -0,0 +1,7 @@
+{
+ "policies": {
+ "Homepage": {
+ "URL": "http://example1.com/"
+ }
+ }
+}
diff --git a/browser/components/enterprisepolicies/tests/moz.build b/browser/components/enterprisepolicies/tests/moz.build
new file mode 100644
index 0000000000..0795ab1747
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/moz.build
@@ -0,0 +1,20 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+BROWSER_CHROME_MANIFESTS += [
+ "browser/browser.ini",
+ "browser/disable_app_update/browser.ini",
+ "browser/disable_default_bookmarks/browser.ini",
+ "browser/disable_developer_tools/browser.ini",
+ "browser/disable_forget_button/browser.ini",
+ "browser/disable_fxscreenshots/browser.ini",
+ "browser/hardware_acceleration/browser.ini",
+ "browser/homepage_button/browser.ini",
+ "browser/managedbookmarks/browser.ini",
+ "browser/show_home_button/browser.ini",
+]
+
+XPCSHELL_TESTS_MANIFESTS += ["xpcshell/xpcshell.ini"]
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..0680e7ece7
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/head.js
@@ -0,0 +1,145 @@
+/* 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} policy
+ * 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`
+ );
+}
+
+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..be16829867
--- /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.iconURI.spec,
+ 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..44b77ddc63
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_preferences.js
@@ -0,0 +1,246 @@
+/* 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",
+ },
+ },
+ },
+ defaultPrefs: {
+ "browser.policies.test.default.boolean": true,
+ "browser.policies.test.default.string": "string",
+ "browser.policies.test.default.number": 11,
+ },
+ 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..47cd33460c
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/test_simple_pref_policies.js
@@ -0,0 +1,1044 @@
+/* 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 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,
+ Snippets: false,
+ Locked: true,
+ },
+ },
+ lockedPrefs: {
+ "browser.newtabpage.activity-stream.feeds.snippets": false,
+ "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.ini b/browser/components/enterprisepolicies/tests/xpcshell/xpcshell.ini
new file mode 100644
index 0000000000..7902977bd6
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/xpcshell/xpcshell.ini
@@ -0,0 +1,33 @@
+[DEFAULT]
+skip-if = toolkit == 'android' # bug 1730213
+firefox-appdir = browser
+head = head.js
+support-files =
+ policytest_v0.1.xpi
+
+[test_3rdparty.js]
+[test_addon_update.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]
+skip-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]
+[test_appupdatepin.js]