tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

browser_cookie_chips.js (23841B)


      1 /* Any copyright is dedicated to the Public Domain.
      2   http://creativecommons.org/publicdomain/zero/1.0/ */
      3 
      4 "use strict";
      5 
      6 // The test is going to test different cookie behaviors. So, it will take a
      7 // longer time to complete.
      8 requestLongerTimeout(3);
      9 
     10 add_setup(() => {
     11  Services.prefs.setIntPref(
     12    "network.cookie.cookieBehavior",
     13    Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN
     14  );
     15  Services.prefs.setBoolPref(
     16    "network.cookieJarSettings.unblocked_for_testing",
     17    true
     18  );
     19  Services.prefs.setBoolPref(
     20    "network.cookie.cookieBehavior.optInPartitioning",
     21    true
     22  );
     23  Services.prefs.setBoolPref("network.cookie.CHIPS.enabled", true);
     24  Services.prefs.setBoolPref("dom.storage_access.enabled", true);
     25  Services.prefs.setBoolPref("dom.storage_access.prompt.testing", true);
     26  Services.cookies.removeAll();
     27  Services.perms.removeAll();
     28 });
     29 
     30 registerCleanupFunction(() => {
     31  Services.prefs.clearUserPref("network.cookie.cookieBehavior");
     32  Services.prefs.clearUserPref(
     33    "network.cookieJarSettings.unblocked_for_testing"
     34  );
     35  Services.prefs.clearUserPref(
     36    "network.cookie.cookieBehavior.optInPartitioning"
     37  );
     38  Services.prefs.clearUserPref("network.cookie.CHIPS.enabled");
     39  Services.prefs.clearUserPref("dom.storage_access.enabled");
     40  Services.prefs.clearUserPref("dom.storage_access.prompt.testing");
     41  Services.cookies.removeAll();
     42  Services.perms.removeAll();
     43 });
     44 
     45 const COOKIE_PARTITIONED =
     46  "cookie=partitioned; Partitioned; Secure; SameSite=None;";
     47 const COOKIE_UNPARTITIONED = "cookie=unpartitioned; Secure; SameSite=None;";
     48 
     49 const PATH = "/browser/netwerk/cookie/test/browser/";
     50 const PATH_EMPTY = PATH + "file_empty.html";
     51 const HTTP_COOKIE_SET = PATH + "chips.sjs?set";
     52 const HTTP_COOKIE_GET = PATH + "chips.sjs?get";
     53 
     54 const FIRST_PARTY = "example.com";
     55 const THIRD_PARTY = "example.org";
     56 
     57 const URL_DOCUMENT_FIRSTPARTY = "https://" + FIRST_PARTY + PATH_EMPTY;
     58 const URL_DOCUMENT_THIRDPARTY = "https://" + THIRD_PARTY + PATH_EMPTY;
     59 const FIRST_PARTY_DOMAIN = "https://" + FIRST_PARTY;
     60 const THIRD_PARTY_DOMAIN = "https://" + THIRD_PARTY;
     61 const URL_HTTP_FIRSTPARTY = FIRST_PARTY_DOMAIN + "/" + HTTP_COOKIE_SET;
     62 const URL_HTTP_THIRDPARTY = THIRD_PARTY_DOMAIN + "/" + HTTP_COOKIE_SET;
     63 
     64 function createOriginAttributes(partitionKey) {
     65  return JSON.stringify({
     66    firstPartyDomain: "",
     67    geckoViewSessionContextId: "",
     68    inIsolatedMozBrowser: false,
     69    partitionKey,
     70    privateBrowsingId: 0,
     71    userContextId: 0,
     72  });
     73 }
     74 
     75 function createPartitonKey(url) {
     76  let uri = NetUtil.newURI(url);
     77  return `(${uri.scheme},${uri.host})`;
     78 }
     79 
     80 // OriginAttributes used to access partitioned and unpartitioned cookie jars
     81 // in all tests.
     82 const partitionedOAs = createOriginAttributes(
     83  createPartitonKey(URL_DOCUMENT_FIRSTPARTY)
     84 );
     85 const unpartitionedOAs = createOriginAttributes("");
     86 
     87 // Set partitioned and unpartitioned cookie from first-party document.
     88 // CHIPS "Partitioned" cookie MUST always be stored in partitioned jar.
     89 // This uses CookieServiceChild internally. CookieService is not explicitly
     90 // tested since CHIPS are in the common function
     91 // CookieCommons::CreateCookieFromDocument().
     92 add_task(
     93  async function test_chips_store_partitioned_document_first_party_child() {
     94    const TEST_COOKIE_BEHAVIORS = [
     95      Ci.nsICookieService.BEHAVIOR_ACCEPT,
     96      Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN,
     97      Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER,
     98      Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
     99    ];
    100 
    101    for (let behavior of TEST_COOKIE_BEHAVIORS) {
    102      Services.prefs.setIntPref("network.cookie.cookieBehavior", behavior);
    103 
    104      const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
    105      const browser = gBrowser.getBrowserForTab(tab);
    106      await BrowserTestUtils.browserLoaded(browser);
    107 
    108      // Set partitioned and unpartitioned cookie from document child-side
    109      await SpecialPowers.spawn(
    110        browser,
    111        [COOKIE_PARTITIONED, COOKIE_UNPARTITIONED],
    112        (partitioned, unpartitioned) => {
    113          content.document.cookie = partitioned;
    114          content.document.cookie = unpartitioned;
    115        }
    116      );
    117 
    118      // Get cookies from partitioned jar
    119      let partitioned = Services.cookies.getCookiesWithOriginAttributes(
    120        partitionedOAs,
    121        FIRST_PARTY
    122      );
    123      // Get cookies from unpartitioned jar
    124      let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
    125        unpartitionedOAs,
    126        FIRST_PARTY
    127      );
    128 
    129      // Assert partitioned/unpartitioned cookie were stored in correct jars
    130      Assert.equal(partitioned.length, 1);
    131      Assert.equal(partitioned[0].value, "partitioned");
    132      Assert.equal(unpartitioned.length, 1);
    133      Assert.equal(unpartitioned[0].value, "unpartitioned");
    134 
    135      // Cleanup
    136      BrowserTestUtils.removeTab(tab);
    137      Services.cookies.removeAll();
    138    }
    139  }
    140 );
    141 
    142 // Set partitioned and unpartitioned cookie from third-party document with storage
    143 // access. CHIPS "Partitioned" cookie MUST always be stored in partitioned jar.
    144 // This uses CookieServiceChild internally.  CookieService is not explicitly
    145 // tested since CHIPS are in the common function
    146 // CookieCommons::CreateCookieFromDocument().
    147 add_task(
    148  async function test_chips_store_partitioned_document_third_party_storage_access_child() {
    149    // We exclude cookieBehavior BEHAVIOR_REJECT here because the StorageAccess
    150    // cannot be granted.
    151    const TEST_COOKIE_BEHAVIORS = [
    152      Ci.nsICookieService.BEHAVIOR_ACCEPT,
    153      Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER,
    154      Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
    155    ];
    156 
    157    for (let behavior of TEST_COOKIE_BEHAVIORS) {
    158      Services.prefs.setIntPref("network.cookie.cookieBehavior", behavior);
    159 
    160      const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
    161      const browser = gBrowser.getBrowserForTab(tab);
    162      await BrowserTestUtils.browserLoaded(browser);
    163 
    164      // Spawn document bc
    165      await SpecialPowers.spawn(
    166        browser,
    167        [URL_DOCUMENT_THIRDPARTY, COOKIE_PARTITIONED, COOKIE_UNPARTITIONED],
    168        async (url, partitioned, unpartitioned) => {
    169          let ifr = content.document.createElement("iframe");
    170          ifr.src = url;
    171          content.document.body.appendChild(ifr);
    172          await ContentTaskUtils.waitForEvent(ifr, "load");
    173 
    174          // Spawn iframe bc
    175          await SpecialPowers.spawn(
    176            await ifr.browsingContext,
    177            [partitioned, unpartitioned],
    178            async (partitioned, unpartitioned) => {
    179              SpecialPowers.wrap(
    180                content.document
    181              ).notifyUserGestureActivation();
    182              await SpecialPowers.addPermission(
    183                "storageAccessAPI",
    184                true,
    185                content.location.href
    186              );
    187              await SpecialPowers.wrap(content.document).requestStorageAccess();
    188 
    189              ok(
    190                await content.document.hasStorageAccess(),
    191                "example.org should have storageAccess"
    192              );
    193 
    194              content.document.cookie = partitioned;
    195              content.document.cookie = unpartitioned;
    196            }
    197          );
    198        }
    199      );
    200 
    201      // Get cookies from partitioned jar
    202      let partitioned = Services.cookies.getCookiesWithOriginAttributes(
    203        partitionedOAs,
    204        THIRD_PARTY
    205      );
    206      // Get cookies from unpartitioned jar
    207      let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
    208        unpartitionedOAs,
    209        THIRD_PARTY
    210      );
    211 
    212      // Assert partitioned/unpartitioned cookie were stored in correct jars
    213      Assert.equal(partitioned.length, 1);
    214      Assert.equal(partitioned[0].value, "partitioned");
    215      Assert.equal(unpartitioned.length, 1);
    216      Assert.equal(unpartitioned[0].value, "unpartitioned");
    217 
    218      // Cleanup
    219      BrowserTestUtils.removeTab(tab);
    220      Services.cookies.removeAll();
    221    }
    222  }
    223 );
    224 
    225 // Set partitioned and unpartitioned cookie from first-party http load.
    226 // CHIPS "Partitioned" cookie MUST always be stored in partitioned jar.
    227 // This calls CookieService::SetCookieStringFromHttp() internally.
    228 add_task(async function test_chips_store_partitioned_http_first_party_parent() {
    229  const TEST_COOKIE_BEHAVIORS = [
    230    Ci.nsICookieService.BEHAVIOR_ACCEPT,
    231    Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN,
    232    Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER,
    233    Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
    234  ];
    235 
    236  for (let behavior of TEST_COOKIE_BEHAVIORS) {
    237    Services.prefs.setIntPref("network.cookie.cookieBehavior", behavior);
    238 
    239    // Set partitioned and unpartitioned cookie from http parent side through
    240    // chips.sjs being loaded.
    241    const tab = BrowserTestUtils.addTab(gBrowser, URL_HTTP_FIRSTPARTY);
    242    const browser = gBrowser.getBrowserForTab(tab);
    243    await BrowserTestUtils.browserLoaded(browser);
    244 
    245    // Get cookies from partitioned jar
    246    let partitioned = Services.cookies.getCookiesWithOriginAttributes(
    247      partitionedOAs,
    248      FIRST_PARTY
    249    );
    250    // Get cookies from unpartitioned jar
    251    let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
    252      unpartitionedOAs,
    253      FIRST_PARTY
    254    );
    255 
    256    // Assert partitioned/unpartitioned cookie were stored in correct jars
    257    Assert.equal(partitioned.length, 1);
    258    Assert.equal(partitioned[0].value, "partitioned");
    259    Assert.equal(unpartitioned.length, 1);
    260    Assert.equal(unpartitioned[0].value, "unpartitioned");
    261 
    262    // Cleanup
    263    BrowserTestUtils.removeTab(tab);
    264    Services.cookies.removeAll();
    265  }
    266 });
    267 
    268 // Set partitioned and unpartitioned cookie from third-party http load.
    269 // CHIPS "Partitioned" cookie MUST always be stored in partitioned jar.
    270 // This calls CookieService::SetCookieStringFromHttp() internally.
    271 add_task(
    272  async function test_chips_store_partitioned_http_third_party_storage_access_parent() {
    273    // We exclude cookieBehavior BEHAVIOR_REJECT here because the StorageAccess
    274    // cannot be granted.
    275    const TEST_COOKIE_BEHAVIORS = [
    276      Ci.nsICookieService.BEHAVIOR_ACCEPT,
    277      Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER,
    278      Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
    279    ];
    280 
    281    for (let behavior of TEST_COOKIE_BEHAVIORS) {
    282      Services.prefs.setIntPref("network.cookie.cookieBehavior", behavior);
    283      const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
    284      const browser = gBrowser.getBrowserForTab(tab);
    285      await BrowserTestUtils.browserLoaded(browser);
    286 
    287      // Spawn document bc
    288      await SpecialPowers.spawn(
    289        browser,
    290        [THIRD_PARTY_DOMAIN, URL_HTTP_THIRDPARTY],
    291        async (url, fetchUrl) => {
    292          let ifr = content.document.createElement("iframe");
    293          ifr.src = url;
    294          content.document.body.appendChild(ifr);
    295          // Send http request with "set" query parameter, partitioned and
    296          // unpartitioned cookie will be set through http response from chips.sjs.
    297          await ContentTaskUtils.waitForEvent(ifr, "load");
    298 
    299          // Spawn iframe bc
    300          await SpecialPowers.spawn(
    301            await ifr.browsingContext,
    302            [fetchUrl],
    303            async url => {
    304              SpecialPowers.wrap(
    305                content.document
    306              ).notifyUserGestureActivation();
    307              await SpecialPowers.addPermission(
    308                "storageAccessAPI",
    309                true,
    310                content.location.href
    311              );
    312              await SpecialPowers.wrap(content.document).requestStorageAccess();
    313 
    314              ok(
    315                await content.document.hasStorageAccess(),
    316                "example.org should have storageAccess"
    317              );
    318 
    319              await content.fetch(url);
    320            }
    321          );
    322        }
    323      );
    324 
    325      // Get cookies from partitioned jar
    326      let partitioned = Services.cookies.getCookiesWithOriginAttributes(
    327        partitionedOAs,
    328        THIRD_PARTY
    329      );
    330      // Get cookies from unpartitioned jar
    331      let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
    332        unpartitionedOAs,
    333        THIRD_PARTY
    334      );
    335 
    336      // Assert partitioned/unpartitioned cookie were stored in correct jars
    337      Assert.equal(partitioned.length, 1);
    338      Assert.equal(partitioned[0].value, "partitioned");
    339      Assert.equal(unpartitioned.length, 1);
    340      Assert.equal(unpartitioned[0].value, "unpartitioned");
    341 
    342      // Cleanup
    343      BrowserTestUtils.removeTab(tab);
    344      Services.cookies.removeAll();
    345    }
    346  }
    347 );
    348 
    349 // TODO CHIPS - Tests for CookieServiceChild::SetCookieStringFromHttp() need
    350 // to be added. Since this is only checkable on onProxyConnectSuccess needs
    351 // proxy setup test harness. It is also called after onStartRequest() (Http)
    352 // but cookies are already set by the parents
    353 // CookieService::SetCookieStringFromHttp() call.
    354 
    355 // Get partitioned and unpartitioned cookies from document (child).
    356 // This uses CookieServiceChild internally.
    357 add_task(
    358  async function test_chips_send_partitioned_and_unpartitioned_document_child() {
    359    const TEST_COOKIE_BEHAVIORS = [
    360      Ci.nsICookieService.BEHAVIOR_ACCEPT,
    361      Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN,
    362      Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER,
    363      Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
    364    ];
    365 
    366    for (let behavior of TEST_COOKIE_BEHAVIORS) {
    367      Services.prefs.setIntPref("network.cookie.cookieBehavior", behavior);
    368 
    369      const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
    370      const browser = gBrowser.getBrowserForTab(tab);
    371      await BrowserTestUtils.browserLoaded(browser);
    372 
    373      // Spawn document bc
    374      await SpecialPowers.spawn(
    375        browser,
    376        [COOKIE_PARTITIONED, COOKIE_UNPARTITIONED],
    377        async (partitioned, unpartitioned) => {
    378          content.document.cookie = partitioned;
    379          content.document.cookie = unpartitioned;
    380 
    381          // Assert both unpartitioned and partitioned cookie are returned.
    382          let cookies = content.document.cookie;
    383          ok(
    384            cookies.includes("cookie=partitioned"),
    385            "Cookie from partitioned jar was sent."
    386          );
    387          ok(
    388            cookies.includes("cookie=unpartitioned"),
    389            "Cookie from unpartitioned jar was sent."
    390          );
    391        }
    392      );
    393 
    394      // Cleanup
    395      BrowserTestUtils.removeTab(tab);
    396      Services.cookies.removeAll();
    397    }
    398  }
    399 );
    400 
    401 // Get partitioned and unpartitioned cookies from document (child) after
    402 // storageAccess was granted. This calls CookieServiceChild::TrackCookieLoad()
    403 // internally to update child's cookies.
    404 add_task(
    405  async function test_chips_send_partitioned_and_unpartitioned_on_storage_access_child() {
    406    // We only test cookieBehavior 5 here because the test involves storage
    407    // access API. The other cookieBehaviors doesn't have the same behavior
    408    // on StorageAccess API, so the test doesn't apply.
    409    const TEST_COOKIE_BEHAVIORS = [
    410      Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
    411    ];
    412 
    413    for (let behavior of TEST_COOKIE_BEHAVIORS) {
    414      Services.prefs.setIntPref("network.cookie.cookieBehavior", behavior);
    415      // Set example.org first-party unpartitioned cookie
    416      await BrowserTestUtils.withNewTab(
    417        URL_DOCUMENT_THIRDPARTY,
    418        async browser => {
    419          info("Set a first party cookie via `document.cookie`.");
    420          await SpecialPowers.spawn(
    421            browser,
    422            [COOKIE_UNPARTITIONED],
    423            async unpartitioned => {
    424              content.document.cookie = unpartitioned;
    425              is(
    426                content.document.cookie,
    427                "cookie=unpartitioned",
    428                "Unpartitioned cookie was set."
    429              );
    430            }
    431          );
    432        }
    433      );
    434 
    435      // Assert cookie was set on parent cookie service for example.org.
    436      // Get cookies from unpartitioned jar
    437      let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
    438        unpartitionedOAs,
    439        THIRD_PARTY
    440      );
    441      Assert.equal(unpartitioned.length, 1);
    442      Assert.equal(unpartitioned[0].value, "unpartitioned");
    443 
    444      // Load example.com as first-party in tab
    445      const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
    446      const browser = gBrowser.getBrowserForTab(tab);
    447      await BrowserTestUtils.browserLoaded(browser);
    448 
    449      // Set third-party cookie from example.org iframe, get storageAccess and
    450      // check cookies.
    451      // Spawn document bc
    452      await SpecialPowers.spawn(
    453        browser,
    454        [URL_DOCUMENT_THIRDPARTY, COOKIE_PARTITIONED],
    455        async (url, partitioned) => {
    456          // Create third-party iframe
    457          let ifr = content.document.createElement("iframe");
    458          ifr.src = url;
    459          content.document.body.appendChild(ifr);
    460          await ContentTaskUtils.waitForEvent(ifr, "load");
    461 
    462          // Spawn iframe bc
    463          await SpecialPowers.spawn(
    464            await ifr.browsingContext,
    465            [partitioned],
    466            async partitioned => {
    467              ok(
    468                !(await content.document.hasStorageAccess()),
    469                "example.org should not have storageAccess initially."
    470              );
    471 
    472              // Set a partitioned third-party cookie and assert its the only.
    473              content.document.cookie = partitioned;
    474              is(
    475                content.document.cookie,
    476                "cookie=partitioned",
    477                "Partitioned cookie was set."
    478              );
    479 
    480              info("Simulate user activation.");
    481              SpecialPowers.wrap(
    482                content.document
    483              ).notifyUserGestureActivation();
    484 
    485              info("Request storage access.");
    486              await content.document.requestStorageAccess();
    487 
    488              ok(
    489                await content.document.hasStorageAccess(),
    490                "example.org should now have storageAccess."
    491              );
    492 
    493              // Assert both unpartitioned and partitioned cookie are returned.
    494              let cookies = content.document.cookie;
    495              ok(
    496                cookies.includes("cookie=partitioned"),
    497                "Cookie from partitioned jar was sent."
    498              );
    499              ok(
    500                cookies.includes("cookie=unpartitioned"),
    501                "Cookie from unpartitioned jar was sent."
    502              );
    503            }
    504          );
    505        }
    506      );
    507 
    508      // Cleanup
    509      BrowserTestUtils.removeTab(tab);
    510      Services.cookies.removeAll();
    511      Services.perms.removeAll();
    512    }
    513  }
    514 );
    515 
    516 // Set partitioned and unpartitioned cookies for URL_DOCUMENT_FIRSTPARTY, then
    517 // load URL again, assure cookies are correctly send to content child process.
    518 // This tests CookieServiceParent::TrackCookieLoad() internally.
    519 add_task(
    520  async function test_chips_send_partitioned_and_unpartitioned_document_parent() {
    521    const TEST_COOKIE_BEHAVIORS = [
    522      Ci.nsICookieService.BEHAVIOR_ACCEPT,
    523      Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN,
    524      Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER,
    525      Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
    526    ];
    527 
    528    for (let behavior of TEST_COOKIE_BEHAVIORS) {
    529      Services.prefs.setIntPref("network.cookie.cookieBehavior", behavior);
    530 
    531      // Set example.com first-party unpartitioned and partitioned cookie, then
    532      // close tab.
    533      await BrowserTestUtils.withNewTab(
    534        URL_DOCUMENT_FIRSTPARTY,
    535        async browser => {
    536          await SpecialPowers.spawn(
    537            browser,
    538            [COOKIE_PARTITIONED, COOKIE_UNPARTITIONED],
    539            async (partitioned, unpartitioned) => {
    540              content.document.cookie = unpartitioned;
    541              content.document.cookie = partitioned;
    542              let cookies = content.document.cookie;
    543              ok(
    544                cookies.includes("cookie=unpartitioned"),
    545                "Unpartitioned cookie was set."
    546              );
    547              ok(
    548                cookies.includes("cookie=partitioned"),
    549                "Partitioned cookie was set."
    550              );
    551            }
    552          );
    553        }
    554      );
    555 
    556      // Assert we have one partitioned and one unpartitioned cookie set.
    557      // Get cookies from partitioned jar
    558      let partitioned = Services.cookies.getCookiesWithOriginAttributes(
    559        partitionedOAs,
    560        FIRST_PARTY
    561      );
    562      // Get cookies from unpartitioned jar
    563      let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
    564        unpartitionedOAs,
    565        FIRST_PARTY
    566      );
    567      Assert.equal(partitioned.length, 1);
    568      Assert.equal(partitioned[0].value, "partitioned");
    569      Assert.equal(unpartitioned.length, 1);
    570      Assert.equal(unpartitioned[0].value, "unpartitioned");
    571 
    572      // Reload example.com and assert previously set cookies are correctly
    573      // send to content child document.
    574      await BrowserTestUtils.withNewTab(
    575        URL_DOCUMENT_FIRSTPARTY,
    576        async browser => {
    577          await SpecialPowers.spawn(browser, [], () => {
    578            let cookies = content.document.cookie;
    579            ok(
    580              cookies.includes("cookie=unpartitioned"),
    581              "Unpartitioned cookie was sent."
    582            );
    583            ok(
    584              cookies.includes("cookie=partitioned"),
    585              "Partitioned cookie was sent."
    586            );
    587          });
    588        }
    589      );
    590 
    591      // Cleanup
    592      Services.cookies.removeAll();
    593    }
    594  }
    595 );
    596 
    597 // Set partitioned and unpartitioned cookies for URL_DOCUMENT_FIRSTPARTY, then
    598 // send http request, assure cookies are correctly send in "Cookie" header.
    599 // This tests CookieService::GetCookieStringFromHttp() internally.
    600 add_task(
    601  async function test_chips_send_partitioned_and_unpartitioned_http_parent() {
    602    const TEST_COOKIE_BEHAVIORS = [
    603      Ci.nsICookieService.BEHAVIOR_ACCEPT,
    604      Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN,
    605      Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER,
    606      Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN,
    607    ];
    608 
    609    for (let behavior of TEST_COOKIE_BEHAVIORS) {
    610      Services.prefs.setIntPref("network.cookie.cookieBehavior", behavior);
    611 
    612      // Load empty document.
    613      let tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
    614      let browser = gBrowser.getBrowserForTab(tab);
    615      await BrowserTestUtils.browserLoaded(browser);
    616 
    617      await SpecialPowers.spawn(
    618        browser,
    619        [HTTP_COOKIE_SET, HTTP_COOKIE_GET],
    620        async (set, get) => {
    621          // Send http request with "set" query parameter, partitioned and
    622          // unpartitioned cookie will be set through http response.
    623          await content.fetch(set);
    624 
    625          // Assert cookies were set to document.
    626          let cookies = content.document.cookie;
    627          ok(
    628            cookies.includes("cookie=unpartitioned"),
    629            "Unpartitioned cookie was set to document."
    630          );
    631          ok(
    632            cookies.includes("cookie=partitioned"),
    633            "Partitioned cookie was set to document."
    634          );
    635 
    636          // Send http request with "get" query parameter, chips.sjs will return
    637          // the request "Cookie" header string.
    638          await content
    639            .fetch(get)
    640            .then(response => response.text())
    641            .then(requestCookies => {
    642              // Assert cookies were sent in http request.
    643              ok(
    644                requestCookies.includes("cookie=unpartitioned"),
    645                "Unpartitioned cookie was sent in http request."
    646              );
    647              ok(
    648                requestCookies.includes("cookie=partitioned"),
    649                "Partitioned cookie was sent in http request."
    650              );
    651            });
    652        }
    653      );
    654 
    655      // Cleanup
    656      BrowserTestUtils.removeTab(tab);
    657      Services.cookies.removeAll();
    658    }
    659  }
    660 );