tor-browser

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

storage-partitioning.https.html (6437B)


      1 <!DOCTYPE html>
      2 <title>Test storage partitioning in fenced frames</title>
      3 <meta name="timeout" content="long">
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 <script src="/common/utils.js"></script>
      7 <script src="/common/dispatcher/dispatcher.js"></script>
      8 <script src="resources/utils.js"></script>
      9 
     10 <body>
     11 <script>
     12 
     13 // `getter(key)` : reads the value of `key`, null if not set
     14 // `setter(key, value)`: sets `key` to `value`
     15 async function runTest(getter, setter) {
     16  const key = "key";
     17  const outer_value = "outer";
     18  const inner_value = "inner";
     19 
     20  // Set the value in the top-level frame, and check that it worked.
     21  await setter(key, outer_value);
     22  assert_equals(await getter(key), outer_value,
     23      "Stored the value in the top-level frame.");
     24 
     25  // Attach a fenced frame.
     26  const frame = attachFencedFrameContext();
     27 
     28  // Check that the outer value isn't visible.
     29  const inner_before_set = await frame.execute(getter, [key]);
     30  assert_equals(inner_before_set, null,
     31      "The outer value isn't visible inside the fenced frame.");
     32 
     33  // Set the value inside the fenced frame, and check that it worked.
     34  await frame.execute(setter, [key, inner_value]);
     35  const inner_after_set = await frame.execute(getter, [key]);
     36  assert_equals(inner_after_set, inner_value,
     37      "Stored the value in the fenced frame.");
     38 
     39  // Check that the inner value isn't visible in the top-level frame.
     40  assert_equals(await getter(key), outer_value,
     41      "The inner value isn't visible outside the fenced frame.");
     42 
     43  // Perform an embedder-initiated navigation that will fail.
     44  const original_config = frame.config;
     45  frame.config = new FencedFrameConfig("resources/response-204.py");
     46  await step_timeout(() => {}, 1000);
     47 
     48  // Check that the failed navigation didn't change the storage partition.
     49  // (The partition nonce should be reinitialized on navigation commit.)
     50  const inner_after_failure = await frame.execute(getter, [key]);
     51  assert_equals(inner_after_failure, inner_value,
     52      "The inner value is still present after the failed navigation.");
     53 
     54  // Refresh the fenced frame from within.
     55  await frame.execute(() => {
     56    window.executor.suspend(() => { location.href = location.href; });
     57  });
     58 
     59  // Check that the storage partition is the same.
     60  const inner_after_inner_refresh = await frame.execute(getter, [key]);
     61  assert_equals(inner_after_inner_refresh, inner_value,
     62      "The inner value is the same after a fencedframe-initiated refresh.");
     63 
     64  // Refresh the fenced frame from the embedder.
     65  await frame.execute(() => window.executor.suspend(() => {}));
     66  frame.element.config = original_config;
     67 
     68  // Check that there is a blank slate.
     69  const inner_after_embedder_refresh = await frame.execute(getter, [key]);
     70  assert_equals(inner_after_embedder_refresh, null,
     71      "The inner value is gone after an embedder-initiated refresh.");
     72 }
     73 
     74 promise_test(async () => {
     75  return runTest(
     76    (_) => { return document.cookie || null; },
     77    (_, value) => { document.cookie = value;}
     78  );
     79 }, 'document.cookie');
     80 
     81 promise_test(async () => {
     82  return runTest(
     83    (key) => { return localStorage.getItem(key); },
     84    (key, value) => { return localStorage.setItem(key, value); }
     85  );
     86 }, 'localStorage');
     87 
     88 promise_test(async () => {
     89  return runTest(
     90    (key) => { return sessionStorage.getItem(key); },
     91    (key, value) => { return sessionStorage.setItem(key, value); }
     92  );
     93 }, 'sessionStorage');
     94 
     95 promise_test(async () => {
     96  return runTest(
     97    async (key) => {
     98      const newCache = await caches.open('test-cache');
     99      const response = await newCache.match(key);
    100      if (!response) {
    101        return null;
    102      }
    103      return response.text();
    104    },
    105    async (key, value) => {
    106      const newCache = await caches.open('test-cache');
    107      return newCache.put(key, new Response(value));
    108    }
    109  );
    110 }, 'Cache API');
    111 
    112 promise_test(async () => {
    113  return runTest(
    114    async (key) => {
    115      const root = await navigator.storage.getDirectory();
    116      const draftHandle = await root.getFileHandle(key, { create: true });
    117      const file = await draftHandle.getFile();
    118      const text = await file.text();
    119      return text || null;
    120    },
    121    async (key, value) => {
    122      const root = await navigator.storage.getDirectory();
    123      const draftHandle = await root.getFileHandle(key, { create: true });
    124      const writable = await draftHandle.createWritable()
    125      await writable.truncate(0);
    126      await writable.write(value);
    127      await writable.close();
    128    }
    129  );
    130 }, 'File System Access API');
    131 
    132 promise_test(async () => {
    133  return runTest(
    134    async (key) => {
    135      const openRequest = indexedDB.open('test-db', 2);
    136      const db = await new Promise((resolve) => {
    137        openRequest.onsuccess = (event) => {
    138          resolve(event.target.result);
    139        };
    140        openRequest.onupgradeneeded = (event) => {
    141          const db = event.target.result;
    142          const objStore = db.createObjectStore('test-tbl', {keyPath: 'key'});
    143          objStore.transaction.oncomplete = (event) => {
    144            resolve(db);
    145          };
    146        };
    147      });
    148      const readRequest = db.transaction(['test-tbl'])
    149                            .objectStore('test-tbl')
    150                            .get(key);
    151      return new Promise((resolve) => {
    152        readRequest.onsuccess = (event) => {
    153          if (!event.target.result) {
    154            resolve(null);
    155          } else {
    156            resolve(event.target.result['value']);
    157          }
    158        };
    159      });
    160    },
    161    async (key, value) => {
    162      const openRequest = indexedDB.open('test-db', 2);
    163      const db = await new Promise((resolve) => {
    164        openRequest.onsuccess = (event) => {
    165          resolve(event.target.result);
    166        };
    167        openRequest.onupgradeneeded = (event) => {
    168          const db = event.target.result;
    169          const objStore = db.createObjectStore('test-tbl', {keyPath: 'key'});
    170          objStore.transaction.oncomplete = (event) => {
    171            resolve(db);
    172          };
    173        };
    174      });
    175      const writeRequest = db.transaction(['test-tbl'], 'readwrite')
    176                             .objectStore('test-tbl')
    177                             .add({'key': key, 'value': value});
    178      return new Promise((resolve) => {
    179        writeRequest.onsuccess = (event) => {
    180          resolve(event.target.result);
    181        };
    182      });
    183    }
    184  );
    185 }, 'IndexedDB');
    186 
    187 </script>
    188 </body>