tor-browser

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

partitioned.tentative.https.html (9330B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8"/>
      3 <title>Service Worker: Partitioned Service Workers</title>
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 <script src="resources/test-helpers.sub.js"></script>
      7 <script src="/common/get-host-info.sub.js"></script>
      8 <script src="resources/partitioned-utils.js"></script>
      9 
     10 <body>
     11  <!-- Debugging text for both test cases -->
     12  The 3p iframe's postMessage:
     13  <p id="iframe_response">No message received</p>
     14 
     15  The nested iframe's postMessage:
     16  <p id="nested_iframe_response">No message received</p>
     17 
     18 <script>
     19 promise_test(async t => {
     20  const script = './resources/partitioned-storage-sw.js'
     21  const scope = './resources/partitioned-'
     22 
     23  // Add service worker to this 1P context. wait_for_state() and
     24  // service_worker_unregister_and_register() are helper functions
     25  // for creating test ServiceWorkers defined in:
     26  // service-workers/service-worker/resources/test-helpers.sub.js
     27  const reg = await service_worker_unregister_and_register(t, script, scope);
     28  t.add_cleanup(() => reg.unregister());
     29  await wait_for_state(t, reg.installing, 'activated');
     30 
     31  // Registers the message listener with messageEventHandler(), defined in:
     32  // service-workers/service-worker/resources/partitioned-utils.js
     33  self.addEventListener('message', messageEventHandler);
     34 
     35  // Open an iframe that will create a promise within the SW.
     36  // Defined in service-workers/service-worker/resources/partitioned-storage-sw.js:
     37  // `waitUntilResolved.fakehtml`: URL scope that creates the promise.
     38  // `?From1pFrame`: query param that tracks which request the service worker is
     39  // handling.
     40  const wait_frame_url = new URL(
     41    './resources/partitioned-waitUntilResolved.fakehtml?From1pFrame',
     42    self.location);
     43 
     44  // Loads a child iframe with wait_frame_url as the content and returns
     45  // a promise for the data messaged from the loaded iframe.
     46  // loadAndReturnSwData() defined in:
     47  // service-workers/service-worker/resources/partitioned-utils.js:
     48  const wait_frame_1p_data = await loadAndReturnSwData(t, wait_frame_url,
     49                                                       'iframe');
     50  assert_equals(wait_frame_1p_data.source, 'From1pFrame',
     51    'The data for the 1p frame came from the wrong source');
     52 
     53  // Now create a 3p iframe that will try to resolve the SW in a 3p context.
     54  const third_party_iframe_url = new URL(
     55    './resources/partitioned-service-worker-third-party-iframe.html',
     56    get_host_info().HTTPS_ORIGIN + self.location.pathname);
     57 
     58  // loadAndReturnSwData() creates a HTTPS_NOTSAMESITE_ORIGIN or 3p `window`
     59  // element which embeds an iframe with the ServiceWorker and returns
     60  // a promise of the data messaged from that frame.
     61  const frame_3p_data = await loadAndReturnSwData(t, third_party_iframe_url, 'window');
     62  assert_equals(frame_3p_data.source, 'From3pFrame',
     63    'The data for the 3p frame came from the wrong source');
     64 
     65  // Print some debug info to the main frame.
     66  document.getElementById("iframe_response").innerHTML =
     67      "3p iframe's has_pending: " + frame_3p_data.has_pending + " source: " +
     68      frame_3p_data.source + ". ";
     69 
     70  // Now do the same for the 1p iframe.
     71  // Defined in service-workers/service-worker/resources/partitioned-storage-sw.js:
     72  // `resolve.fakehtml`: URL scope that resolves the promise.
     73  const resolve_frame_url = new URL(
     74    './resources/partitioned-resolve.fakehtml?From1pFrame', self.location);
     75 
     76  const frame_1p_data = await loadAndReturnSwData(t, resolve_frame_url,
     77                                                  'iframe');
     78  assert_equals(frame_1p_data.source, 'From1pFrame',
     79    'The data for the 1p frame came from the wrong source');
     80  // Both the 1p frames should have been serviced by the same service worker ID.
     81  // If this isn't the case then that means the SW could have been deactivated
     82  // which invalidates the test.
     83  assert_equals(frame_1p_data.ID, wait_frame_1p_data.ID,
     84    'The 1p frames were serviced by different service workers.');
     85 
     86  document.getElementById("iframe_response").innerHTML +=
     87    "1p iframe's has_pending: " + frame_1p_data.has_pending + " source: " +
     88    frame_1p_data.source;
     89 
     90  // If partitioning is working correctly then only the 1p iframe should see
     91  // (and resolve) its SW's promise. Additionally the two frames should see
     92  // different IDs.
     93  assert_true(frame_1p_data.has_pending,
     94      'The 1p iframe saw a pending promise in the service worker.');
     95  assert_false(frame_3p_data.has_pending,
     96    'The 3p iframe saw a pending promise in the service worker.');
     97  assert_not_equals(frame_1p_data.ID, frame_3p_data.ID,
     98    'The frames were serviced by the same service worker thread.');
     99 }, 'Services workers under different top-level sites are partitioned.');
    100 
    101 // Optional Test: Checking for partitioned ServiceWorkers in an A->B->A
    102 // (nested-iframes with cross-site ancestor) scenario.
    103 promise_test(async t => {
    104  const script = './resources/partitioned-storage-sw.js'
    105  const scope = './resources/partitioned-'
    106 
    107  // Add service worker to this 1P context. wait_for_state() and
    108  // service_worker_unregister_and_register() are helper functions
    109  // for creating test ServiceWorkers defined in:
    110  // service-workers/service-worker/resources/test-helpers.sub.js
    111  const reg = await service_worker_unregister_and_register(t, script, scope);
    112  t.add_cleanup(() => reg.unregister());
    113  await wait_for_state(t, reg.installing, 'activated');
    114 
    115  // Registers the message listener with messageEventHandler(), defined in:
    116  // service-workers/service-worker/resources/partitioned-utils.js
    117  self.addEventListener('message', messageEventHandler);
    118 
    119  // Open an iframe that will create a promise within the SW.
    120  // Defined in service-workers/service-worker/resources/partitioned-storage-sw.js:
    121  // `waitUntilResolved.fakehtml`: URL scope that creates the promise.
    122  // `?From1pFrame`: query param that tracks which request the service worker is
    123  // handling.
    124  const wait_frame_url = new URL(
    125    './resources/partitioned-waitUntilResolved.fakehtml?From1pFrame',
    126    self.location);
    127 
    128  // Load a child iframe with wait_frame_url as the content.
    129  // loadAndReturnSwData() defined in:
    130  // service-workers/service-worker/resources/partitioned-utils.js:
    131  const wait_frame_1p_data = await loadAndReturnSwData(t, wait_frame_url,
    132                                                       'iframe');
    133  assert_equals(wait_frame_1p_data.source, 'From1pFrame',
    134    'The data for the 1p frame came from the wrong source');
    135 
    136  // Now create a set of nested iframes in the configuration A1->B->A2
    137  // where B is cross-site and A2 is same-site to this top-level
    138  // site (A1). The innermost iframe of the nested iframes (A2) will
    139  // create an additional iframe to finally resolve the ServiceWorker.
    140  const nested_iframe_url = new URL(
    141    './resources/partitioned-service-worker-nested-iframe-parent.html',
    142    get_host_info().HTTPS_NOTSAMESITE_ORIGIN + self.location.pathname);
    143 
    144  // Create the nested iframes (which will in turn create the iframe
    145  // with the ServiceWorker) and await on receiving its data.
    146  const nested_iframe_data = await loadAndReturnSwData(t, nested_iframe_url, 'iframe');
    147  assert_equals(nested_iframe_data.source, 'FromNestedFrame',
    148    'The data for the nested iframe frame came from the wrong source');
    149 
    150  // Print some debug info to the main frame.
    151  document.getElementById("nested_iframe_response").innerHTML =
    152      "Nested iframe's has_pending: " + nested_iframe_data.has_pending + " source: " +
    153      nested_iframe_data.source + ". ";
    154 
    155  // Now do the same for the 1p iframe.
    156  // Defined in service-workers/service-worker/resources/partitioned-storage-sw.js:
    157  // `resolve.fakehtml`: URL scope that resolves the promise.
    158  const resolve_frame_url = new URL(
    159    './resources/partitioned-resolve.fakehtml?From1pFrame', self.location);
    160 
    161  const frame_1p_data = await loadAndReturnSwData(t, resolve_frame_url,
    162                                                  'iframe');
    163  assert_equals(frame_1p_data.source, 'From1pFrame',
    164    'The data for the 1p frame came from the wrong source');
    165  // Both the 1p frames should have been serviced by the same service worker ID.
    166  // If this isn't the case then that means the SW could have been deactivated
    167  // which invalidates the test.
    168  assert_equals(frame_1p_data.ID, wait_frame_1p_data.ID,
    169    'The 1p frames were serviced by different service workers.');
    170 
    171  document.getElementById("nested_iframe_response").innerHTML +=
    172    "1p iframe's has_pending: " + frame_1p_data.has_pending + " source: " +
    173    frame_1p_data.source;
    174 
    175  // If partitioning is working correctly then only the 1p iframe should see
    176  // (and resolve) its SW's promise. Additionally, the innermost iframe of
    177  // the nested iframes (A2 in the configuration A1->B->A2) should have a
    178  // different service worker ID than the 1p (A1) frame.
    179  assert_true(frame_1p_data.has_pending,
    180      'The 1p iframe saw a pending promise in the service worker.');
    181  assert_false(nested_iframe_data.has_pending,
    182    'The 3p iframe saw a pending promise in the service worker.');
    183  assert_not_equals(frame_1p_data.ID, nested_iframe_data.ID,
    184    'The frames were serviced by the same service worker thread.');
    185 }, 'Services workers with cross-site ancestors are partitioned.');
    186 
    187 </script>
    188 </body>