tor-browser

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

browser_chips_partition_cap_child.js (11109B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 const URL_EXAMPLE =
      6  "https://example.com/browser/netwerk/cookie/test/browser/cookie-set-dom.html";
      7 
      8 registerCleanupFunction(() => {
      9  Services.prefs.clearUserPref("network.cookie.cookieBehavior");
     10  Services.prefs.clearUserPref(
     11    "network.cookie.cookieBehavior.optInPartitioning"
     12  );
     13  Services.prefs.clearUserPref("network.cookie.chips.partitionLimitEnabled");
     14  Services.prefs.clearUserPref(
     15    "network.cookie.chips.partitionLimitByteCapacity"
     16  );
     17  Services.prefs.clearUserPref("network.cookie.CHIPS.enabled");
     18  Services.prefs.clearUserPref("network.cookie.chips.partitionLimitDryRun");
     19  Services.cookies.removeAll();
     20 });
     21 
     22 // enable chips and chips partition limit
     23 add_setup(async () => {
     24  Services.prefs.setIntPref("network.cookie.cookieBehavior", 5);
     25  Services.prefs.setBoolPref(
     26    "network.cookie.cookieBehavior.optInPartitioning",
     27    true
     28  );
     29  Services.prefs.setBoolPref("network.cookie.CHIPS.enabled", true);
     30  Services.prefs.setBoolPref(
     31    "network.cookie.chips.partitionLimitEnabled",
     32    true
     33  );
     34  Services.prefs.setBoolPref(
     35    "network.cookie.chips.partitionLimitDryRun",
     36    false
     37  );
     38 });
     39 
     40 const PATH = "/browser/netwerk/cookie/test/browser/";
     41 const PATH_EMPTY = PATH + "file_empty.html";
     42 
     43 const FIRST_PARTY = "example.com";
     44 const THIRD_PARTY = "example.org";
     45 
     46 const URL_DOCUMENT_FIRSTPARTY = "https://" + FIRST_PARTY + PATH_EMPTY;
     47 const URL_DOCUMENT_THIRDPARTY = "https://" + THIRD_PARTY + PATH_EMPTY;
     48 
     49 const COOKIE_PARTITIONED =
     50  "cookie=partitioned; Partitioned; Secure; SameSite=None;";
     51 const COOKIE_UNPARTITIONED = "cookie=unpartitioned; Secure; SameSite=None;";
     52 
     53 function createOriginAttributes(partitionKey) {
     54  return JSON.stringify({
     55    firstPartyDomain: "",
     56    geckoViewSessionContextId: "",
     57    inIsolatedMozBrowser: false,
     58    partitionKey,
     59    privateBrowsingId: 0,
     60    userContextId: 0,
     61  });
     62 }
     63 
     64 function createPartitionKey(url) {
     65  let uri = NetUtil.newURI(url);
     66  return `(${uri.scheme},${uri.host})`;
     67 }
     68 
     69 function createSameSiteForeignPartitionKey(url) {
     70  let uri = NetUtil.newURI(url);
     71  return `(${uri.scheme},${uri.host},f)`;
     72 }
     73 
     74 // OriginAttributes used to access partitioned and unpartitioned cookie jars
     75 // in all tests.
     76 const partitionedOAs = createOriginAttributes(
     77  createPartitionKey(URL_DOCUMENT_FIRSTPARTY)
     78 );
     79 const partitionedSameSiteForeignOAs = createOriginAttributes(
     80  createSameSiteForeignPartitionKey(URL_DOCUMENT_FIRSTPARTY)
     81 );
     82 const unpartitionedOAs = createOriginAttributes("");
     83 
     84 // cookie bytes >= 4013
     85 var staticCount = 0;
     86 function uniqueLargeCookie(partitioned) {
     87  ++staticCount;
     88  var cookie = "largecookie"
     89    .concat(staticCount)
     90    .concat("=")
     91    .concat("1234567890".repeat(400))
     92    .concat("; Secure; SameSite=None;");
     93  if (partitioned) {
     94    return cookie.concat("; Partitioned");
     95  }
     96  return cookie;
     97 }
     98 
     99 async function setCookieViaDomOnChild(browser, cookie) {
    100  await SpecialPowers.spawn(browser, [cookie], cookie => {
    101    content.document.cookie = cookie;
    102  });
    103 }
    104 
    105 // child-side document sets are byte-limited
    106 add_task(async function test_chips_limit_document_first_party_child() {
    107  const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
    108  const browser = gBrowser.getBrowserForTab(tab);
    109  await BrowserTestUtils.browserLoaded(browser);
    110 
    111  // Set partitioned and unpartitioned cookie from document child-side
    112  // 10240 * 1.2 -> 12288
    113  // fourth will cause purge (> 12288 Bytes)
    114  // and we will purge down to the soft maximum (quota) (10240 Bytes)
    115  await setCookieViaDomOnChild(browser, uniqueLargeCookie(true));
    116  await setCookieViaDomOnChild(browser, uniqueLargeCookie(true));
    117  await setCookieViaDomOnChild(browser, uniqueLargeCookie(true));
    118  await setCookieViaDomOnChild(browser, uniqueLargeCookie(true));
    119 
    120  await setCookieViaDomOnChild(browser, uniqueLargeCookie(false));
    121  await setCookieViaDomOnChild(browser, uniqueLargeCookie(false));
    122  await setCookieViaDomOnChild(browser, uniqueLargeCookie(false));
    123  await setCookieViaDomOnChild(browser, uniqueLargeCookie(false));
    124 
    125  // Get cookies from partitioned jar
    126  let partitioned = Services.cookies.getCookiesWithOriginAttributes(
    127    partitionedOAs,
    128    FIRST_PARTY
    129  );
    130 
    131  // Get cookies from unpartitioned jar
    132  let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
    133    unpartitionedOAs,
    134    FIRST_PARTY
    135  );
    136 
    137  // check that partitioned cookies are purged at maximum
    138  // check that unpartitioned cookies are not
    139  Assert.equal(partitioned.length, 2);
    140  Assert.equal(unpartitioned.length, 4);
    141 
    142  // Cleanup
    143  BrowserTestUtils.removeTab(tab);
    144  Services.cookies.removeAll();
    145 });
    146 
    147 // chips partitioned 3rd party cookies are subject to chips partition limit
    148 add_task(async function test_chips_limit_third_party() {
    149  const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
    150  const browser = gBrowser.getBrowserForTab(tab);
    151  await BrowserTestUtils.browserLoaded(browser);
    152 
    153  // Spawn document bc
    154  await SpecialPowers.spawn(browser, [URL_DOCUMENT_THIRDPARTY], async url => {
    155    let ifr = content.document.createElement("iframe");
    156    let loadPromise = ContentTaskUtils.waitForEvent(ifr, "load");
    157    ifr.src = url;
    158    content.document.body.appendChild(ifr);
    159    await loadPromise;
    160 
    161    // Spawn iframe bc
    162    await SpecialPowers.spawn(await ifr.browsingContext, [], async () => {
    163      function largeCookie(partitioned, index) {
    164        var cookie = "largecookie"
    165          .concat(index)
    166          .concat("=")
    167          .concat("1234567890".repeat(400))
    168          .concat("; Secure; SameSite=None;");
    169        if (partitioned) {
    170          return cookie.concat("; Partitioned");
    171        }
    172        return cookie;
    173      }
    174      content.document.cookie = largeCookie(true, 0);
    175      content.document.cookie = largeCookie(true, 1);
    176      content.document.cookie = largeCookie(true, 2);
    177      content.document.cookie = largeCookie(true, 3);
    178      content.document.cookie = largeCookie(false, 0);
    179      content.document.cookie = largeCookie(false, 1);
    180      content.document.cookie = largeCookie(false, 2);
    181      content.document.cookie = largeCookie(false, 3);
    182    });
    183  });
    184 
    185  // Get cookies from partitioned jar
    186  let partitioned = Services.cookies.getCookiesWithOriginAttributes(
    187    partitionedOAs,
    188    THIRD_PARTY
    189  );
    190  // Get cookies from unpartitioned jar
    191  let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
    192    unpartitionedOAs,
    193    THIRD_PARTY
    194  );
    195 
    196  // third party partitioned cookies are subject to the byte limit
    197  // while unpartitioned are blocked
    198  Assert.equal(partitioned.length, 2);
    199  Assert.equal(unpartitioned.length, 0);
    200 
    201  // Cleanup
    202  BrowserTestUtils.removeTab(tab);
    203  Services.cookies.removeAll();
    204 });
    205 
    206 // same-site foreign partitioned cookies are subject to the limit
    207 // This is ABA scenario: A contains B iframe, which contains A iframe
    208 add_task(async function test_chips_limit_samesite_foreign() {
    209  const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
    210  const browser = gBrowser.getBrowserForTab(tab);
    211  await BrowserTestUtils.browserLoaded(browser);
    212 
    213  // content process (top-level)
    214  await SpecialPowers.spawn(
    215    browser,
    216    [URL_DOCUMENT_THIRDPARTY, URL_DOCUMENT_FIRSTPARTY],
    217    async (url, urlInner) => {
    218      let ifr = content.document.createElement("iframe");
    219      let loadPromise = ContentTaskUtils.waitForEvent(ifr, "load");
    220      ifr.src = url;
    221      content.document.body.appendChild(ifr);
    222      await loadPromise;
    223 
    224      // Spawn iframe bc (third-party to top-level)
    225      await SpecialPowers.spawn(
    226        await ifr.browsingContext,
    227        [urlInner],
    228        async urlInner => {
    229          let ifr = content.document.createElement("iframe");
    230          let loadPromise = ContentTaskUtils.waitForEvent(ifr, "load");
    231          ifr.src = urlInner;
    232          content.document.body.appendChild(ifr);
    233          await loadPromise;
    234 
    235          // spawn inner iframe (same-site as top-level)
    236          await SpecialPowers.spawn(await ifr.browsingContext, [], async () => {
    237            function largeCookie(partitioned, index) {
    238              var cookie = "largecookie"
    239                .concat(index)
    240                .concat("=")
    241                .concat("1234567890".repeat(400))
    242                .concat("; Secure; SameSite=None;");
    243              if (partitioned) {
    244                return cookie.concat("; Partitioned");
    245              }
    246              return cookie;
    247            }
    248            content.document.cookie = largeCookie(true, 0);
    249            content.document.cookie = largeCookie(true, 1);
    250            content.document.cookie = largeCookie(true, 2);
    251            content.document.cookie = largeCookie(true, 3);
    252            content.document.cookie = largeCookie(false, 0);
    253            content.document.cookie = largeCookie(false, 1);
    254            content.document.cookie = largeCookie(false, 2);
    255            content.document.cookie = largeCookie(false, 3);
    256          });
    257        }
    258      );
    259    }
    260  );
    261 
    262  // Get cookies from partitioned jar
    263  let partitioned = Services.cookies.getCookiesWithOriginAttributes(
    264    partitionedSameSiteForeignOAs,
    265    FIRST_PARTY
    266  );
    267  // Get cookies from unpartitioned jar
    268  let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
    269    unpartitionedOAs, // no such thing as unpartitioned with foreign bit
    270    FIRST_PARTY
    271  );
    272 
    273  // same-site foreign partitioned cookies are subject to the byte limit
    274  // unpartitioned are blocked
    275  Assert.equal(partitioned.length, 2);
    276  Assert.equal(unpartitioned.length, 0);
    277 
    278  // Cleanup
    279  BrowserTestUtils.removeTab(tab);
    280  Services.cookies.removeAll();
    281 });
    282 
    283 // reducing the byte limit pref affects the amount of cookie bytes we trigger at
    284 add_task(async function test_chips_limit_change_byte_limit() {
    285  Services.prefs.setIntPref(
    286    "network.cookie.chips.partitionLimitByteCapacity",
    287    5120 // half the default
    288  );
    289  const tab = BrowserTestUtils.addTab(gBrowser, URL_DOCUMENT_FIRSTPARTY);
    290  const browser = gBrowser.getBrowserForTab(tab);
    291  await BrowserTestUtils.browserLoaded(browser);
    292 
    293  // two cookies of this size will exceed the new limit
    294  await setCookieViaDomOnChild(browser, uniqueLargeCookie(true));
    295  await setCookieViaDomOnChild(browser, uniqueLargeCookie(true));
    296  // unpartitioned will be unaffected
    297  await setCookieViaDomOnChild(browser, uniqueLargeCookie(false));
    298  await setCookieViaDomOnChild(browser, uniqueLargeCookie(false));
    299 
    300  // Get cookies from partitioned jar
    301  let partitioned = Services.cookies.getCookiesWithOriginAttributes(
    302    partitionedOAs,
    303    FIRST_PARTY
    304  );
    305 
    306  // Get cookies from unpartitioned jar
    307  let unpartitioned = Services.cookies.getCookiesWithOriginAttributes(
    308    unpartitionedOAs,
    309    FIRST_PARTY
    310  );
    311 
    312  // check that partitioned cookies are purged at maximum
    313  // check that unpartitioned cookies are not
    314  Assert.equal(partitioned.length, 1);
    315  Assert.equal(unpartitioned.length, 2);
    316 
    317  // Cleanup
    318  BrowserTestUtils.removeTab(tab);
    319  Services.cookies.removeAll();
    320 });