Bug 1429169 - Add enterprise policy to change the global cookie settings
Additionally fixes a minor bug in PoliciesPrefTracker.restoreDefaultValues that causes prefs with falsey values not to be reset
MozReview-Commit-ID: 2OG4tHsjTTb
--- a/browser/components/enterprisepolicies/Policies.jsm
+++ b/browser/components/enterprisepolicies/Policies.jsm
@@ -113,16 +113,58 @@ var Policies = {
if (param.Block) {
const hosts = param.Block.map(uri => uri.host).sort().join("\n");
runOncePerModification("clearCookiesForBlockedHosts", hosts, () => {
for (let blocked of param.Block) {
Services.cookies.removeCookiesWithOriginAttributes("{}", blocked.host);
}
});
}
+
+ if (param.Default !== undefined ||
+ param.AcceptThirdParty !== undefined ||
+ param.Locked) {
+ const ACCEPT_COOKIES = 0;
+ const REJECT_THIRD_PARTY_COOKIES = 1;
+ const REJECT_ALL_COOKIES = 2;
+ const REJECT_UNVISITED_THIRD_PARTY = 3;
+
+ let newCookieBehavior = ACCEPT_COOKIES;
+ if (param.Default !== undefined && !param.Default) {
+ newCookieBehavior = REJECT_ALL_COOKIES;
+ } else if (param.AcceptThirdParty) {
+ if (param.AcceptThirdParty == "none") {
+ newCookieBehavior = REJECT_THIRD_PARTY_COOKIES;
+ } else if (param.AcceptThirdParty == "from-visited") {
+ newCookieBehavior = REJECT_UNVISITED_THIRD_PARTY;
+ }
+ }
+
+ if (param.Locked) {
+ setAndLockPref("network.cookie.cookieBehavior", newCookieBehavior);
+ } else {
+ setDefaultPref("network.cookie.cookieBehavior", newCookieBehavior);
+ }
+ }
+
+ const KEEP_COOKIES_UNTIL_EXPIRATION = 0;
+ const KEEP_COOKIES_UNTIL_END_OF_SESSION = 2;
+
+ if (param.ExpireAtSessionEnd !== undefined || param.Locked) {
+ let newLifetimePolicy = KEEP_COOKIES_UNTIL_EXPIRATION;
+ if (param.ExpireAtSessionEnd) {
+ newLifetimePolicy = KEEP_COOKIES_UNTIL_END_OF_SESSION;
+ }
+
+ if (param.Locked) {
+ setAndLockPref("network.cookie.lifetimePolicy", newLifetimePolicy);
+ } else {
+ setDefaultPref("network.cookie.lifetimePolicy", newLifetimePolicy);
+ }
+ }
}
},
"CreateMasterPassword": {
onBeforeUIStartup(manager, param) {
if (!param) {
manager.disallowFeature("createMasterPassword");
}
--- a/browser/components/enterprisepolicies/schemas/policies-schema.json
+++ b/browser/components/enterprisepolicies/schemas/policies-schema.json
@@ -83,16 +83,33 @@
}
},
"Block": {
"type": "array",
"items": {
"type": "origin"
}
+ },
+
+ "Default": {
+ "type": "boolean"
+ },
+
+ "AcceptThirdParty": {
+ "type": "string",
+ "enum": ["all", "none", "from-visited"]
+ },
+
+ "ExpireAtSessionEnd": {
+ "type": "boolean"
+ },
+
+ "Locked": {
+ "type": "boolean"
}
}
},
"CreateMasterPassword": {
"description": "If false, removes access to create a master password.",
"first_available": "60.0",
--- a/browser/components/enterprisepolicies/tests/EnterprisePolicyTesting.jsm
+++ b/browser/components/enterprisepolicies/tests/EnterprisePolicyTesting.jsm
@@ -130,20 +130,20 @@ var PoliciesPrefTracker = {
let defaults = new Preferences({defaultBranch: true});
for (let [prefName, stored] of this._originalValues) {
// If a pref was used through setDefaultPref instead
// of setAndLockPref, it wasn't locked, but calling
// unlockPref is harmless
Preferences.unlock(prefName);
- if (stored.originalDefaultValue) {
+ if (stored.originalDefaultValue !== undefined) {
defaults.set(prefName, stored.originalDefaultValue);
}
- if (stored.originalUserValue) {
+ if (stored.originalUserValue !== undefined) {
Preferences.set(prefName, stored.originalUserValue);
}
}
this._originalValues.clear();
},
};
--- a/browser/components/enterprisepolicies/tests/browser/browser.ini
+++ b/browser/components/enterprisepolicies/tests/browser/browser.ini
@@ -20,16 +20,17 @@ support-files =
[browser_policy_app_update.js]
[browser_policy_block_about_addons.js]
[browser_policy_block_about_config.js]
[browser_policy_block_about_profiles.js]
[browser_policy_block_about_support.js]
[browser_policy_block_set_desktop_background.js]
[browser_policy_bookmarks.js]
[browser_policy_clear_blocked_cookies.js]
+[browser_policy_cookie_settings.js]
[browser_policy_default_browser_check.js]
[browser_policy_disable_feedback_commands.js]
[browser_policy_disable_fxaccounts.js]
[browser_policy_disable_masterpassword.js]
[browser_policy_disable_pdfjs.js]
[browser_policy_disable_pocket.js]
[browser_policy_disable_privatebrowsing.js]
[browser_policy_disable_safemode.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_cookie_settings.js
@@ -0,0 +1,262 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+"use strict";
+
+const { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm", {});
+XPCOMUtils.defineLazyServiceGetter(Services, "cookies",
+ "@mozilla.org/cookieService;1",
+ "nsICookieService");
+XPCOMUtils.defineLazyServiceGetter(Services, "cookiemgr",
+ "@mozilla.org/cookiemanager;1",
+ "nsICookieManager");
+
+function restore_prefs() {
+ Services.prefs.clearUserPref("network.cookie.cookieBehavior");
+ Services.prefs.clearUserPref("network.cookie.lifetimePolicy");
+}
+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", "shutdown-persist");
+ });
+ 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,
+ cookiesExpireAfterSession,
+ cookieSettingsLocked
+ }) {
+ let firstPartyURI = NetUtil.newURI("http://example.com/");
+ let thirdPartyURI = NetUtil.newURI("http://example.org/");
+ let channel = NetUtil.newChannel({uri: firstPartyURI,
+ loadUsingSystemPrincipal: true});
+ channel.QueryInterface(Ci.nsIHttpChannelInternal).forceAllowThirdPartyCookie = true;
+ Services.cookies.removeAll();
+ Services.cookies.setCookieString(firstPartyURI, null, "key=value", channel);
+ Services.cookies.setCookieString(thirdPartyURI, null, "key=value", channel);
+
+ let expectedFirstPartyCookies = 1;
+ let expectedThirdPartyCookies = 1;
+ if (!cookiesEnabled) {
+ expectedFirstPartyCookies = 0;
+ }
+ if (!cookiesEnabled || !thirdPartyCookiesEnabled) {
+ expectedThirdPartyCookies = 0;
+ }
+ is(Services.cookiemgr.countCookiesFromHost(firstPartyURI.host),
+ expectedFirstPartyCookies,
+ "Number of first-party cookies should match expected");
+ is(Services.cookiemgr.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.setCookieString(firstPartyURI, null, "key=value; max-age=1000", channel);
+
+ await fake_profile_change();
+
+ // Now check if the cookie persisted or not
+ let expectedCookieCount = 1;
+ if (cookiesExpireAfterSession || !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"), cookieSettingsLocked,
+ "Cookie behavior pref lock status should be what is expected");
+ is(Services.prefs.prefIsLocked("network.cookie.lifetimePolicy"), cookieSettingsLocked,
+ "Cookie lifetime pref lock status should be what is expected");
+}
+
+add_task(async function test_initial_state() {
+ await test_cookie_settings({
+ cookiesEnabled: true,
+ thirdPartyCookiesEnabled: true,
+ cookiesExpireAfterSession: false,
+ cookieSettingsLocked: false
+ });
+ restore_prefs();
+});
+
+add_task(async function test_undefined_unlocked() {
+ Services.prefs.setIntPref("network.cookie.cookieBehavior", 3);
+ Services.prefs.setIntPref("network.cookie.lifetimePolicy", 2);
+ await setupPolicyEngineWithJson({
+ "policies": {
+ "Cookies": {
+ }
+ }
+ });
+ is(Services.prefs.getIntPref("network.cookie.cookieBehavior", undefined), 3,
+ "An empty cookie policy should not have changed the cookieBehavior preference");
+ is(Services.prefs.getIntPref("network.cookie.lifetimePolicy", undefined), 2,
+ "An empty cookie policy should not have changed the lifetimePolicy preference");
+ restore_prefs();
+});
+
+add_task(async function test_disabled() {
+ await setupPolicyEngineWithJson({
+ "policies": {
+ "Cookies": {
+ "Default": false
+ }
+ }
+ });
+
+ await test_cookie_settings({
+ cookiesEnabled: false,
+ thirdPartyCookiesEnabled: true,
+ cookiesExpireAfterSession: false,
+ cookieSettingsLocked: false
+ });
+ restore_prefs();
+});
+
+add_task(async function test_third_party_disabled() {
+ await setupPolicyEngineWithJson({
+ "policies": {
+ "Cookies": {
+ "AcceptThirdParty": "none"
+ }
+ }
+ });
+
+ await test_cookie_settings({
+ cookiesEnabled: true,
+ thirdPartyCookiesEnabled: false,
+ cookiesExpireAfterSession: false,
+ cookieSettingsLocked: false
+ });
+ restore_prefs();
+});
+
+add_task(async function test_disabled_and_third_party_disabled() {
+ await setupPolicyEngineWithJson({
+ "policies": {
+ "Cookies": {
+ "Default": false,
+ "AcceptThirdParty": "none"
+ }
+ }
+ });
+
+ await test_cookie_settings({
+ cookiesEnabled: false,
+ thirdPartyCookiesEnabled: false,
+ cookiesExpireAfterSession: false,
+ cookieSettingsLocked: false
+ });
+ restore_prefs();
+});
+
+add_task(async function test_disabled_and_third_party_disabled_locked() {
+ await setupPolicyEngineWithJson({
+ "policies": {
+ "Cookies": {
+ "Default": false,
+ "AcceptThirdParty": "none",
+ "Locked": true
+ }
+ }
+ });
+
+ await test_cookie_settings({
+ cookiesEnabled: false,
+ thirdPartyCookiesEnabled: false,
+ cookiesExpireAfterSession: false,
+ cookieSettingsLocked: true
+ });
+ restore_prefs();
+});
+
+add_task(async function test_undefined_locked() {
+ await setupPolicyEngineWithJson({
+ "policies": {
+ "Cookies": {
+ "Locked": true
+ }
+ }
+ });
+
+ await test_cookie_settings({
+ cookiesEnabled: true,
+ thirdPartyCookiesEnabled: true,
+ cookiesExpireAfterSession: false,
+ cookieSettingsLocked: true
+ });
+ restore_prefs();
+});
+
+add_task(async function test_cookie_expire() {
+ await setupPolicyEngineWithJson({
+ "policies": {
+ "Cookies": {
+ "ExpireAtSessionEnd": true
+ }
+ }
+ });
+
+ await test_cookie_settings({
+ cookiesEnabled: true,
+ thirdPartyCookiesEnabled: true,
+ cookiesExpireAfterSession: true,
+ cookieSettingsLocked: false
+ });
+ restore_prefs();
+});
+
+add_task(async function test_cookie_expire_locked() {
+ await setupPolicyEngineWithJson({
+ "policies": {
+ "Cookies": {
+ "ExpireAtSessionEnd": true,
+ "Locked": true
+ }
+ }
+ });
+
+ await test_cookie_settings({
+ cookiesEnabled: true,
+ thirdPartyCookiesEnabled: true,
+ cookiesExpireAfterSession: true,
+ cookieSettingsLocked: true
+ });
+ restore_prefs();
+});
+
+add_task(async function test_disabled_cookie_expire_locked() {
+ await setupPolicyEngineWithJson({
+ "policies": {
+ "Cookies": {
+ "Default": false,
+ "AcceptThirdParty": "none",
+ "ExpireAtSessionEnd": true,
+ "Locked": true
+ }
+ }
+ });
+
+ await test_cookie_settings({
+ cookiesEnabled: false,
+ thirdPartyCookiesEnabled: false,
+ cookiesExpireAfterSession: true,
+ cookieSettingsLocked: true
+ });
+ restore_prefs();
+});