tor-browser

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

claim-fetch.https.html (2898B)


      1 <!doctype html>
      2 <meta charset=utf-8>
      3 <title></title>
      4 <meta name="timeout" content="long">
      5 <script src="/resources/testharness.js"></script>
      6 <script src="/resources/testharnessreport.js"></script>
      7 <script src="resources/test-helpers.sub.js"></script>
      8 <body>
      9 <script>
     10 
     11 async function tryFetch(fetchFunc, path) {
     12  let response;
     13  try {
     14   response = await fetchFunc(path);
     15  } catch (err) {
     16    throw (`fetch() threw: ${err}`);
     17  }
     18 
     19  let responseText;
     20  try {
     21   responseText = await response.text();
     22  } catch (err) {
     23   throw (`text() threw: ${err}`);
     24  }
     25 
     26  return responseText;
     27 }
     28 
     29 promise_test(async function(t) {
     30  const scope = 'resources/';
     31  const script = 'resources/claim-worker.js';
     32  const resource = 'simple.txt';
     33 
     34  // Create the test frame.
     35  const frame = await with_iframe('resources/blank.html');
     36  t.add_cleanup(() => frame.remove());
     37 
     38  // Check the controller and test with fetch.
     39  assert_equals(frame.contentWindow.navigator.controller, undefined,
     40                'Should have no controller.');
     41  let response;
     42  try {
     43    response = await tryFetch(frame.contentWindow.fetch, resource);
     44  } catch (err) {
     45    assert_unreached(`uncontrolled fetch failed: ${err}`);
     46  }
     47  assert_equals(response, 'a simple text file\n',
     48                'fetch() should not be intercepted.');
     49 
     50  // Register a service worker.
     51  const registration =
     52    await service_worker_unregister_and_register(t, script, scope);
     53  t.add_cleanup(() => registration.unregister());
     54  const worker = registration.installing;
     55  await wait_for_state(t, worker, 'activated');
     56 
     57  // Register a controllerchange event to wait until the controller is updated
     58  // and check if the frame is controlled by a service worker.
     59  const controllerChanged = new Promise((resolve) => {
     60    frame.contentWindow.navigator.serviceWorker.oncontrollerchange = () => {
     61      resolve(frame.contentWindow.navigator.serviceWorker.controller);
     62    };
     63  });
     64 
     65  // Tell the service worker to claim the iframe.
     66  const sawMessage = new Promise((resolve) => {
     67    const channel = new MessageChannel();
     68    channel.port1.onmessage = t.step_func((event) => {
     69      resolve(event.data);
     70    });
     71    worker.postMessage({port: channel.port2}, [channel.port2]);
     72  });
     73  const data = await sawMessage;
     74  assert_equals(data, 'PASS', 'Worker call to claim() should fulfill.');
     75 
     76  // Check if the controller is updated after claim() and test with fetch.
     77  const controller = await controllerChanged;
     78  assert_true(controller instanceof frame.contentWindow.ServiceWorker,
     79              'iframe should be controlled.');
     80  try {
     81    response = await tryFetch(frame.contentWindow.fetch, resource);
     82  } catch (err) {
     83    assert_unreached(`controlled fetch failed: ${err}`);
     84  }
     85  assert_equals(response, 'Intercepted!',
     86                'fetch() should be intercepted.');
     87 }, 'fetch() should be intercepted after the client is claimed.');
     88 
     89 </script>
     90 </body>