tor-browser

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

partitioned-estimate-usage-details-indexeddb.tentative.https.sub.html (7941B)


      1 <!DOCTYPE html>
      2 <meta name=help href="https://privacycg.github.io/storage-partitioning/">
      3 <title>Partitioned estimate() usage details for indexeddb test</title>
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 <script src="/common/utils.js"></script>
      7 <script src="./helpers.js"></script>
      8 <script src="../IndexedDB/resources/support-promises.js"></script>
      9 
     10 <body>
     11  <script>
     12    // Helper function to obtain IndexedDB usage data for this test window.
     13    const usageDetails = async () =>
     14      (await navigator.storage.estimate()).usageDetails.indexedDB || 0;
     15 
     16    // Helper function to create usage of the IndexedDB so that our test
     17    // can estimate that usage.
     18    const createSomeUsage = async (test) => {
     19      // We use 100KB here because db compaction usually happens every few MB
     20      // 100KB is large enough to avoid a false positive (small amounts of
     21      // metadata getting written for some random reason), and small enough to
     22      // avoid compaction with a reasonably high probability.
     23      const write_size = 1024 * 100;
     24      const object_store_name = token();
     25      const db_name = self.location.pathname;
     26 
     27      await indexedDB.deleteDatabase(db_name);
     28      const db = await createDB(db_name, object_store_name, test);
     29      const transaction = db.transaction(object_store_name, 'readwrite');
     30      const value_to_store = largeValue(write_size, Math.random() * 255);
     31      transaction.objectStore(object_store_name).add(value_to_store, 1);
     32 
     33      await transactionPromise(transaction);
     34      return db;
     35    }
     36 
     37    // Helper function for creating pathnames to test resources.
     38    const testPath = () => location.pathname.split("/").slice(0, -1).join("/");
     39 
     40    // Define our test variables.
     41    let alt_origin = "https://{{hosts[alt][]}}:{{ports[https][0]}}";
     42    let details = {};
     43 
     44    // Step 0: Construct an iframe. The content of this iframe includes
     45    // a script that will intercept and send postMessages back to this test
     46    // window.
     47    const iframe = document.createElement("iframe");
     48    iframe.src = `https://{{host}}:{{ports[https][0]}}${testPath()}/resources` +
     49      `/partitioned-estimate-usage-details-indexeddb-helper-frame.html`;
     50    document.body.appendChild(iframe);
     51 
     52    // Our test will perform the following steps to demonstrate the partitioning
     53    // of storage estimate usage details for IndexedDB. Some steps are in:
     54    // wpt/storage/resources/partitioned-estimate-usage-details-indexeddb-helper-frame.html
     55    // --------------------
     56    // (0) Construct a same-partition iframe on our test page. The content of
     57    // this iframe includes a script that will intercept and send postMessages
     58    // back to this test window.
     59    // (1) The same-partition iframe sends a postMessage notifying that the
     60    // iframe was constructed and we are ready to proceed with the test.
     61    // (2) Our test window intercepts this "iframe-is-ready" message.
     62    // (3) We create some IndexedDB usage and ensure that the IndexedDB usage
     63    // data reflects that increase in the test window.
     64    // (4) postMessage the same-partition iframe to obtain the IndexedDB usage
     65    // data from that frame.
     66    // (5) Our same-partition iframe intercepts the "get-details" postMessage,
     67    // obtains the IndexedDB usage details available to the iframe, and
     68    // postMessages the usage back to the test window.
     69    // (6) Our test window intercepts the "same-site" message from the same-
     70    // partition iframe containing usage data obtained there.
     71    // (7) We record the same-partition usage data. Then, we open a cross-
     72    // site window containing this test script. As a result, Step 0 will
     73    // be repeated, and an iframe will be created in that cross-site
     74    // window (referred to from here on out as the "cross-partition iframe").
     75    // Our cross-partition iframe will receive the same script as our same-
     76    // partition iframe. We then return early to avoid running another
     77    // instance of this test.
     78    // (8) Once created and loaded, our cross-partition iframe has an on-load
     79    // listener that is triggered. To check that our script is executing in the
     80    // cross-partition iframe (and not the same-partition iframe), we check that
     81    // our parent has a valid opener value.
     82    // (9) Then, our cross-partition iframe obtains the IndexedDB usage details
     83    // available to it and postMessages the usage back to the test window.
     84    // (10) Our test window intercepts the "cross-site" message from the cross-
     85    // partition iframe containing the usage data obtained there.
     86    // (11) We record the cross-partition usage data. Then we make our final
     87    // assertions.
     88    async_test(test => {
     89      // Since this script is loaded in two windows (our original test window
     90      // and the cross-site window opened later in the test), and we only want
     91      // to run the test body in the original test window, we return early
     92      // if our origin matches the "cross-site" window.
     93      if (location.origin === alt_origin)
     94        return;
     95 
     96      // Step 2: Our test window intercepts the "iframe-is-ready" message from
     97      // the same-partition iframe.
     98      let db;
     99      window.addEventListener("message", test.step_func(async event => {
    100        if (event.data === "iframe-is-ready") {
    101          // Step 3: We create some IndexedDB usage and ensure that the
    102          // IndexedDB usage data reflects that increase in the test window.
    103          details.init = await usageDetails();
    104          db = await createSomeUsage(test);
    105          details.after = await usageDetails();
    106          assert_greater_than(details.after, details.init);
    107 
    108          // Step 4: postMessage the same-partition iframe to request that
    109          // IndexedDB usage data be obtained and sent from that frame.
    110          iframe.contentWindow.postMessage("get-details", iframe.origin);
    111        }
    112      }));
    113 
    114      window.addEventListener("message", test.step_func(event => {
    115        // Step 6: Our test window intercepts the "same-site" message from the
    116        // same-partition iframe containing usage data obtained there.
    117        if (event.data.source === "same-site") {
    118          // Step 7: We record the same-partition data here. Then, we open a
    119          // cross-site window containing this test script. As a result,
    120          // Step 0 will be repeated, and a cross-partition iframe will be
    121          // created in that cross-site window. Our cross-partition iframe
    122          // will receive the same script as our same-partition iframe.
    123          // We return early to avoid running another instance of this test.
    124          details.same_site = event.data;
    125 
    126          const cross_site_window = window
    127            .open(`${alt_origin}${location.pathname}`, "", "noopener=false");
    128          test.add_cleanup(() => cross_site_window.close());
    129        }
    130        // Step 10: Our test window intercepts the "cross-site" message from
    131        // the cross-partition iframe containing the usage data obtained there.
    132        if (event.data.source === "cross-site") {
    133          // Step 11: We record the cross-partition data. Then we make our final
    134          // assertions.
    135          details.cross_site = event.data;
    136 
    137          // Some cleanup.
    138          test.step(async () => await db.close());
    139 
    140          // Usage data is correctly partitioned if:
    141          // a. Our cross-partition iframe recorded no IndexedDB usage data AND
    142          // b. The IndexedDB usage data for our test window (after the usage
    143          // was created) is equal to the IndexedDB usage data recorded by our
    144          // same-partition iframe.
    145          test.step(() => {
    146            assert_true(details.cross_site.init == 0, "Usage should be 0.");
    147            assert_equals(details.same_site.init, details.after);
    148          });
    149 
    150          test.done();
    151        }
    152      }));
    153    }, "Partitioned estimate() usage details for indexeddb test.");
    154  </script>
    155 </body>