Bug 818340 - change third party cookie handling to block third party cookies from sites I haven't visited. (r=jdm, r=dolske)
authorJonathan Mayer <jmayer@stanford.edu>
Fri, 22 Feb 2013 08:16:01 -0800
changeset 122662 8679f0f1c2153b06a31122670dcb7d7b2f9f2a42
parent 122661 1861d261f88fc6458995a74799f7ad898a640d21
child 122663 18b38e18b751e0521309a5da960a473e8804e216
push id23423
push usersstamm@mozilla.com
push dateFri, 22 Feb 2013 16:55:38 +0000
treeherdermozilla-inbound@8679f0f1c215 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdm, dolske
bugs818340
milestone22.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 818340 - change third party cookie handling to block third party cookies from sites I haven't visited. (r=jdm, r=dolske)
browser/components/preferences/in-content/privacy.js
browser/components/preferences/in-content/privacy.xul
browser/components/preferences/in-content/tests/browser_privacypane_4.js
browser/components/preferences/in-content/tests/privacypane_tests_perwindow.js
browser/components/preferences/privacy.js
browser/components/preferences/privacy.xul
browser/components/preferences/tests/browser_bug705422.js
browser/components/preferences/tests/browser_permissions.js
browser/components/preferences/tests/browser_privacypane_4.js
browser/components/preferences/tests/privacypane_tests_perwindow.js
browser/locales/en-US/chrome/browser/preferences/privacy.dtd
content/base/test/test_CrossSiteXHR.html
content/base/test/test_bug338583.html
dom/plugins/test/mochitest/test_privatemode_perwindowpb.xul
extensions/cookie/nsCookiePermission.cpp
extensions/cookie/test/test_app_uninstall_cookies.html
extensions/cookie/test/unit/head_cookies.js
extensions/cookie/test/unit/test_bug526789.js
extensions/cookie/test/unit/test_cookies_async_failure.js
extensions/cookie/test/unit/test_cookies_profile_close.js
extensions/cookie/test/unit/test_cookies_read.js
extensions/cookie/test/unit/test_cookies_sync_failure.js
extensions/cookie/test/unit/test_cookies_thirdparty.js
modules/libpref/src/init/all.js
netwerk/cookie/CookieServiceChild.cpp
netwerk/cookie/nsCookieService.cpp
netwerk/cookie/nsCookieService.h
netwerk/cookie/nsICookiePermission.idl
netwerk/cookie/test/unit/test_bug643051.js
netwerk/cookie/test/unit/test_parser_0001.js
netwerk/cookie/test/unit/test_parser_0019.js
netwerk/cookie/test/unit_ipc/test_ipc_parser_0001.js
netwerk/cookie/test/unit_ipc/test_ipc_parser_0019.js
netwerk/test/unit/test_bug248970_cookie.js
netwerk/test/unit/test_bug659569.js
netwerk/test/unit/test_bug667818.js
netwerk/test/unit/test_cookie_header.js
netwerk/test/unit/test_cookiejars.js
netwerk/test/unit/test_private_cookie_changed.js
netwerk/test/unit_ipc/test_bug248970_cookie_wrap.js
netwerk/test/unit_ipc/test_cookie_header_wrap.js
netwerk/test/unit_ipc/test_cookiejars_wrap.js
toolkit/components/downloads/test/unit/test_private_resume.js
toolkit/devtools/webconsole/test/network_requests_iframe.html
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -174,18 +174,18 @@ var gPrivacyPane = {
       // select the remember history option if needed
       let rememberHistoryCheckbox = document.getElementById("rememberHistory");
       if (!rememberHistoryCheckbox.checked)
         rememberHistoryCheckbox.checked = true;
 
       // select the remember forms history option
       document.getElementById("browser.formfill.enable").value = true;
 
-      // select the accept cookies option
-      document.getElementById("network.cookie.cookieBehavior").value = 0;
+      // select the limit cookies option
+      document.getElementById("network.cookie.cookieBehavior").value = 3;
       // select the cookie lifetime policy option
       document.getElementById("network.cookie.lifetimePolicy").value = 0;
 
       // select the clear on close option
       document.getElementById("privacy.sanitize.sanitizeOnShutdown").value = false;
       break;
     case "dontremember":
       if (!pref.value)
@@ -358,74 +358,100 @@ var gPrivacyPane = {
   // COOKIES
 
   /*
    * Preferences:
    *
    * network.cookie.cookieBehavior
    * - determines how the browser should handle cookies:
    *     0   means enable all cookies
-   *     1   means reject third party cookies; see
-   *         netwerk/cookie/src/nsCookieService.cpp for a hairier definition
+   *     1   means reject all third party cookies
    *     2   means disable all cookies
+   *     3   means reject third party cookies unless at least one is already set for the eTLD
+   *         see netwerk/cookie/src/nsCookieService.cpp for details
    * network.cookie.lifetimePolicy
    * - determines how long cookies are stored:
    *     0   means keep cookies until they expire
    *     1   means ask how long to keep each cookie
    *     2   means keep cookies until the browser is closed
    */
 
   /**
    * Reads the network.cookie.cookieBehavior preference value and
    * enables/disables the rest of the cookie UI accordingly, returning true
    * if cookies are enabled.
    */
   readAcceptCookies: function ()
   {
     var pref = document.getElementById("network.cookie.cookieBehavior");
-    var acceptThirdParty = document.getElementById("acceptThirdParty");
+    var acceptThirdPartyLabel = document.getElementById("acceptThirdPartyLabel");
+    var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu");
     var keepUntil = document.getElementById("keepUntil");
     var menu = document.getElementById("keepCookiesUntil");
 
     // enable the rest of the UI for anything other than "disable all cookies"
     var acceptCookies = (pref.value != 2);
 
-    acceptThirdParty.disabled = !acceptCookies;
+    acceptThirdPartyLabel.disabled = acceptThirdPartyMenu.disabled = !acceptCookies;
     keepUntil.disabled = menu.disabled = this._autoStartPrivateBrowsing || !acceptCookies;
-
+    
     return acceptCookies;
   },
 
-  readAcceptThirdPartyCookies: function ()
-  {
-    var pref = document.getElementById("network.cookie.cookieBehavior");
-    return pref.value == 0;
-  },
-
   /**
    * Enables/disables the "keep until" label and menulist in response to the
    * "accept cookies" checkbox being checked or unchecked.
    */
   writeAcceptCookies: function ()
   {
     var accept = document.getElementById("acceptCookies");
-    var acceptThirdParty = document.getElementById("acceptThirdParty");
+    var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu");
 
-    // if we're enabling cookies, automatically check 'accept third party'
+    // if we're enabling cookies, automatically select 'accept third party from visited'
     if (accept.checked)
-      acceptThirdParty.checked = true;
+      acceptThirdPartyMenu.selectedIndex = 1;
 
-    return accept.checked ? (acceptThirdParty.checked ? 0 : 1) : 2;
+    return accept.checked ? 3 : 2;
   },
-
+  
+  /**
+   * Converts between network.cookie.cookieBehavior and the third-party cookie UI
+   */
+  readAcceptThirdPartyCookies: function ()
+  {
+    var pref = document.getElementById("network.cookie.cookieBehavior");
+    switch (pref.value)
+    {
+      case 0:
+        return "always";
+      case 1:
+        return "never";
+      case 2:
+        return "never";
+      case 3:
+        return "visited";
+      default:
+        return undefined;
+    }
+  },
+  
   writeAcceptThirdPartyCookies: function ()
   {
-    var accept = document.getElementById("acceptCookies");
-    var acceptThirdParty = document.getElementById("acceptThirdParty");
-    return accept.checked ? (acceptThirdParty.checked ? 0 : 1) : 2;
+    var accept = document.getElementById("acceptThirdPartyMenu").selectedItem;
+    switch (accept.value)
+    {
+      case "always":
+        return 0;
+      case "visited":
+        return 3;
+      case "never":
+        return 1;
+      default:
+        return undefined;
+    }
   },
 
   /**
    * Displays fine-grained, per-site preferences for cookies.
    */
   showCookieExceptions: function ()
   {
     var bundlePreferences = document.getElementById("bundlePreferences");
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -165,21 +165,29 @@
                       preference="network.cookie.cookieBehavior"
                       accesskey="&acceptCookies.accesskey;"
                       onsyncfrompreference="return gPrivacyPane.readAcceptCookies();"
                       onsynctopreference="return gPrivacyPane.writeAcceptCookies();"/>
             <button id="cookieExceptions" oncommand="gPrivacyPane.showCookieExceptions();"
                     label="&cookieExceptions.label;" accesskey="&cookieExceptions.accesskey;"
                     preference="pref.privacy.disable_button.cookie_exceptions"/>
           </hbox>
-          <checkbox id="acceptThirdParty" label="&acceptThirdParty.label;" class="indent"
-                    preference="network.cookie.cookieBehavior"
-                    accesskey="&acceptThirdParty.accesskey;"
-                    onsyncfrompreference="return gPrivacyPane.readAcceptThirdPartyCookies();"
-                    onsynctopreference="return gPrivacyPane.writeAcceptThirdPartyCookies();"/>
+          <hbox id="acceptThirdPartyRow" class="indent">
+            <label id="acceptThirdPartyLabel" control="acceptThirdPartyMenu"
+                   accesskey="&acceptThirdParty.pre.accesskey;">&acceptThirdParty.pre.label;</label>
+            <menulist id="acceptThirdPartyMenu" preference="network.cookie.cookieBehavior"
+            onsyncfrompreference="return gPrivacyPane.readAcceptThirdPartyCookies();"
+            onsynctopreference="return gPrivacyPane.writeAcceptThirdPartyCookies();">
+              <menupopup>
+                <menuitem label="&acceptThirdParty.always.label;" value="always"/>
+                <menuitem label="&acceptThirdParty.visited.label;" value="visited"/>
+                <menuitem label="&acceptThirdParty.never.label;" value="never"/>
+              </menupopup>
+            </menulist>
+          </hbox>
           <hbox id="keepRow" class="indent">
             <label id="keepUntil"
                    control="keepCookiesUntil"
                    accesskey="&keepUntil.accesskey;">&keepUntil.label;</label>
             <menulist id="keepCookiesUntil"
                       preference="network.cookie.lifetimePolicy">
               <menupopup>
                 <menuitem label="&expire.label;" value="0"/>
--- a/browser/components/preferences/in-content/tests/browser_privacypane_4.js
+++ b/browser/components/preferences/in-content/tests/browser_privacypane_4.js
@@ -10,18 +10,18 @@ function test() {
     let tmpdir = extractJarToTmp(jar);
     rootDir = "file://" + tmpdir.path + '/';
   }
   loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
 
   run_test_subset([
     test_custom_retention("acceptCookies", "remember"),
     test_custom_retention("acceptCookies", "custom"),
-    test_custom_retention("acceptThirdParty", "remember"),
-    test_custom_retention("acceptThirdParty", "custom"),
+    test_custom_retention("acceptThirdPartyMenu", "remember", "always"),
+    test_custom_retention("acceptThirdPartyMenu", "custom", "visited"),
     test_custom_retention("keepCookiesUntil", "remember", 1),
     test_custom_retention("keepCookiesUntil", "custom", 2),
     test_custom_retention("keepCookiesUntil", "custom", 0),
     test_custom_retention("alwaysClear", "remember"),
     test_custom_retention("alwaysClear", "custom"),
     test_historymode_retention("remember", "remember"),
 
     // reset all preferences to their default values once we're done
--- a/browser/components/preferences/in-content/tests/privacypane_tests_perwindow.js
+++ b/browser/components/preferences/in-content/tests/privacypane_tests_perwindow.js
@@ -54,17 +54,18 @@ function test_dependent_elements(win) {
     win.document.getElementById("keepCookiesUntil"),
     win.document.getElementById("alwaysClear"),
   ];
   controls.forEach(function(control) {
     ok(control, "the dependent controls should exist");
   });
   let independents = [
     win.document.getElementById("acceptCookies"),
-    win.document.getElementById("acceptThirdParty"),
+    win.document.getElementById("acceptThirdPartyLabel"),
+    win.document.getElementById("acceptThirdPartyMenu")
   ];
   independents.forEach(function(control) {
     ok(control, "the independent controls should exist");
   });
   let cookieexceptions = win.document.getElementById("cookieExceptions");
   ok(cookieexceptions, "the cookie exceptions button should exist");
   let keepuntil = win.document.getElementById("keepCookiesUntil");
   ok(keepuntil, "the keep cookies until menulist should exist");
@@ -119,17 +120,18 @@ function test_dependent_elements(win) {
 }
 
 function test_dependent_cookie_elements(win) {
   let historymode = win.document.getElementById("historyMode");
   ok(historymode, "history mode menulist should exist");
   let pbautostart = win.document.getElementById("privateBrowsingAutoStart");
   ok(pbautostart, "the private browsing auto-start checkbox should exist");
   let controls = [
-    win.document.getElementById("acceptThirdParty"),
+    win.document.getElementById("acceptThirdPartyLabel"),
+    win.document.getElementById("acceptThirdPartyMenu"),
     win.document.getElementById("keepUntil"),
     win.document.getElementById("keepCookiesUntil"),
   ];
   controls.forEach(function(control) {
     ok(control, "the dependent cookie controls should exist");
   });
   let acceptcookies = win.document.getElementById("acceptCookies");
   ok(acceptcookies, "the accept cookies checkbox should exist");
@@ -205,38 +207,44 @@ function test_dependent_clearonclose_ele
 }
 
 function test_dependent_prefs(win) {
   let historymode = win.document.getElementById("historyMode");
   ok(historymode, "history mode menulist should exist");
   let controls = [
     win.document.getElementById("rememberHistory"),
     win.document.getElementById("rememberForms"),
-    win.document.getElementById("acceptCookies"),
-    win.document.getElementById("acceptThirdParty"),
+    win.document.getElementById("acceptCookies")
   ];
   controls.forEach(function(control) {
     ok(control, "the micro-management controls should exist");
   });
 
+  let thirdPartyCookieMenu = win.document.getElementById("acceptThirdPartyMenu");
+  ok(thirdPartyCookieMenu, "the third-party cookie control should exist");
+
   function expect_checked(checked) {
     controls.forEach(function(control) {
       is(control.checked, checked,
         control.getAttribute("id") + " should " + (checked ? "not " : "") + "be checked");
     });
+
+    is(thirdPartyCookieMenu.value == "always" || thirdPartyCookieMenu.value == "visited", checked, "third-party cookies should "  + (checked ? "not " : "") + "be limited");
   }
 
   // controls should be checked in remember mode
   historymode.value = "remember";
   controlChanged(historymode);
   expect_checked(true);
 
   // even if they're unchecked in custom mode
   historymode.value = "custom";
   controlChanged(historymode);
+  thirdPartyCookieMenu.value = "never";
+  controlChanged(thirdPartyCookieMenu);
   controls.forEach(function(control) {
     control.checked = false;
     controlChanged(control);
   });
   expect_checked(false);
   historymode.value = "remember";
   controlChanged(historymode);
   expect_checked(true);
--- a/browser/components/preferences/privacy.js
+++ b/browser/components/preferences/privacy.js
@@ -177,18 +177,18 @@ var gPrivacyPane = {
       // select the remember history option if needed
       let rememberHistoryCheckbox = document.getElementById("rememberHistory");
       if (!rememberHistoryCheckbox.checked)
         rememberHistoryCheckbox.checked = true;
 
       // select the remember forms history option
       document.getElementById("browser.formfill.enable").value = true;
 
-      // select the accept cookies option
-      document.getElementById("network.cookie.cookieBehavior").value = 0;
+      // select the limit cookies option
+      document.getElementById("network.cookie.cookieBehavior").value = 3;
       // select the cookie lifetime policy option
       document.getElementById("network.cookie.lifetimePolicy").value = 0;
 
       // select the clear on close option
       document.getElementById("privacy.sanitize.sanitizeOnShutdown").value = false;
       break;
     case "dontremember":
       if (!pref.value)
@@ -361,74 +361,100 @@ var gPrivacyPane = {
   // COOKIES
 
   /*
    * Preferences:
    *
    * network.cookie.cookieBehavior
    * - determines how the browser should handle cookies:
    *     0   means enable all cookies
-   *     1   means reject third party cookies; see
-   *         netwerk/cookie/src/nsCookieService.cpp for a hairier definition
+   *     1   means reject all third party cookies
    *     2   means disable all cookies
+   *     3   means reject third party cookies unless at least one is already set for the eTLD
+   *         see netwerk/cookie/src/nsCookieService.cpp for details
    * network.cookie.lifetimePolicy
    * - determines how long cookies are stored:
    *     0   means keep cookies until they expire
    *     1   means ask how long to keep each cookie
    *     2   means keep cookies until the browser is closed
    */
 
   /**
    * Reads the network.cookie.cookieBehavior preference value and
    * enables/disables the rest of the cookie UI accordingly, returning true
    * if cookies are enabled.
    */
   readAcceptCookies: function ()
   {
     var pref = document.getElementById("network.cookie.cookieBehavior");
-    var acceptThirdParty = document.getElementById("acceptThirdParty");
+    var acceptThirdPartyLabel = document.getElementById("acceptThirdPartyLabel");
+    var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu");
     var keepUntil = document.getElementById("keepUntil");
     var menu = document.getElementById("keepCookiesUntil");
 
     // enable the rest of the UI for anything other than "disable all cookies"
     var acceptCookies = (pref.value != 2);
 
-    acceptThirdParty.disabled = !acceptCookies;
+    acceptThirdPartyLabel.disabled = acceptThirdPartyMenu.disabled = !acceptCookies;
     keepUntil.disabled = menu.disabled = this._autoStartPrivateBrowsing || !acceptCookies;
     
     return acceptCookies;
   },
 
-  readAcceptThirdPartyCookies: function ()
-  {
-    var pref = document.getElementById("network.cookie.cookieBehavior");
-    return pref.value == 0;
-  },
-
   /**
    * Enables/disables the "keep until" label and menulist in response to the
    * "accept cookies" checkbox being checked or unchecked.
    */
   writeAcceptCookies: function ()
   {
     var accept = document.getElementById("acceptCookies");
-    var acceptThirdParty = document.getElementById("acceptThirdParty");
+    var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu");
 
-    // if we're enabling cookies, automatically check 'accept third party'
+    // if we're enabling cookies, automatically select 'accept third party from visited'
     if (accept.checked)
-      acceptThirdParty.checked = true;
+      acceptThirdPartyMenu.selectedIndex = 1;
 
-    return accept.checked ? (acceptThirdParty.checked ? 0 : 1) : 2;
+    return accept.checked ? 3 : 2;
   },
-
+  
+  /**
+   * Converts between network.cookie.cookieBehavior and the third-party cookie UI
+   */
+  readAcceptThirdPartyCookies: function ()
+  {
+    var pref = document.getElementById("network.cookie.cookieBehavior");
+    switch (pref.value)
+    {
+      case 0:
+        return "always";
+      case 1:
+        return "never";
+      case 2:
+        return "never";
+      case 3:
+        return "visited";
+      default:
+        return undefined;
+    }
+  },
+  
   writeAcceptThirdPartyCookies: function ()
   {
-    var accept = document.getElementById("acceptCookies");
-    var acceptThirdParty = document.getElementById("acceptThirdParty");
-    return accept.checked ? (acceptThirdParty.checked ? 0 : 1) : 2;
+    var accept = document.getElementById("acceptThirdPartyMenu").selectedItem;
+    switch (accept.value)
+    {
+      case "always":
+        return 0;
+      case "visited":
+        return 3;
+      case "never":
+        return 1;
+      default:
+        return undefined;
+    }
   },
 
   /**
    * Displays fine-grained, per-site preferences for cookies.
    */
   showCookieExceptions: function ()
   {
     var bundlePreferences = document.getElementById("bundlePreferences");
@@ -498,12 +524,12 @@ var gPrivacyPane = {
   /**
    * Enables or disables the "Settings..." button depending
    * on the privacy.sanitize.sanitizeOnShutdown preference value
    */
   _updateSanitizeSettingsButton: function () {
     var settingsButton = document.getElementById("clearDataSettings");
     var sanitizeOnShutdownPref = document.getElementById("privacy.sanitize.sanitizeOnShutdown");
     
-    settingsButton.disabled = !sanitizeOnShutdownPref.value;  	
+    settingsButton.disabled = !sanitizeOnShutdownPref.value;
    }
 
 };
--- a/browser/components/preferences/privacy.xul
+++ b/browser/components/preferences/privacy.xul
@@ -178,22 +178,33 @@
                           preference="network.cookie.cookieBehavior"
                           accesskey="&acceptCookies.accesskey;"
                           onsyncfrompreference="return gPrivacyPane.readAcceptCookies();"
                           onsynctopreference="return gPrivacyPane.writeAcceptCookies();"/>
                 <button id="cookieExceptions" oncommand="gPrivacyPane.showCookieExceptions();"
                         label="&cookieExceptions.label;" accesskey="&cookieExceptions.accesskey;"
                         preference="pref.privacy.disable_button.cookie_exceptions"/>
               </hbox>
-              <checkbox id="acceptThirdParty" label="&acceptThirdParty.label;" class="indent"
-                        preference="network.cookie.cookieBehavior"
-                        accesskey="&acceptThirdParty.accesskey;"
-                        onsyncfrompreference="return gPrivacyPane.readAcceptThirdPartyCookies();"
-                        onsynctopreference="return gPrivacyPane.writeAcceptThirdPartyCookies();"/>
 
+              <hbox id="acceptThirdPartyRow" class="indent">
+                <hbox id="acceptThirdPartyBox" align="center">
+                  <label id="acceptThirdPartyLabel" control="acceptThirdPartyMenu"
+                         accesskey="&acceptThirdParty.pre.accesskey;">&acceptThirdParty.pre.label;</label>
+                  <menulist id="acceptThirdPartyMenu" preference="network.cookie.cookieBehavior"
+                  onsyncfrompreference="return gPrivacyPane.readAcceptThirdPartyCookies();"
+                  onsynctopreference="return gPrivacyPane.writeAcceptThirdPartyCookies();">
+                    <menupopup>
+                      <menuitem label="&acceptThirdParty.always.label;" value="always"/>
+                      <menuitem label="&acceptThirdParty.visited.label;" value="visited"/>
+                      <menuitem label="&acceptThirdParty.never.label;" value="never"/>
+                    </menupopup>
+                  </menulist>
+                </hbox>
+              </hbox>
+              
               <hbox id="keepRow" class="indent">
                 <hbox id="keepBox" align="center">
                   <label id="keepUntil"
                          control="keepCookiesUntil"
                          accesskey="&keepUntil.accesskey;">&keepUntil.label;</label>
                   <menulist id="keepCookiesUntil"
                             preference="network.cookie.lifetimePolicy">
                     <menupopup>
--- a/browser/components/preferences/tests/browser_bug705422.js
+++ b/browser/components/preferences/tests/browser_bug705422.js
@@ -1,13 +1,18 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 function test() {
-    waitForExplicitFinish();
+  waitForExplicitFinish();
+  // Allow all cookies, then actually set up the test
+  SpecialPowers.pushPrefEnv({"set": [["network.cookie.cookieBehavior", 0]]}, initTest);
+}
+
+function initTest() {
     const searchTerm = "example";
     const dummyTerm = "elpmaxe";
 
     var cm =  Components.classes["@mozilla.org/cookiemanager;1"]
                         .getService(Components.interfaces.nsICookieManager);
 
     // delete all cookies (might be left over from other tests)
     cm.removeAll();
--- a/browser/components/preferences/tests/browser_permissions.js
+++ b/browser/components/preferences/tests/browser_permissions.js
@@ -158,16 +158,19 @@ var tests = [
       let menuitem = gBrowser.contentDocument.getElementById(aType + "-" + PERM_ALLOW);
       ok(menuitem.hidden, aType + " allow menuitem hidden for all sites");
     });
 
     runNextTest();
   },
 
   function test_all_sites_permission() {
+    // apply the old default of allowing all cookies
+    Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+  
     // there should be no user-set pref for cookie behavior
     is(Services.prefs.getIntPref("network.cookie.cookieBehavior"), PERM_UNKNOWN,
        "network.cookie.cookieBehavior is expected default");
 
     // the default behavior is to allow cookies
     let cookieMenulist = getPermissionMenulist("cookie");
     is(cookieMenulist.value, PERM_ALLOW,
        "menulist correctly shows that cookies are allowed");
--- a/browser/components/preferences/tests/browser_privacypane_4.js
+++ b/browser/components/preferences/tests/browser_privacypane_4.js
@@ -11,18 +11,18 @@ function test() {
     let tmpdir = extractJarToTmp(jar);
     rootDir = "file://" + tmpdir.path + '/';
   }
   loader.loadSubScript(rootDir + "privacypane_tests_perwindow.js", this);
 
   run_test_subset([
     test_custom_retention("acceptCookies", "remember"),
     test_custom_retention("acceptCookies", "custom"),
-    test_custom_retention("acceptThirdParty", "remember"),
-    test_custom_retention("acceptThirdParty", "custom"),
+    test_custom_retention("acceptThirdPartyMenu", "remember", "always"),
+    test_custom_retention("acceptThirdPartyMenu", "custom", "visited"),
     test_custom_retention("keepCookiesUntil", "remember", 1),
     test_custom_retention("keepCookiesUntil", "custom", 2),
     test_custom_retention("keepCookiesUntil", "custom", 0),
     test_custom_retention("alwaysClear", "remember"),
     test_custom_retention("alwaysClear", "custom"),
     test_historymode_retention("remember", "remember"),
 
     // reset all preferences to their default values once we're done
--- a/browser/components/preferences/tests/privacypane_tests_perwindow.js
+++ b/browser/components/preferences/tests/privacypane_tests_perwindow.js
@@ -64,17 +64,18 @@ function test_dependent_elements(win) {
     win.document.getElementById("keepCookiesUntil"),
     win.document.getElementById("alwaysClear"),
   ];
   controls.forEach(function(control) {
     ok(control, "the dependent controls should exist");
   });
   let independents = [
     win.document.getElementById("acceptCookies"),
-    win.document.getElementById("acceptThirdParty"),
+    win.document.getElementById("acceptThirdPartyLabel"),
+    win.document.getElementById("acceptThirdPartyMenu")
   ];
   independents.forEach(function(control) {
     ok(control, "the independent controls should exist");
   });
   let cookieexceptions = win.document.getElementById("cookieExceptions");
   ok(cookieexceptions, "the cookie exceptions button should exist");
   let keepuntil = win.document.getElementById("keepCookiesUntil");
   ok(keepuntil, "the keep cookies until menulist should exist");
@@ -128,17 +129,18 @@ function test_dependent_elements(win) {
 }
 
 function test_dependent_cookie_elements(win) {
   let historymode = win.document.getElementById("historyMode");
   ok(historymode, "history mode menulist should exist");
   let pbautostart = win.document.getElementById("privateBrowsingAutoStart");
   ok(pbautostart, "the private browsing auto-start checkbox should exist");
   let controls = [
-    win.document.getElementById("acceptThirdParty"),
+    win.document.getElementById("acceptThirdPartyLabel"),
+    win.document.getElementById("acceptThirdPartyMenu"),
     win.document.getElementById("keepUntil"),
     win.document.getElementById("keepCookiesUntil"),
   ];
   controls.forEach(function(control) {
     ok(control, "the dependent cookie controls should exist");
   });
   let acceptcookies = win.document.getElementById("acceptCookies");
   ok(acceptcookies, "the accept cookies checkbox should exist");
@@ -215,37 +217,43 @@ function test_dependent_clearonclose_ele
 
 function test_dependent_prefs(win) {
   let historymode = win.document.getElementById("historyMode");
   ok(historymode, "history mode menulist should exist");
   let controls = [
     win.document.getElementById("rememberHistory"),
     win.document.getElementById("rememberForms"),
     win.document.getElementById("acceptCookies"),
-    win.document.getElementById("acceptThirdParty"),
   ];
   controls.forEach(function(control) {
     ok(control, "the micro-management controls should exist");
   });
+  
+  let thirdPartyCookieMenu = win.document.getElementById("acceptThirdPartyMenu");
+  ok(thirdPartyCookieMenu, "the third-party cookie control should exist");
 
   function expect_checked(checked) {
     controls.forEach(function(control) {
       is(control.checked, checked,
         control.getAttribute("id") + " should " + (checked ? "not " : "") + "be checked");
     });
+
+    is(thirdPartyCookieMenu.value == "always" || thirdPartyCookieMenu.value == "visited", checked, "third-party cookies should "  + (checked ? "not " : "") + "be limited");
   }
 
   // controls should be checked in remember mode
   historymode.value = "remember";
   controlChanged(historymode);
   expect_checked(true);
 
   // even if they're unchecked in custom mode
   historymode.value = "custom";
   controlChanged(historymode);
+  thirdPartyCookieMenu.value = "never";
+  controlChanged(thirdPartyCookieMenu);
   controls.forEach(function(control) {
     control.checked = false;
     controlChanged(control);
   });
   expect_checked(false);
   historymode.value = "remember";
   controlChanged(historymode);
   expect_checked(true);
--- a/browser/locales/en-US/chrome/browser/preferences/privacy.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/privacy.dtd
@@ -22,18 +22,21 @@
 <!ENTITY  locbar.both.label             "History and Bookmarks">
 <!ENTITY  locbar.history.label          "History">
 <!ENTITY  locbar.bookmarks.label        "Bookmarks">
 <!ENTITY  locbar.nothing.label          "Nothing">
 
 <!ENTITY  acceptCookies.label           "Accept cookies from sites">
 <!ENTITY  acceptCookies.accesskey       "A">
 
-<!ENTITY  acceptThirdParty.label        "Accept third-party cookies">
-<!ENTITY  acceptThirdParty.accesskey    "c">
+<!ENTITY  acceptThirdParty.pre.label      "Accept third-party cookies:">
+<!ENTITY  acceptThirdParty.pre.accesskey  "c">
+<!ENTITY  acceptThirdParty.always.label   "Always">
+<!ENTITY  acceptThirdParty.never.label    "Never">
+<!ENTITY  acceptThirdParty.visited.label  "From visited">
 
 <!ENTITY  keepUntil.label               "Keep until:">
 <!ENTITY  keepUntil.accesskey           "K">
 
 <!ENTITY  expire.label                  "they expire">
 <!ENTITY  close.label                   "I close &brandShortName;">
 <!ENTITY  askEachTime.label             "ask me every time">
 
--- a/content/base/test/test_CrossSiteXHR.html
+++ b/content/base/test/test_CrossSiteXHR.html
@@ -1,37 +1,47 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
   <title>Test for Cross Site XMLHttpRequest</title>
   <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>        
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
 </head>
-<body onload="gen.next()">
+<body onload="initTest()">
 <p id="display">
 <iframe id=loader></iframe>
 </p>
 <div id="content" style="display: none">
   
 </div>
 <pre id="test">
 <script class="testbody" type="application/javascript;version=1.8">
 
 const runPreflightTests = 1;
 const runCookieTests = 1;
 const runRedirectTests = 1;
 
-SimpleTest.waitForExplicitFinish();
+var gen;
+
+function initTest() {
+  SimpleTest.waitForExplicitFinish();
+  // Allow all cookies, then do the actual test initialization
+  SpecialPowers.pushPrefEnv({"set": [["network.cookie.cookieBehavior", 0]]}, initTestCallback);
+}
 
-window.addEventListener("message", function(e) {
-  gen.send(e.data);
-}, false);
+function initTestCallback() {
+  window.addEventListener("message", function(e) {
+    gen.send(e.data);
+  }, false);
 
-gen = runTest();
+  gen = runTest();
+  
+  gen.next()
+}
 
 function runTest() {
   var loader = document.getElementById('loader');
   var loaderWindow = loader.contentWindow;
   loader.onload = function () { gen.next() };
 
   // Test preflight-less requests
   basePath = "/tests/content/base/test/file_CrossSiteXHR_server.sjs?"
--- a/content/base/test/test_bug338583.html
+++ b/content/base/test/test_bug338583.html
@@ -590,17 +590,23 @@ https://bugzilla.mozilla.org/show_bug.cg
          gEventSourceObj7.msg_received[2] == "delayed2", "Test 7 failed");
 
       SpecialPowers.setBoolPref("dom.server-events.enabled", oldPrefVal);
       document.getElementById('waitSpan').innerHTML = '';
       setTestHasFinished(test_id);
     }, parseInt(8000*stress_factor));
   }
 
-  function doTest(test_id)
+  function doTest()
+  {
+    // Allow all cookies, then run the actual test
+    SpecialPowers.pushPrefEnv({"set": [["network.cookie.cookieBehavior", 0]]}, doTestCallback);
+  }
+  
+  function doTestCallback()
   {
     oldPrefVal = SpecialPowers.getBoolPref("dom.server-events.enabled");
     SpecialPowers.setBoolPref("dom.server-events.enabled", true);
 
     // we get a good stress_factor by testing 10 setTimeouts and some float
     // arithmetic taking my machine as stress_factor==1 (time=589)
 
     var begin_time = (new Date()).getTime();
--- a/dom/plugins/test/mochitest/test_privatemode_perwindowpb.xul
+++ b/dom/plugins/test/mochitest/test_privatemode_perwindowpb.xul
@@ -15,16 +15,21 @@
 <script class="testbody" type="application/javascript">
 <![CDATA[
 SimpleTest.waitForExplicitFinish();
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 function runTests() {
+  // Allow all cookies, then run the actual tests
+  SpecialPowers.pushPrefEnv({"set": [["network.cookie.cookieBehavior", 0]]}, runTestsCallback);
+}
+
+function runTestsCallback() {
   var pluginElement1 = document.getElementById("plugin1");
   var pluginElement2 = document.getElementById("plugin2");
 
   var state1 = false;
   var state2 = false;
   var exceptionThrown = false;
 
   try {
--- a/extensions/cookie/nsCookiePermission.cpp
+++ b/extensions/cookie/nsCookiePermission.cpp
@@ -211,16 +211,34 @@ nsCookiePermission::CanSetCookie(nsIURI 
 
   case nsICookiePermission::ACCESS_ALLOW_FIRST_PARTY_ONLY:
     mThirdPartyUtil->IsThirdPartyChannel(aChannel, aURI, &isThirdParty);
     // If it's third party, we can't set the cookie
     if (isThirdParty)
       *aResult = false;
     break;
 
+  case nsICookiePermission::ACCESS_LIMIT_THIRD_PARTY:
+    mThirdPartyUtil->IsThirdPartyChannel(aChannel, aURI, &isThirdParty);
+    // If it's third party, check whether cookies are already set
+    if (isThirdParty) {
+      nsresult rv;
+      nsCOMPtr<nsICookieManager2> cookieManager = do_GetService(NS_COOKIEMANAGER_CONTRACTID, &rv);
+      if (NS_FAILED(rv)) {
+        *aResult = false;
+        break;
+      }
+      uint32_t priorCookieCount = 0;
+      nsAutoCString hostFromURI;
+      aURI->GetHost(hostFromURI);
+      cookieManager->CountCookiesFromHost(hostFromURI, &priorCookieCount);
+      *aResult = priorCookieCount != 0;
+    }
+    break;
+
   default:
     // the permission manager has nothing to say about this cookie -
     // so, we apply the default prefs to it.
     NS_ASSERTION(perm == nsIPermissionManager::UNKNOWN_ACTION, "unknown permission");
 
     // now we need to figure out what type of accept policy we're dealing with
     // if we accept cookies normally, just bail and return
     if (mCookiesLifetimePolicy == ACCEPT_NORMALLY) {
--- a/extensions/cookie/test/test_app_uninstall_cookies.html
+++ b/extensions/cookie/test/test_app_uninstall_cookies.html
@@ -147,16 +147,21 @@ function setNextCookie(request, data, co
 
 var previousDryRunValue = null;
 try {
   previousDryRunValue = SpecialPowers.getBoolPref('browser.mozApps.installer.dry_run');
 } catch(e) {
 }
 
 SpecialPowers.setBoolPref('browser.mozApps.installer.dry_run', true);
+
+var previousCookiePrefValue = SpecialPowers.getIntPref('network.cookie.cookieBehavior');
+
+SpecialPowers.setIntPref('network.cookie.cookieBehavior', 0);
+
 permManager.addFromPrincipal(window.document.nodePrincipal, "webapps-manage",
                              Ci.nsIPermissionManager.ALLOW_ACTION);
 
 var gManifestURL = "http://www.example.com/chrome/dom/tests/mochitest/webapps/apps/basic.webapp";
 
 confirmNextInstall();
 
 var gTestAppId = 0;
@@ -190,16 +195,17 @@ function checkCookie() {
       if (app.manifestURL == gManifestURL) {
         navigator.mozApps.mgmt.uninstall(app).onsuccess = function() {
           is(getCookiesCountForApp(gTestAppId), 0, "App should have no cookies");
 
           is(getCookiesCount(), gCurrentCookiesCount,
              "Number of cookies should not have changed");
 
           SpecialPowers.setBoolPref('browser.mozApps.installer.dry_run', previousDryRunValue);
+          SpecialPowers.setIntPref('network.cookie.cookieBehavior', previousCookiePrefValue);
           permManager.removeFromPrincipal(window.document.nodePrincipal, "webapps-manage",
                                        Ci.nsIPermissionManager.ALLOW_ACTION);
 
           httpserver.stop(function() {
             SimpleTest.finish();
           });
 
           return;
--- a/extensions/cookie/test/unit/head_cookies.js
+++ b/extensions/cookie/test/unit/head_cookies.js
@@ -99,16 +99,23 @@ function do_load_profile(generator) {
   // Register an observer for read completion.
   let obs = new _observer(generator, "cookie-db-read");
 
   // Load the profile.
   let service = Services.cookies.QueryInterface(Ci.nsIObserver);
   service.observe(null, "profile-do-change", "");
 }
 
+// Set a single session cookie using http and test the cookie count
+// against 'expected'
+function do_set_single_http_cookie(uri, channel, expected) {
+  Services.cookies.setCookieStringFromHttp(uri, null, null, "foo=bar", null, channel);
+  do_check_eq(Services.cookiemgr.countCookiesFromHost(uri.host), expected);
+}
+
 // Set four cookies; with & without channel, http and non-http; and test
 // the cookie count against 'expected' after each set.
 function do_set_cookies(uri, channel, session, expected) {
   let suffix = session ? "" : "; max-age=1000";
 
   // without channel
   Services.cookies.setCookieString(uri, null, "oh=hai" + suffix, null);
   do_check_eq(Services.cookiemgr.countCookiesFromHost(uri.host), expected[0]);
--- a/extensions/cookie/test/unit/test_bug526789.js
+++ b/extensions/cookie/test/unit/test_bug526789.js
@@ -3,16 +3,19 @@
 
 function run_test() {
   var cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
   var cm = Cc["@mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
   var expiry = (Date.now() + 1000) * 1000;
 
   cm.removeAll();
 
+  // Allow all cookies.
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
   // test that variants of 'baz.com' get normalized appropriately, but that
   // malformed hosts are rejected
   cm.add("baz.com", "/", "foo", "bar", false, false, true, expiry);
   do_check_eq(cm.countCookiesFromHost("baz.com"), 1);
   do_check_eq(cm.countCookiesFromHost("BAZ.com"), 1);
   do_check_eq(cm.countCookiesFromHost(".baz.com"), 1);
   do_check_eq(cm.countCookiesFromHost("baz.com."), 0);
   do_check_eq(cm.countCookiesFromHost(".baz.com."), 0);
--- a/extensions/cookie/test/unit/test_cookies_async_failure.js
+++ b/extensions/cookie/test/unit/test_cookies_async_failure.js
@@ -31,16 +31,19 @@ function finish_test() {
     do_test_finished();
   });
 }
 
 function do_run_test() {
   // Set up a profile.
   this.profile = do_get_profile();
 
+  // Allow all cookies.
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
   // Get the cookie file and the backup file.
   do_check_false(do_get_cookie_file(profile).exists());
   do_check_false(do_get_backup_file(profile).exists());
 
   // Create a cookie object for testing.
   this.now = Date.now() * 1000;
   this.futureExpiry = Math.round(this.now / 1e6 + 1000);
   this.cookie = new Cookie("oh", "hai", "bar.com", "/", this.futureExpiry,
--- a/extensions/cookie/test/unit/test_cookies_profile_close.js
+++ b/extensions/cookie/test/unit/test_cookies_profile_close.js
@@ -16,16 +16,19 @@ function finish_test() {
     do_test_finished();
   });
 }
 
 function do_run_test() {
   // Set up a profile.
   let profile = do_get_profile();
 
+  // Allow all cookies.
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
   // Start the cookieservice.
   Services.cookies;
 
   // Set a cookie.
   let uri = NetUtil.newURI("http://foo.com");
   Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null);
   let enumerator = Services.cookiemgr.enumerator;
   do_check_true(enumerator.hasMoreElements());
--- a/extensions/cookie/test/unit/test_cookies_read.js
+++ b/extensions/cookie/test/unit/test_cookies_read.js
@@ -16,16 +16,19 @@ function finish_test() {
     do_test_finished();
   });
 }
 
 function do_run_test() {
   // Set up a profile.
   let profile = do_get_profile();
 
+  // Allow all cookies.
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
   // Start the cookieservice, to force creation of a database.
   Services.cookies;
 
   // Open a database connection now, after synchronous initialization has
   // completed. We may not be able to open one later once asynchronous writing
   // begins.
   do_check_true(do_get_cookie_file(profile).exists());
   let db = new CookieDatabaseConnection(do_get_cookie_file(profile), 4);
--- a/extensions/cookie/test/unit/test_cookies_sync_failure.js
+++ b/extensions/cookie/test/unit/test_cookies_sync_failure.js
@@ -33,16 +33,19 @@ function finish_test() {
     do_test_finished();
   });
 }
 
 function do_run_test() {
   // Set up a profile.
   this.profile = do_get_profile();
 
+  // Allow all cookies.
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
   // Get the cookie file and the backup file.
   this.cookieFile = profile.clone();
   cookieFile.append("cookies.sqlite");
   this.backupFile = profile.clone();
   backupFile.append("cookies.sqlite.bak");
   do_check_false(cookieFile.exists());
   do_check_false(backupFile.exists());
 
--- a/extensions/cookie/test/unit/test_cookies_thirdparty.js
+++ b/extensions/cookie/test/unit/test_cookies_thirdparty.js
@@ -45,31 +45,103 @@ function run_test() {
 
   // test with third party cookies blocked
   Services.prefs.setIntPref("network.cookie.cookieBehavior", 1);
   do_set_cookies(uri1, channel1, true, [0, 1, 1, 2]);
   Services.cookies.removeAll();
   do_set_cookies(uri1, channel2, true, [0, 0, 0, 0]);
   Services.cookies.removeAll();
 
-  // Test per-site 3rd party cookies with cookies enabled
+  // test with third party cookies limited
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 3);
+  do_set_cookies(uri1, channel1, true, [0, 1, 2, 3]);
+  Services.cookies.removeAll();
+  do_set_cookies(uri1, channel2, true, [0, 0, 0, 0]);
+  Services.cookies.removeAll();
+  do_set_single_http_cookie(uri1, channel1, 1);
+  do_set_cookies(uri1, channel2, true, [2, 3, 4, 5]);
+  Services.cookies.removeAll();
+
+  // Test per-site 3rd party cookie blocking with cookies enabled
   Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
   var kPermissionType = "cookie";
   var ALLOW_FIRST_PARTY_ONLY = 9;
   // ALLOW_FIRST_PARTY_ONLY overrides
   Services.permissions.add(uri1, kPermissionType, ALLOW_FIRST_PARTY_ONLY);
   do_set_cookies(uri1, channel1, true, [0, 1, 1, 2]);
   Services.cookies.removeAll();
   do_set_cookies(uri1, channel2, true, [0, 0, 0, 0]);
   Services.cookies.removeAll();
 
-  // Test per-site 3rd party cookies with 3rd party cookies disabled
+  // Test per-site 3rd party cookie blocking with 3rd party cookies disabled
   Services.prefs.setIntPref("network.cookie.cookieBehavior", 1);
   do_set_cookies(uri1, channel1, true, [0, 1, 1, 2]);
   Services.cookies.removeAll();
   // No preference has been set for uri2, but it should act as if
   // ALLOW_FIRST_PARTY_ONLY has been set
   do_set_cookies(uri2, channel2, true, [0, 1, 1, 2]);
   Services.cookies.removeAll();
   do_set_cookies(uri1, channel2, true, [0, 0, 0, 0]);
   Services.cookies.removeAll();
+
+  // Test per-site 3rd party cookie blocking with 3rd party cookies limited
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 3);
+  do_set_cookies(uri1, channel1, true, [0, 1, 1, 2]);
+  Services.cookies.removeAll();
+  // No preference has been set for uri2, but it should act as if
+  // LIMIT_THIRD_PARTY has been set
+  do_set_cookies(uri2, channel2, true, [0, 1, 2, 3]);
+  Services.cookies.removeAll();
+  do_set_single_http_cookie(uri2, channel2, 1);
+  do_set_cookies(uri2, channel2, true, [2, 3, 4, 5]);
+  Services.cookies.removeAll();
+  do_set_cookies(uri1, channel2, true, [0, 0, 0, 0]);
+  Services.cookies.removeAll();
+  do_set_single_http_cookie(uri1, channel1, 1);
+  do_set_cookies(uri1, channel2, true, [1, 1, 1, 1]);
+  Services.cookies.removeAll();
+
+  // Test per-site 3rd party cookie limiting with cookies enabled
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+  var kPermissionType = "cookie";
+  var LIMIT_THIRD_PARTY = 10;
+  // LIMIT_THIRD_PARTY overrides
+  Services.permissions.add(uri1, kPermissionType, LIMIT_THIRD_PARTY);
+  do_set_cookies(uri1, channel1, true, [0, 1, 2, 3]);
+  Services.cookies.removeAll();
+  do_set_cookies(uri1, channel2, true, [0, 0, 0, 0]);
+  Services.cookies.removeAll();
+  do_set_single_http_cookie(uri1, channel1, 1);
+  do_set_cookies(uri1, channel2, true, [2, 3, 4, 5]);
+  Services.cookies.removeAll();
+
+  // Test per-site 3rd party cookie limiting with 3rd party cookies disabled
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 1);
+  do_set_cookies(uri1, channel1, true, [0, 1, 2, 3]);
+  Services.cookies.removeAll();
+  // No preference has been set for uri2, but it should act as if
+  // ALLOW_FIRST_PARTY_ONLY has been set
+  do_set_cookies(uri2, channel2, true, [0, 1, 1, 2]);
+  Services.cookies.removeAll();
+  do_set_cookies(uri1, channel2, true, [0, 0, 0, 0]);
+  Services.cookies.removeAll();
+  do_set_single_http_cookie(uri1, channel1, 1);
+  do_set_cookies(uri1, channel2, true, [2, 3, 4, 5]);
+  Services.cookies.removeAll();
+
+  // Test per-site 3rd party cookie limiting with 3rd party cookies limited
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 3);
+  do_set_cookies(uri1, channel1, true, [0, 1, 2, 3]);
+  Services.cookies.removeAll();
+  // No preference has been set for uri2, but it should act as if
+  // LIMIT_THIRD_PARTY has been set
+  do_set_cookies(uri2, channel2, true, [0, 1, 2, 3]);
+  Services.cookies.removeAll();
+  do_set_single_http_cookie(uri2, channel2, 1);
+  do_set_cookies(uri2, channel2, true, [2, 3, 4, 5]);
+  Services.cookies.removeAll();
+  do_set_cookies(uri1, channel2, true, [0, 0, 0, 0]);
+  Services.cookies.removeAll();
+  do_set_single_http_cookie(uri1, channel1, 1);
+  do_set_cookies(uri1, channel2, true, [2, 3, 4, 5]);
+  Services.cookies.removeAll();
 }
 
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -1281,17 +1281,23 @@ pref("network.proxy.ssl",               
 pref("network.proxy.ssl_port",              0);
 pref("network.proxy.socks",                 "");
 pref("network.proxy.socks_port",            0);
 pref("network.proxy.socks_version",         5);
 pref("network.proxy.socks_remote_dns",      false);
 pref("network.proxy.no_proxies_on",         "localhost, 127.0.0.1");
 pref("network.proxy.failover_timeout",      1800); // 30 minutes
 pref("network.online",                      true); //online/offline
-pref("network.cookie.cookieBehavior",       0); // 0-Accept, 1-dontAcceptForeign, 2-dontUse
+pref("network.cookie.cookieBehavior",       3); // 0-Accept, 1-dontAcceptForeign, 2-dontUse, 3-limitForeign
+#ifdef ANDROID
+pref("network.cookie.cookieBehavior",       0); // Keep the old default of accepting all cookies
+#endif
+#ifdef MOZ_WIDGET_GONK
+pref("network.cookie.cookieBehavior",       0); // Keep the old default of accepting all cookies
+#endif
 pref("network.cookie.thirdparty.sessionOnly", false);
 pref("network.cookie.lifetimePolicy",       0); // accept normally, 1-askBeforeAccepting, 2-acceptForSession,3-acceptForNDays
 pref("network.cookie.alwaysAcceptSessionCookies", false);
 pref("network.cookie.prefsMigrated",        false);
 pref("network.cookie.lifetime.days",        90);
 
 // The PAC file to load.  Ignored unless network.proxy.type is 2.
 pref("network.proxy.autoconfig_url", "");
--- a/netwerk/cookie/CookieServiceChild.cpp
+++ b/netwerk/cookie/CookieServiceChild.cpp
@@ -17,16 +17,17 @@ using namespace mozilla::ipc;
 
 namespace mozilla {
 namespace net {
 
 // Behavior pref constants
 static const int32_t BEHAVIOR_ACCEPT = 0;
 static const int32_t BEHAVIOR_REJECTFOREIGN = 1;
 static const int32_t BEHAVIOR_REJECT = 2;
+static const int32_t BEHAVIOR_LIMITFOREIGN = 3;
 
 // Pref string constants
 static const char kPrefCookieBehavior[] = "network.cookie.cookieBehavior";
 static const char kPrefThirdPartySession[] =
   "network.cookie.thirdparty.sessionOnly";
 
 static CookieServiceChild *gCookieService;
 
@@ -75,32 +76,32 @@ CookieServiceChild::~CookieServiceChild(
 }
 
 void
 CookieServiceChild::PrefChanged(nsIPrefBranch *aPrefBranch)
 {
   int32_t val;
   if (NS_SUCCEEDED(aPrefBranch->GetIntPref(kPrefCookieBehavior, &val)))
     mCookieBehavior =
-      val >= BEHAVIOR_ACCEPT && val <= BEHAVIOR_REJECT ? val : BEHAVIOR_ACCEPT;
+      val >= BEHAVIOR_ACCEPT && val <= BEHAVIOR_LIMITFOREIGN ? val : BEHAVIOR_ACCEPT;
 
   bool boolval;
   if (NS_SUCCEEDED(aPrefBranch->GetBoolPref(kPrefThirdPartySession, &boolval)))
     mThirdPartySession = !!boolval;
 
   if (!mThirdPartyUtil && RequireThirdPartyCheck()) {
     mThirdPartyUtil = do_GetService(THIRDPARTYUTIL_CONTRACTID);
     NS_ASSERTION(mThirdPartyUtil, "require ThirdPartyUtil service");
   }
 }
 
 bool
 CookieServiceChild::RequireThirdPartyCheck()
 {
-  return mCookieBehavior == BEHAVIOR_REJECTFOREIGN || mThirdPartySession;
+  return mCookieBehavior == BEHAVIOR_REJECTFOREIGN || mCookieBehavior == BEHAVIOR_LIMITFOREIGN || mThirdPartySession;
 }
 
 nsresult
 CookieServiceChild::GetCookieStringInternal(nsIURI *aHostURI,
                                             nsIChannel *aChannel,
                                             char **aCookieString,
                                             bool aFromHttp)
 {
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -90,19 +90,21 @@ static const char kOldCookieFileName[] =
 // default limits for the cookie list. these can be tuned by the
 // network.cookie.maxNumber and network.cookie.maxPerHost prefs respectively.
 static const uint32_t kMaxNumberOfCookies = 3000;
 static const uint32_t kMaxCookiesPerHost  = 150;
 static const uint32_t kMaxBytesPerCookie  = 4096;
 static const uint32_t kMaxBytesPerPath    = 1024;
 
 // behavior pref constants
-static const uint32_t BEHAVIOR_ACCEPT        = 0;
-static const uint32_t BEHAVIOR_REJECTFOREIGN = 1;
-static const uint32_t BEHAVIOR_REJECT        = 2;
+static const uint32_t BEHAVIOR_ACCEPT        = 0; // allow all cookies
+static const uint32_t BEHAVIOR_REJECTFOREIGN = 1; // reject all third-party cookies
+static const uint32_t BEHAVIOR_REJECT        = 2; // reject all cookies
+static const uint32_t BEHAVIOR_LIMITFOREIGN  = 3; // reject third-party cookies unless the
+                                                  // eTLD already has at least one cookie
 
 // pref string constants
 static const char kPrefCookieBehavior[]     = "network.cookie.cookieBehavior";
 static const char kPrefMaxNumberOfCookies[] = "network.cookie.maxNumber";
 static const char kPrefMaxCookiesPerHost[]  = "network.cookie.maxPerHost";
 static const char kPrefCookiePurgeAge[]     = "network.cookie.purgeAge";
 static const char kPrefThirdPartySession[]  = "network.cookie.thirdparty.sessionOnly";
 
@@ -1689,17 +1691,17 @@ nsCookieService::CreatePurgeList(nsICook
  * pref observer impl
  ******************************************************************************/
 
 void
 nsCookieService::PrefChanged(nsIPrefBranch *aPrefBranch)
 {
   int32_t val;
   if (NS_SUCCEEDED(aPrefBranch->GetIntPref(kPrefCookieBehavior, &val)))
-    mCookieBehavior = (uint8_t) LIMIT(val, 0, 2, 0);
+    mCookieBehavior = (uint8_t) LIMIT(val, 0, 3, 0);
 
   if (NS_SUCCEEDED(aPrefBranch->GetIntPref(kPrefMaxNumberOfCookies, &val)))
     mMaxNumberOfCookies = (uint16_t) LIMIT(val, 1, 0xFFFF, kMaxNumberOfCookies);
 
   if (NS_SUCCEEDED(aPrefBranch->GetIntPref(kPrefMaxCookiesPerHost, &val)))
     mMaxCookiesPerHost = (uint16_t) LIMIT(val, 1, 0xFFFF, kMaxCookiesPerHost);
 
   if (NS_SUCCEEDED(aPrefBranch->GetIntPref(kPrefCookiePurgeAge, &val))) {
@@ -3239,16 +3241,30 @@ nsCookieService::CheckPrefs(nsIURI      
           COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI,
                             aCookieHeader, "third party cookies are blocked "
                             "for this site");
           return STATUS_REJECTED;
 
         }
         return STATUS_ACCEPTED;
 
+      case nsICookiePermission::ACCESS_LIMIT_THIRD_PARTY:
+        if (!aIsForeign)
+          return STATUS_ACCEPTED;
+        uint32_t priorCookieCount = 0;
+        nsAutoCString hostFromURI;
+        aHostURI->GetHost(hostFromURI);
+        CountCookiesFromHost(hostFromURI, &priorCookieCount);
+        if (priorCookieCount == 0) {
+          COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI,
+                            aCookieHeader, "third party cookies are blocked "
+                            "for this site");
+          return STATUS_REJECTED;
+        }
+        return STATUS_ACCEPTED;
       }
     }
   }
 
   // check default prefs
   if (mCookieBehavior == BEHAVIOR_REJECT) {
     COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "cookies are disabled");
     return STATUS_REJECTED;
@@ -3258,16 +3274,29 @@ nsCookieService::CheckPrefs(nsIURI      
   if (aIsForeign) {
     if (mCookieBehavior == BEHAVIOR_ACCEPT && mThirdPartySession)
       return STATUS_ACCEPT_SESSION;
 
     if (mCookieBehavior == BEHAVIOR_REJECTFOREIGN) {
       COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "context is third party");
       return STATUS_REJECTED;
     }
+
+    if (mCookieBehavior == BEHAVIOR_LIMITFOREIGN) {
+      uint32_t priorCookieCount = 0;
+      nsAutoCString hostFromURI;
+      aHostURI->GetHost(hostFromURI);
+      CountCookiesFromHost(hostFromURI, &priorCookieCount);
+      if (priorCookieCount == 0) {
+        COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI, aCookieHeader, "context is third party");
+        return STATUS_REJECTED;
+      }
+      if (mThirdPartySession)
+        return STATUS_ACCEPT_SESSION;
+    }
   }
 
   // if nothing has complained, accept cookie
   return STATUS_ACCEPTED;
 }
 
 // processes domain attribute, and returns true if host has permission to set for this domain.
 bool
--- a/netwerk/cookie/nsCookieService.h
+++ b/netwerk/cookie/nsCookieService.h
@@ -320,17 +320,17 @@ class nsCookieService : public nsICookie
     // this state encapsulates both the in-memory table and the on-disk DB.
     // note that the private states' dbConn should always be null - we never
     // want to be dealing with the on-disk DB when in private browsing.
     DBState                      *mDBState;
     nsRefPtr<DBState>             mDefaultDBState;
     nsRefPtr<DBState>             mPrivateDBState;
 
     // cached prefs
-    uint8_t                       mCookieBehavior; // BEHAVIOR_{ACCEPT, REJECTFOREIGN, REJECT}
+    uint8_t                       mCookieBehavior; // BEHAVIOR_{ACCEPT, REJECTFOREIGN, REJECT, LIMITFOREIGN}
     bool                          mThirdPartySession;
     uint16_t                      mMaxNumberOfCookies;
     uint16_t                      mMaxCookiesPerHost;
     int64_t                       mCookiePurgeAge;
 
     // friends!
     friend PLDHashOperator purgeCookiesCallback(nsCookieEntry *aEntry, void *aArg);
     friend class DBListenerErrorHandler;
--- a/netwerk/cookie/nsICookiePermission.idl
+++ b/netwerk/cookie/nsICookiePermission.idl
@@ -26,16 +26,17 @@ interface nsICookiePermission : nsISuppo
   /**
    * additional values for nsCookieAccess which may not match
    * nsIPermissionManager. Keep 3-7 available to allow nsIPermissionManager to
    * add values without colliding. ACCESS_SESSION is not directly returned by
    * any methods on this interface.
    */
   const nsCookieAccess ACCESS_SESSION = 8;
   const nsCookieAccess ACCESS_ALLOW_FIRST_PARTY_ONLY = 9;
+  const nsCookieAccess ACCESS_LIMIT_THIRD_PARTY = 10;
 
   /**
    * setAccess
    *
    * this method is called to block cookie access for the given URI.  this
    * may result in other URIs being blocked as well (e.g., URIs which share
    * the same host name).
    *
--- a/netwerk/cookie/test/unit/test_bug643051.js
+++ b/netwerk/cookie/test/unit/test_bug643051.js
@@ -1,14 +1,18 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 Components.utils.import("resource://gre/modules/NetUtil.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
 
 function run_test() {
+  // Allow all cookies.
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
   let cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
 
   let uri = NetUtil.newURI("http://example.org/");
 
   let set = "foo=bar\nbaz=foo";
   let expected = "foo=bar; baz=foo";
   cs.setCookieStringFromHttp(uri, null, null, set, null, null);
 
--- a/netwerk/cookie/test/unit/test_parser_0001.js
+++ b/netwerk/cookie/test/unit/test_parser_0001.js
@@ -1,14 +1,25 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 Components.utils.import("resource://gre/modules/NetUtil.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+function inChildProcess() {
+  return Cc["@mozilla.org/xre/app-info;1"]
+           .getService(Ci.nsIXULRuntime)
+           .processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
+}
 
 function run_test() {
+  // Allow all cookies if the pref service is available in this process.
+  if (!inChildProcess())
+    Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
   let cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
 
   let uri = NetUtil.newURI("http://example.org/");
 
   let set = "foo=bar";
   cs.setCookieStringFromHttp(uri, null, null, set, null, null);
 
   let expected = "foo=bar";
--- a/netwerk/cookie/test/unit/test_parser_0019.js
+++ b/netwerk/cookie/test/unit/test_parser_0019.js
@@ -1,14 +1,25 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 Components.utils.import("resource://gre/modules/NetUtil.jsm");
+Components.utils.import("resource://gre/modules/Services.jsm");
+
+function inChildProcess() {
+  return Cc["@mozilla.org/xre/app-info;1"]
+           .getService(Ci.nsIXULRuntime)
+           .processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
+}
 
 function run_test() {
+  // Allow all cookies if the pref service is available in this process.
+  if (!inChildProcess())
+    Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
   let cs = Cc["@mozilla.org/cookieService;1"].getService(Ci.nsICookieService);
 
   let uri = NetUtil.newURI("http://example.org/");
 
   let set = "foo=b;max-age=3600, c=d;path=/";
   cs.setCookieStringFromHttp(uri, null, null, set, null, null);
 
   let expected = "foo=b";
--- a/netwerk/cookie/test/unit_ipc/test_ipc_parser_0001.js
+++ b/netwerk/cookie/test/unit_ipc/test_ipc_parser_0001.js
@@ -1,3 +1,9 @@
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
 function run_test() {
+  // Allow all cookies.
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
   run_test_in_child("../unit/test_parser_0001.js");
 }
--- a/netwerk/cookie/test/unit_ipc/test_ipc_parser_0019.js
+++ b/netwerk/cookie/test/unit_ipc/test_ipc_parser_0019.js
@@ -1,3 +1,9 @@
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
 function run_test() {
+  // Allow all cookies.
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
   run_test_in_child("../unit/test_parser_0019.js");
 }
--- a/netwerk/test/unit/test_bug248970_cookie.js
+++ b/netwerk/test/unit/test_bug248970_cookie.js
@@ -61,16 +61,20 @@ function setHandler(metadata, response) 
   response.setStatusLine("1.0", 200, "Cookie set");
   var match = /cookie=([^&]*)/.exec(metadata.queryString);
   if (match) {
     response.setHeader("Set-Cookie", match[1]);
   }
 }
 
 function run_test() {
+  // Allow all cookies if the pref service is available in this process.
+  if (!inChildProcess())
+    Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
   httpserver = new HttpServer();
   httpserver.registerPathHandler("/set", setHandler);
   httpserver.registerPathHandler("/present", presentHandler);
   httpserver.start(4444);
   
   do_test_pending();
   
   function check_cookie(req) {
--- a/netwerk/test/unit/test_bug659569.js
+++ b/netwerk/test/unit/test_bug659569.js
@@ -1,14 +1,15 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import("resource://testing-common/httpd.js");
+Cu.import("resource://gre/modules/Services.jsm");
 var httpserver = new HttpServer();
 
 function setupChannel(suffix)
 {
     var ios =
         Components.classes["@mozilla.org/network/io-service;1"]
         .getService(Ci.nsIIOService);
     var chan = ios.newChannel("http://localhost:4444" + suffix, "", null);
@@ -18,16 +19,19 @@ function setupChannel(suffix)
 function checkValueAndTrigger(request, data, ctx)
 {
     do_check_eq("Ok", data);
     httpserver.stop(do_test_finished);
 }
 
 function run_test()
 {
+    // Allow all cookies.
+    Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
     httpserver.registerPathHandler("/redirect1", redirectHandler1);
     httpserver.registerPathHandler("/redirect2", redirectHandler2);
     httpserver.start(4444);
 
     // clear cache
     evict_cache_entries();
 
     // load first time
--- a/netwerk/test/unit/test_bug667818.js
+++ b/netwerk/test/unit/test_bug667818.js
@@ -1,15 +1,21 @@
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
 function makeURI(str) {
     return Components.classes["@mozilla.org/network/io-service;1"]
                      .getService(Components.interfaces.nsIIOService)
                      .newURI(str, null, null);
 }
 
 function run_test() {
+    // Allow all cookies.
+    Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
     var serv =   Components.classes["@mozilla.org/cookieService;1"]
                            .getService(Components.interfaces.nsICookieService);
     var uri = makeURI("http://example.com/");
     // Try an expiration time before the epoch
     serv.setCookieString(uri, null, "test=test; path=/; domain=example.com; expires=Sun, 31-Dec-1899 16:00:00 GMT;", null);
     do_check_eq(serv.getCookieString(uri, null), null);
     // Now sanity check
     serv.setCookieString(uri, null, "test2=test2; path=/; domain=example.com;", null);
--- a/netwerk/test/unit/test_cookie_header.js
+++ b/netwerk/test/unit/test_cookie_header.js
@@ -1,16 +1,23 @@
 // This file tests bug 250375
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import("resource://testing-common/httpd.js");
+Cu.import("resource://gre/modules/Services.jsm");
+
+function inChildProcess() {
+  return Cc["@mozilla.org/xre/app-info;1"]
+           .getService(Ci.nsIXULRuntime)
+           .processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;  
+}
 
 function check_request_header(chan, name, value) {
   var chanValue;
   try {
     chanValue = chan.getRequestHeader(name);
   } catch (e) {
     do_throw("Expected to find header '" + name + "' but didn't find it, got exception: " + e);
   }
@@ -56,16 +63,20 @@ function makeChan() {
                 .QueryInterface(Components.interfaces.nsIHttpChannel);
 
   return chan;
 }
 
 var httpserv = null;
 
 function run_test() {
+  // Allow all cookies if the pref service is available in this process.
+  if (!inChildProcess())
+    Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
   httpserv = new HttpServer();
   httpserv.start(4444);
 
   var chan = makeChan();
 
   chan.setRequestHeader("Cookie", cookieVal, false);
 
   chan.asyncOpen(listener, null);
--- a/netwerk/test/unit/test_cookiejars.js
+++ b/netwerk/test/unit/test_cookiejars.js
@@ -9,21 +9,28 @@
  */ 
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import("resource://testing-common/httpd.js");
+Cu.import("resource://gre/modules/Services.jsm");
 var httpserver = new HttpServer();
 
 var cookieSetPath = "/setcookie";
 var cookieCheckPath = "/checkcookie";
 
+function inChildProcess() {
+  return Cc["@mozilla.org/xre/app-info;1"]
+           .getService(Ci.nsIXULRuntime)
+           .processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
+}
+
 // Test array:
 //  - element 0: name for cookie, used both to set and later to check 
 //  - element 1: loadContext (determines cookie namespace)
 //
 // TODO: bug 722850: make private browsing work per-app, and add tests.  For now
 // all values are 'false' for PB.
 
 var tests = [
@@ -104,16 +111,20 @@ function completeCheckCookie(request, da
     httpserver.stop(do_test_finished);
   } else {
     checkCookie();
   }
 }
 
 function run_test()
 {
+  // Allow all cookies if the pref service is available in this process.
+  if (!inChildProcess())
+    Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
   httpserver.registerPathHandler(cookieSetPath, cookieSetHandler);
   httpserver.registerPathHandler(cookieCheckPath, cookieCheckHandler);
   httpserver.start(4444);
 
   setCookie();
   do_test_pending();
 }
 
--- a/netwerk/test/unit/test_private_cookie_changed.js
+++ b/netwerk/test/unit/test_private_cookie_changed.js
@@ -10,16 +10,19 @@ function makeChan(uri, isPrivate) {
   var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
   var chan = ios.newChannel(uri.spec, null, null)
                 .QueryInterface(Ci.nsIHttpChannel);
   chan.QueryInterface(Ci.nsIPrivateBrowsingChannel).setPrivate(isPrivate);
   return chan;
 }
 
 function run_test() {
+  // Allow all cookies.
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+  
   let publicNotifications = 0;
   let privateNotifications = 0;
   Services.obs.addObserver(function() {publicNotifications++;}, "cookie-changed", false);
   Services.obs.addObserver(function() {privateNotifications++;}, "private-cookie-changed", false);
 
   let uri = NetUtil.newURI("http://foo.com/");
   let publicChan = makeChan(uri, false);
   let svc = Services.cookies.QueryInterface(Ci.nsICookieService);
--- a/netwerk/test/unit_ipc/test_bug248970_cookie_wrap.js
+++ b/netwerk/test/unit_ipc/test_bug248970_cookie_wrap.js
@@ -1,3 +1,9 @@
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
 function run_test() {
+  // Allow all cookies.
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
   run_test_in_child("../unit/test_bug248970_cookie.js");
 }
\ No newline at end of file
--- a/netwerk/test/unit_ipc/test_cookie_header_wrap.js
+++ b/netwerk/test/unit_ipc/test_cookie_header_wrap.js
@@ -1,7 +1,13 @@
 //
 // Run test script in content process instead of chrome (xpcshell's default)
 //
 
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
 function run_test() {
+  // Allow all cookies.
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
   run_test_in_child("../unit/test_cookie_header.js");
 }
--- a/netwerk/test/unit_ipc/test_cookiejars_wrap.js
+++ b/netwerk/test/unit_ipc/test_cookiejars_wrap.js
@@ -1,3 +1,9 @@
+const Cu = Components.utils;
+
+Cu.import("resource://gre/modules/Services.jsm");
+
 function run_test() {
+  // Allow all cookies.
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
   run_test_in_child("../unit/test_cookiejars.js");
 }
--- a/toolkit/components/downloads/test/unit/test_private_resume.js
+++ b/toolkit/components/downloads/test/unit/test_private_resume.js
@@ -2,16 +2,19 @@
  * 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/. */
 
 // Public request gets times=0 cookie, completes
 // Private request gets times=1 cookie, canceled
 // Private resumed request sends times=1 cookie, completes
 
 function run_test() {
+  // Allow all cookies.
+  Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
+
   do_test_pending();
   let httpserv = new HttpServer();
 
   let times = 0;
   httpserv.registerPathHandler("/head_download_manager.js", function (meta, response) {
     response.setHeader("Content-Type", "text/plain", false);
     response.setStatusLine("1.1", !meta.hasHeader('range') ? 200 : 206);
 
--- a/toolkit/devtools/webconsole/test/network_requests_iframe.html
+++ b/toolkit/devtools/webconsole/test/network_requests_iframe.html
@@ -1,17 +1,31 @@
 <!DOCTYPE HTML>
 <html>
   <head>
     <meta charset="utf-8">
     <title>Console HTTP test page</title>
     <!-- Any copyright is dedicated to the Public Domain.
        - http://creativecommons.org/publicdomain/zero/1.0/ -->
     <script type="text/javascript"><!--
+      var setAllowAllCookies = false;
+
       function makeXhr(aMethod, aUrl, aRequestBody, aCallback) {
+        // On the first call, allow all cookies and set cookies, then resume the actual test
+        if(!setAllowAllCookies)
+          SpecialPowers.pushPrefEnv({"set": [["network.cookie.cookieBehavior", 0]]}, function () {
+            setAllowAllCookies = true;
+            setCookies();
+            makeXhrCallback(aMethod, aUrl, aRequestBody, aCallback);
+          });
+        else
+          makeXhrCallback(aMethod, aUrl, aRequestBody, aCallback);
+      }
+
+      function makeXhrCallback(aMethod, aUrl, aRequestBody, aCallback) {
         var xmlhttp = new XMLHttpRequest();
         xmlhttp.open(aMethod, aUrl, true);
         if (aCallback) {
           xmlhttp.onreadystatechange = function() {
             if (xmlhttp.readyState == 4) {
               aCallback();
             }
           };
@@ -22,20 +36,22 @@
       function testXhrGet(aCallback) {
         makeXhr('get', 'data.json', null, aCallback);
       }
 
       function testXhrPost(aCallback) {
         var body = "Hello world! " + (new Array(50)).join("foobaz barr");
         makeXhr('post', 'data.json', body, aCallback);
       }
-
-      document.cookie = "foobar=fooval";
-      document.cookie = "omgfoo=bug768096";
-      document.cookie = "badcookie=bug826798=st3fan";
+      
+      function setCookies() {
+        document.cookie = "foobar=fooval";
+        document.cookie = "omgfoo=bug768096";
+        document.cookie = "badcookie=bug826798=st3fan";
+      }
     // --></script>
   </head>
   <body>
     <h1>Web Console HTTP Logging Testpage</h1>
     <h2>This page is used to test the HTTP logging.</h2>
 
     <form action="?" method="post">
       <input name="name" type="text" value="foo bar"><br>