Bug 1429169 - Add enterprise policy to change the global cookie settings r=Felipe,jaws
authorKirk Steuber <ksteuber@mozilla.com>
Mon, 19 Mar 2018 10:30:11 -0700
changeset 411248 13b2fe28f15234e5f811157161d46f86dcdec2a0
parent 411247 fa53e62227a9fec00ad2374cd9ed6e80c27cb082
child 411249 c6ed8787d259125344f06058fee7e012500ee01f
push id101594
push userbtara@mozilla.com
push dateSun, 01 Apr 2018 09:52:39 +0000
treeherdermozilla-inbound@090e8fb2b85b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersFelipe, jaws
bugs1429169
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1429169 - Add enterprise policy to change the global cookie settings r=Felipe,jaws Additionally fixes a minor bug in PoliciesPrefTracker.restoreDefaultValues that causes prefs with falsey values not to be reset MozReview-Commit-ID: 2OG4tHsjTTb
browser/components/enterprisepolicies/Policies.jsm
browser/components/enterprisepolicies/schemas/policies-schema.json
browser/components/enterprisepolicies/tests/EnterprisePolicyTesting.jsm
browser/components/enterprisepolicies/tests/browser/browser.ini
browser/components/enterprisepolicies/tests/browser/browser_policy_cookie_settings.js
--- a/browser/components/enterprisepolicies/Policies.jsm
+++ b/browser/components/enterprisepolicies/Policies.jsm
@@ -114,16 +114,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();
+});