Backed out 2 changesets (bug 1521051) for xpcshell fails on extensions/cookie/test/unit/test_cookies_thirdparty.js. CLOSED TREE
authorRazvan Maries <rmaries@mozilla.com>
Wed, 23 Jan 2019 22:09:32 +0200
changeset 515171 f0f4bf8af10a1ba026623963950277dac0814360
parent 515170 211eda3487ef5bb72a2482e15051808ec508166d
child 515172 b8444f241aca60ed9f7520b89bb0865c61da96f3
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1521051
milestone66.0a1
backs out90bb620dd870552e1a9c64d4bb4924c0d3f56065
483fa314e45e0cc19039c69726068ab8b8d37cec
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
Backed out 2 changesets (bug 1521051) for xpcshell fails on extensions/cookie/test/unit/test_cookies_thirdparty.js. CLOSED TREE Backed out changeset 90bb620dd870 (bug 1521051) Backed out changeset 483fa314e45e (bug 1521051)
browser/components/preferences/permissions.js
browser/locales/en-US/browser/preferences/permissions.ftl
browser/modules/Sanitizer.jsm
dom/base/nsContentUtils.cpp
dom/tests/mochitest/localstorage/mochitest.ini
dom/tests/mochitest/localstorage/test_firstPartyOnlyPermission.html
extensions/cookie/nsCookiePermission.cpp
extensions/cookie/test/unit/test_cookies_thirdparty.js
netwerk/cookie/nsCookieService.cpp
netwerk/cookie/nsICookiePermission.idl
testing/mochitest/tests/Harness_sanity/test_SpecialPowersPushPermissions.html
testing/specialpowers/content/specialpowersAPI.js
--- a/browser/components/preferences/permissions.js
+++ b/browser/components/preferences/permissions.js
@@ -126,64 +126,53 @@ var gPermissionManager = {
     if (permission.type !== this._type)
       return;
 
     if (data == "added") {
       this._addPermissionToList(permission);
       this.buildPermissionsList();
     } else if (data == "changed") {
       let p = this._permissions.get(permission.principal.origin);
-      // Maybe this item has been excluded before because it had an invalid capability.
-      if (p) {
-        p.capability = permission.capability;
-        this._handleCapabilityChange(p);
-      } else {
-        this._addPermissionToList(permission);
-      }
+      p.capability = permission.capability;
+      this._handleCapabilityChange(p);
       this.buildPermissionsList();
     } else if (data == "deleted") {
       this._removePermissionFromList(permission.principal.origin);
     }
   },
 
   _handleCapabilityChange(perm) {
     let permissionlistitem = document.getElementsByAttribute("origin", perm.origin)[0];
     document.l10n.setAttributes(permissionlistitem.querySelector(".website-capability-value"), this._getCapabilityL10nId(perm.capability));
   },
 
-  _isCapabilitySupported(capability) {
-     return capability == Ci.nsIPermissionManager.ALLOW_ACTION ||
-            capability == Ci.nsIPermissionManager.DENY_ACTION ||
-            capability == Ci.nsICookiePermission.ACCESS_SESSION;
-  },
-
   _getCapabilityL10nId(capability) {
     let stringKey = null;
     switch (capability) {
     case Ci.nsIPermissionManager.ALLOW_ACTION:
       stringKey = "permissions-capabilities-listitem-allow";
       break;
     case Ci.nsIPermissionManager.DENY_ACTION:
       stringKey = "permissions-capabilities-listitem-block";
       break;
+    case Ci.nsICookiePermission.ACCESS_ALLOW_FIRST_PARTY_ONLY:
+      stringKey = "permissions-capabilities-listitem-allow-first-party";
+      break;
     case Ci.nsICookiePermission.ACCESS_SESSION:
       stringKey = "permissions-capabilities-listitem-allow-session";
       break;
     default:
       throw new Error(`Unknown capability: ${capability}`);
     }
     return stringKey;
   },
 
   _addPermissionToList(perm) {
     if (perm.type !== this._type)
       return;
-    if (!this._isCapabilitySupported(perm.capability))
-      return;
-
     let p = new Permission(perm.principal, perm.type, perm.capability);
     this._permissions.set(p.origin, p);
   },
 
   addPermission(capability) {
     let textbox = document.getElementById("url");
     let input_url = textbox.value.replace(/^\s*/, ""); // trim any leading space
     let principal;
--- a/browser/locales/en-US/browser/preferences/permissions.ftl
+++ b/browser/locales/en-US/browser/preferences/permissions.ftl
@@ -55,16 +55,18 @@ permissions-capabilities-block =
     .label = Block
 permissions-capabilities-prompt =
     .label = Always Ask
 
 permissions-capabilities-listitem-allow =
     .value = Allow
 permissions-capabilities-listitem-block =
     .value = Block
+permissions-capabilities-listitem-allow-first-party =
+    .value = Allow first party only
 permissions-capabilities-listitem-allow-session =
     .value = Allow for Session
 
 ## Invalid Hostname Dialog
 
 permissions-invalid-uri-title = Invalid Hostname Entered
 permissions-invalid-uri-label = Please enter a valid hostname
 
--- a/browser/modules/Sanitizer.jsm
+++ b/browser/modules/Sanitizer.jsm
@@ -794,17 +794,19 @@ async function maybeSanitizeSessionPrinc
 
   return Promise.all(promises);
 }
 
 function cookiesAllowedForDomainOrSubDomain(principal) {
   // If we have the 'cookie' permission for this principal, let's return
   // immediately.
   let p = Services.perms.testPermissionFromPrincipal(principal, "cookie");
-  if (p == Ci.nsICookiePermission.ACCESS_ALLOW) {
+  if (p == Ci.nsICookiePermission.ACCESS_ALLOW ||
+      p == Ci.nsICookiePermission.ACCESS_ALLOW_FIRST_PARTY_ONLY ||
+      p == Ci.nsICookiePermission.ACCESS_LIMIT_THIRD_PARTY) {
     return true;
   }
 
   if (p == Ci.nsICookiePermission.ACCESS_DENY ||
       p == Ci.nsICookiePermission.ACCESS_SESSION) {
     return false;
   }
 
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -8183,16 +8183,32 @@ void nsContentUtils::GetCookieLifetimePo
       *aLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
       break;
     case nsICookiePermission::ACCESS_DENY:
       *aLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
       break;
     case nsICookiePermission::ACCESS_SESSION:
       *aLifetimePolicy = nsICookieService::ACCEPT_SESSION;
       break;
+    case nsICookiePermission::ACCESS_ALLOW_FIRST_PARTY_ONLY:
+      // NOTE: The decision was made here to override the lifetime policy to be
+      // ACCEPT_NORMALLY for consistency with ACCESS_ALLOW, but this does
+      // prevent us from expressing BEHAVIOR_REJECT_FOREIGN/ACCEPT_SESSION for a
+      // specific domain. As BEHAVIOR_REJECT_FOREIGN isn't visible in our UI,
+      // this is probably not an issue.
+      *aLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
+      break;
+    case nsICookiePermission::ACCESS_LIMIT_THIRD_PARTY:
+      // NOTE: The decision was made here to override the lifetime policy to be
+      // ACCEPT_NORMALLY for consistency with ACCESS_ALLOW, but this does
+      // prevent us from expressing BEHAVIOR_REJECT_FOREIGN/ACCEPT_SESSION for a
+      // specific domain. As BEHAVIOR_LIMIT_FOREIGN isn't visible in our UI,
+      // this is probably not an issue.
+      *aLifetimePolicy = nsICookieService::ACCEPT_NORMALLY;
+      break;
   }
 }
 
 // static public
 bool nsContentUtils::IsThirdPartyWindowOrChannel(nsPIDOMWindowInner* aWindow,
                                                  nsIChannel* aChannel,
                                                  nsIURI* aURI) {
   MOZ_ASSERT(!aWindow || !aChannel,
--- a/dom/tests/mochitest/localstorage/mochitest.ini
+++ b/dom/tests/mochitest/localstorage/mochitest.ini
@@ -45,8 +45,9 @@ skip-if = toolkit == 'android' #TIMED_OU
 [test_localStorageQuotaSessionOnly.html]
 skip-if = toolkit == 'android' || (verify && (os == 'linux' || os == 'mac' || os == 'win')) #TIMED_OUT
 [test_localStorageQuotaSessionOnly2.html]
 skip-if = true # bug 1347690
 [test_localStorageReplace.html]
 skip-if = toolkit == 'android'
 [test_storageConstructor.html]
 [test_localStorageSessionPrefOverride.html]
+[test_firstPartyOnlyPermission.html]
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/localstorage/test_firstPartyOnlyPermission.html
@@ -0,0 +1,62 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>first party storage permission test</title>
+
+<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="text/javascript" src="/tests/SimpleTest/AddTask.js"></script>
+<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+
+<script type="text/javascript">
+  TRY_ACCESS_SESSION_STORAGE =
+    'http://example.com/tests/dom/tests/mochitest/localstorage/file_tryAccessSessionStorage.html';
+
+  add_task(async function() {
+    await SpecialPowers.pushPrefEnv({
+      set: [['network.cookie.cookieBehavior', SpecialPowers.Ci.nsICookieService.BEHAVIOR_REJECT]],
+    });
+
+    try {
+      sessionStorage.setItem("blocked", "blocked");
+      ok(false, "Shouldn't be available yet");
+    } catch (ex) {
+      ok(true, "Shouldn't be available yet");
+    }
+
+    await new Promise(resolve => SpecialPowers.pushPermissions([{
+      type: 'cookie',
+      allow: SpecialPowers.Ci.nsICookiePermission.ACCESS_ALLOW_FIRST_PARTY_ONLY,
+      context: document,
+    }], resolve));
+
+    // With the permission set to ACCESS_ALLOW_FIRST_PARTY_ONLY, we should be
+    // able to run it from this iframe (as we are first party with the test
+    // runner parent document).
+    try {
+      sessionStorage.setItem("blocked", "blocked");
+      ok(true, "Should be available");
+    } catch (ex) {
+      ok(false, "Should be available");
+    }
+
+    // A third party iframe should not have access however.
+    await new Promise(resolve => {
+      window.onmessage = evt => {
+        window.onmessage = null;
+        is(evt.data, "sessionStorage=false");
+        resolve();
+      };
+
+      let iframe = document.createElement('iframe');
+      iframe.setAttribute('src', TRY_ACCESS_SESSION_STORAGE);
+      document.body.appendChild(iframe);
+    });
+  });
+
+</script>
+
+</head>
+
+<body>
+
+</body>
+</html>
--- a/extensions/cookie/nsCookiePermission.cpp
+++ b/extensions/cookie/nsCookiePermission.cpp
@@ -153,31 +153,60 @@ nsCookiePermission::CanSetCookie(nsIURI 
 
   *aResult = kDefaultPolicy;
 
   // Lazily initialize ourselves
   if (!EnsureInitialized()) return NS_ERROR_UNEXPECTED;
 
   uint32_t perm;
   mPermMgr->TestPermission(aURI, kPermissionType, &perm);
+  bool isThirdParty = false;
   switch (perm) {
     case nsICookiePermission::ACCESS_SESSION:
       *aIsSession = true;
       MOZ_FALLTHROUGH;
 
     case nsICookiePermission::ACCESS_ALLOW:
       *aResult = true;
       break;
 
     case nsICookiePermission::ACCESS_DENY:
       *aResult = false;
       break;
 
+    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<nsICookieManager> 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:
-      // Here we can have any legacy permission value.
+      // 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) {
         *aResult = true;
         return NS_OK;
       }
 
--- a/extensions/cookie/test/unit/test_cookies_thirdparty.js
+++ b/extensions/cookie/test/unit/test_cookies_thirdparty.js
@@ -94,16 +94,30 @@ function run_test() {
   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.perms.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();
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -4075,16 +4075,41 @@ CookieStatus nsCookieService::CheckPrefs
           COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI,
                             aCookieHeader, "cookies are blocked for this site");
           *aRejectedReason =
               nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION;
           return STATUS_REJECTED;
 
         case nsICookiePermission::ACCESS_ALLOW:
           return STATUS_ACCEPTED;
+
+        case nsICookiePermission::ACCESS_ALLOW_FIRST_PARTY_ONLY:
+          if (aIsForeign) {
+            COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI,
+                              aCookieHeader,
+                              "third party cookies are blocked "
+                              "for this site");
+            *aRejectedReason =
+                nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION;
+            return STATUS_REJECTED;
+          }
+          return STATUS_ACCEPTED;
+
+        case nsICookiePermission::ACCESS_LIMIT_THIRD_PARTY:
+          if (!aIsForeign) return STATUS_ACCEPTED;
+          if (aNumOfCookies == 0) {
+            COOKIE_LOGFAILURE(aCookieHeader ? SET_COOKIE : GET_COOKIE, aHostURI,
+                              aCookieHeader,
+                              "third party cookies are blocked "
+                              "for this site");
+            *aRejectedReason =
+                nsIWebProgressListener::STATE_COOKIES_BLOCKED_BY_PERMISSION;
+            return STATUS_REJECTED;
+          }
+          return STATUS_ACCEPTED;
       }
     }
   }
 
   // No cookies allowed if this request comes from a tracker, in a 3rd party
   // context, when anti-tracking protection is enabled and when we don't have
   // access to the first-party cookie jar.
   if (aIsForeign && aIsTrackingResource && !aFirstPartyStorageAccessGranted &&
--- a/netwerk/cookie/nsICookiePermission.idl
+++ b/netwerk/cookie/nsICookiePermission.idl
@@ -26,22 +26,18 @@ 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;
-
-  /**
-   * Don't use values 9 and 10! They used to be ACCESS_ALLOW_FIRST_PARTY_ONLY
-   * and ACCESS_LIMIT_THIRD_PARTY, now removed, but maybe still stored in some
-   * ancient user profiles.
-   */
+  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/testing/mochitest/tests/Harness_sanity/test_SpecialPowersPushPermissions.html
+++ b/testing/mochitest/tests/Harness_sanity/test_SpecialPowersPushPermissions.html
@@ -9,16 +9,18 @@
 
 <pre id="test">
 <script class="testbody" type="text/javascript">
 const ALLOW_ACTION = SpecialPowers.Ci.nsIPermissionManager.ALLOW_ACTION;
 const DENY_ACTION = SpecialPowers.Ci.nsIPermissionManager.DENY_ACTION;
 const UNKNOWN_ACTION = SpecialPowers.Ci.nsIPermissionManager.UNKNOWN_ACTION;
 const PROMPT_ACTION = SpecialPowers.Ci.nsIPermissionManager.PROMPT_ACTION;
 const ACCESS_SESSION = SpecialPowers.Ci.nsICookiePermission.ACCESS_SESSION;
+const ACCESS_ALLOW_FIRST_PARTY_ONLY = SpecialPowers.Ci.nsICookiePermission.ACCESS_ALLOW_FIRST_PARTY_ONLY;
+const ACCESS_LIMIT_THIRD_PARTY = SpecialPowers.Ci.nsICookiePermission.ACCESS_LIMIT_THIRD_PARTY;
 
 const EXPIRE_TIME = SpecialPowers.Ci.nsIPermissionManager.EXPIRE_TIME;
 // expire Setting:
 //     start                 expire time point
 //   ----|------------------------|-----------
 //       <------------------------>
 //                 PERIOD
 var start;
@@ -30,16 +32,18 @@ var gScript = SpecialPowers.loadChromeSc
 SimpleTest.requestFlakyTimeout("untriaged");
 
 function starttest(){
   SpecialPowers.addPermission("pPROMPT", PROMPT_ACTION, document);
   SpecialPowers.addPermission("pALLOW", ALLOW_ACTION, document);
   SpecialPowers.addPermission("pDENY", DENY_ACTION, document);
   SpecialPowers.addPermission("pREMOVE", ALLOW_ACTION, document);
   SpecialPowers.addPermission("pSESSION", ACCESS_SESSION, document);
+  SpecialPowers.addPermission("pFIRSTPARTY", ACCESS_ALLOW_FIRST_PARTY_ONLY, document);
+  SpecialPowers.addPermission("pTHIRDPARTY", ACCESS_LIMIT_THIRD_PARTY, document);
 
   setTimeout(test1, 0);
 }
 
 SimpleTest.waitForExplicitFinish();
 
 function test1() {
   if (!SpecialPowers.testPermission('pALLOW', ALLOW_ACTION, document)) {
@@ -52,83 +56,78 @@ function test1() {
     dump('/**** prompt not set ****/\n');
     setTimeout(test1, 0);
   } else if (!SpecialPowers.testPermission('pREMOVE', ALLOW_ACTION, document)) {
     dump('/**** remove not set ****/\n');
     setTimeout(test1, 0);
   } else if (!SpecialPowers.testPermission('pSESSION', ACCESS_SESSION, document)) {
     dump('/**** ACCESS_SESSION not set ****/\n');
     setTimeout(test1, 0);
+  } else if (!SpecialPowers.testPermission('pFIRSTPARTY', ACCESS_ALLOW_FIRST_PARTY_ONLY, document)) {
+    dump('/**** ACCESS_ALLOW_FIRST_PARTY_ONLY not set ****/\n');
+    setTimeout(test1, 0);
+  } else if (!SpecialPowers.testPermission('pTHIRDPARTY', ACCESS_LIMIT_THIRD_PARTY, document)) {
+    dump('/**** ACCESS_LIMIT_THIRD_PARTY not set ****/\n');
+    setTimeout(test1, 0);
   } else {
     test2();
   }
 }
 
 function test2() {
   ok(SpecialPowers.testPermission('pUNKNOWN', UNKNOWN_ACTION, document), 'pUNKNOWN value should have UNKOWN permission');
-  SpecialPowers.pushPermissions([
-    {'type': 'pUNKNOWN', 'allow': true, 'context': document},
-    {'type': 'pALLOW', 'allow': false, 'context': document},
-    {'type': 'pDENY', 'allow': true, 'context': document},
-    {'type': 'pPROMPT', 'allow': true, 'context': document},
-    {'type': 'pSESSION', 'allow': true, 'context': document},
-    {'type': 'pREMOVE', 'remove': true, 'context': document},
-  ], test3);
+  SpecialPowers.pushPermissions([{'type': 'pUNKNOWN', 'allow': true, 'context': document}, {'type': 'pALLOW', 'allow': false, 'context': document}, {'type': 'pDENY', 'allow': true, 'context': document}, {'type': 'pPROMPT', 'allow': true, 'context': document}, {'type': 'pSESSION', 'allow': true, 'context': document}, {'type': 'pFIRSTPARTY', 'allow': true, 'context': document}, {'type': 'pTHIRDPARTY', 'allow': true, 'context': document}, {'type': 'pREMOVE', 'remove': true, 'context': document}], test3);
 }
 
 function test3() {
   ok(SpecialPowers.testPermission('pUNKNOWN', ALLOW_ACTION, document), 'pUNKNOWN value should have ALLOW permission');
   ok(SpecialPowers.testPermission('pPROMPT', ALLOW_ACTION, document), 'pPROMPT value should have ALLOW permission');
   ok(SpecialPowers.testPermission('pALLOW', DENY_ACTION, document), 'pALLOW should have DENY permission');
   ok(SpecialPowers.testPermission('pDENY', ALLOW_ACTION, document), 'pDENY should have ALLOW permission');
   ok(SpecialPowers.testPermission('pREMOVE', UNKNOWN_ACTION, document), 'pREMOVE should have REMOVE permission');
   ok(SpecialPowers.testPermission('pSESSION', ALLOW_ACTION, document), 'pSESSION should have ALLOW permission');
+  ok(SpecialPowers.testPermission('pFIRSTPARTY', ALLOW_ACTION, document), 'pFIRSTPARTY should have ALLOW permission');
+  ok(SpecialPowers.testPermission('pTHIRDPARTY', ALLOW_ACTION, document), 'pTHIRDPARTY should have ALLOW permission');
 
   // only pPROMPT (last one) is different, the other stuff is just to see if it doesn't cause test failures
-  SpecialPowers.pushPermissions([
-    {'type': 'pUNKNOWN', 'allow': true, 'context': document},
-    {'type': 'pALLOW', 'allow': false, 'context': document},
-    {'type': 'pDENY', 'allow': true, 'context': document},
-    {'type': 'pPROMPT', 'allow': false, 'context': document},
-    {'type': 'pREMOVE', 'remove': true, 'context': document},
-  ], test3b);
+  SpecialPowers.pushPermissions([{'type': 'pUNKNOWN', 'allow': true, 'context': document}, {'type': 'pALLOW', 'allow': false, 'context': document}, {'type': 'pDENY', 'allow': true, 'context': document}, {'type': 'pPROMPT', 'allow': false, 'context': document}, {'type': 'pREMOVE', 'remove': true, 'context': document}], test3b);
 }
 
 function test3b() {
   ok(SpecialPowers.testPermission('pPROMPT', DENY_ACTION, document), 'pPROMPT value should have DENY permission');
-  SpecialPowers.pushPermissions([
-    {'type': 'pUNKNOWN', 'allow': DENY_ACTION, 'context': document},
-    {'type': 'pALLOW', 'allow': PROMPT_ACTION, 'context': document},
-    {'type': 'pDENY', 'allow': PROMPT_ACTION, 'context': document},
-    {'type': 'pPROMPT', 'allow': ALLOW_ACTION, 'context': document},
-  ], test4);
+  SpecialPowers.pushPermissions([{'type': 'pUNKNOWN', 'allow': DENY_ACTION, 'context': document}, {'type': 'pALLOW', 'allow': PROMPT_ACTION, 'context': document}, {'type': 'pDENY', 'allow': PROMPT_ACTION, 'context': document}, {'type': 'pPROMPT', 'allow': ALLOW_ACTION, 'context': document}], test4);
 }
 
 function test4() {
   ok(SpecialPowers.testPermission('pUNKNOWN', DENY_ACTION, document), 'pUNKNOWN value should have DENY permission');
   ok(SpecialPowers.testPermission('pPROMPT', ALLOW_ACTION, document), 'pPROMPT value should have ALLOW permission');
   ok(SpecialPowers.testPermission('pALLOW', PROMPT_ACTION, document), 'pALLOW should have PROMPT permission');
   ok(SpecialPowers.testPermission('pDENY', PROMPT_ACTION, document), 'pDENY should have PROMPT permission');
   //this should reset all the permissions to before all the pushPermissions calls
   SpecialPowers.flushPermissions(test5);
 }
 
+
 function test5() {
   ok(SpecialPowers.testPermission('pUNKNOWN', UNKNOWN_ACTION, document), 'pUNKNOWN should have UNKNOWN permission');
   ok(SpecialPowers.testPermission('pALLOW', ALLOW_ACTION, document), 'pALLOW should have ALLOW permission');
   ok(SpecialPowers.testPermission('pDENY', DENY_ACTION, document), 'pDENY should have DENY permission');
   ok(SpecialPowers.testPermission('pPROMPT', PROMPT_ACTION, document), 'pPROMPT should have PROMPT permission');
   ok(SpecialPowers.testPermission('pREMOVE', ALLOW_ACTION, document), 'pREMOVE should have ALLOW permission');
   ok(SpecialPowers.testPermission('pSESSION', ACCESS_SESSION, document), 'pSESSION should have ACCESS_SESSION permission');
+  ok(SpecialPowers.testPermission('pFIRSTPARTY', ACCESS_ALLOW_FIRST_PARTY_ONLY, document), 'pFIRSTPARTY should have ACCESS_ALLOW_FIRST_PARTY_ONLY permission');
+  ok(SpecialPowers.testPermission('pTHIRDPARTY', ACCESS_LIMIT_THIRD_PARTY, document), 'pTHIRDPARTY should have ACCESS_LIMIT_THIRD_PARTY permission');
 
   SpecialPowers.removePermission("pPROMPT", document);
   SpecialPowers.removePermission("pALLOW", document);
   SpecialPowers.removePermission("pDENY", document);
   SpecialPowers.removePermission("pREMOVE", document);
   SpecialPowers.removePermission("pSESSION", document);
+  SpecialPowers.removePermission("pFIRSTPARTY", document);
+  SpecialPowers.removePermission("pTHIRDPARTY", document);
 
   setTimeout(test6, 0);
 }
 
 function test6() {
   if (!SpecialPowers.testPermission('pALLOW', UNKNOWN_ACTION, document)) {
     dump('/**** allow still set ****/\n');
     setTimeout(test6, 0);
@@ -139,16 +138,22 @@ function test6() {
     dump('/**** prompt still set ****/\n');
     setTimeout(test6, 0);
   } else if (!SpecialPowers.testPermission('pREMOVE', UNKNOWN_ACTION, document)) {
     dump('/**** remove still set ****/\n');
     setTimeout(test6, 0);
   } else if (!SpecialPowers.testPermission('pSESSION', UNKNOWN_ACTION, document)) {
     dump('/**** pSESSION still set ****/\n');
     setTimeout(test6, 0);
+  } else if (!SpecialPowers.testPermission('pFIRSTPARTY', UNKNOWN_ACTION, document)) {
+    dump('/**** pFIRSTPARTY still set ****/\n');
+    setTimeout(test6, 0);
+  } else if (!SpecialPowers.testPermission('pTHIRDPARTY', UNKNOWN_ACTION, document)) {
+    dump('/**** pTHIRDPARTY still set ****/\n');
+    setTimeout(test6, 0);
   } else {
     test7();
   }
 }
 
 function test7() {
   afterPermissionChanged('pEXPIRE', 'deleted', test8);
   afterPermissionChanged('pEXPIRE', 'added', permissionPollingCheck);
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -797,16 +797,20 @@ SpecialPowersAPI.prototype = {
         if (this.testPermission(permission.type, Ci.nsIPermissionManager.ALLOW_ACTION, context)) {
           originalValue = Ci.nsIPermissionManager.ALLOW_ACTION;
         } else if (this.testPermission(permission.type, Ci.nsIPermissionManager.DENY_ACTION, context)) {
           originalValue = Ci.nsIPermissionManager.DENY_ACTION;
         } else if (this.testPermission(permission.type, Ci.nsIPermissionManager.PROMPT_ACTION, context)) {
           originalValue = Ci.nsIPermissionManager.PROMPT_ACTION;
         } else if (this.testPermission(permission.type, Ci.nsICookiePermission.ACCESS_SESSION, context)) {
           originalValue = Ci.nsICookiePermission.ACCESS_SESSION;
+        } else if (this.testPermission(permission.type, Ci.nsICookiePermission.ACCESS_ALLOW_FIRST_PARTY_ONLY, context)) {
+          originalValue = Ci.nsICookiePermission.ACCESS_ALLOW_FIRST_PARTY_ONLY;
+        } else if (this.testPermission(permission.type, Ci.nsICookiePermission.ACCESS_LIMIT_THIRD_PARTY, context)) {
+          originalValue = Ci.nsICookiePermission.ACCESS_LIMIT_THIRD_PARTY;
         }
 
         let principal = this._getPrincipalFromArg(context);
         if (principal.isSystemPrincipal) {
           continue;
         }
 
         let perm;