tor-browser

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

basic.sub.https.html (10346B)


      1 <!DOCTYPE html>
      2 <meta name="timeout" content="long">
      3 <script src="/resources/testharness.js"></script>
      4 <script src="/resources/testharnessreport.js"></script>
      5 <script src="/common/utils.js"></script>
      6 <script src="/common/dispatcher/dispatcher.js"></script>
      7 <script src="../../../resources/utils.js"></script>
      8 <script src="../../resources/utils.sub.js"></script>
      9 <script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
     10 
     11 <meta name="variant" content="?origin=same-site&sw=fetch-handler">
     12 <meta name="variant" content="?origin=same-site&sw=fetch-handler-to-fallback">
     13 <meta name="variant" content="?origin=same-site&sw=fetch-handler-modify-url">
     14 <meta name="variant" content="?origin=same-site&sw=fetch-handler-modify-referrer">
     15 <meta name="variant" content="?origin=same-site&sw=fetch-handler-navigation-preload">
     16 <meta name="variant" content="?origin=same-site&sw=no-fetch-handler">
     17 <meta name="variant" content="?origin=same-site&sw=no-controller">
     18 <meta name="variant" content="?origin=same-site&sw=race-fetch-handler">
     19 <meta name="variant" content="?origin=same-site&sw=race-fetch-handler-to-fallback">
     20 <meta name="variant" content="?origin=same-site&sw=race-fetch-handler-modify-url">
     21 
     22 <meta name="variant" content="?origin=same-site&sw=fetch-handler&clientId">
     23 <meta name="variant" content="?origin=same-site&sw=fetch-handler-to-fallback&clientId">
     24 <meta name="variant" content="?origin=same-site&sw=fetch-handler-modify-url&clientId">
     25 <meta name="variant" content="?origin=same-site&sw=fetch-handler-modify-referrer&clientId">
     26 <meta name="variant" content="?origin=same-site&sw=no-fetch-handler&clientId">
     27 <meta name="variant" content="?origin=same-site&sw=no-controller&clientId">
     28 
     29 <meta name="variant" content="?origin=cross-site&sw=fetch-handler">
     30 <meta name="variant" content="?origin=cross-site&sw=fetch-handler-to-fallback">
     31 <meta name="variant" content="?origin=cross-site&sw=no-fetch-handler">
     32 <meta name="variant" content="?origin=cross-site&sw=no-controller">
     33 
     34 <meta name="variant" content="?origin=cross-site&sw=fetch-handler&clientId">
     35 <meta name="variant" content="?origin=cross-site&sw=fetch-handler-to-fallback&clientId">
     36 <meta name="variant" content="?origin=cross-site&sw=no-fetch-handler&clientId">
     37 <meta name="variant" content="?origin=cross-site&sw=no-controller&clientId">
     38 
     39 <script>
     40 setup(() => assertSpeculationRulesIsSupported());
     41 
     42 // TODO(https://crbug.com/404573972): Rename "same-site" tests to
     43 // "same-origin", and add same-site cross-origin tests.
     44 const originOption = new URL(location.href).searchParams.get('origin');
     45 const originalSwOption = new URL(location.href).searchParams.get('sw');
     46 
     47 // Used when checking the resulting behavior.
     48 // In the following race-network cases, race network requests work in parallel
     49 // with fetch handlers and the checked observed behavior are the same with
     50 // non-race-network cases.
     51 let swOption = originalSwOption;
     52 if (originalSwOption === 'race-fetch-handler') {
     53  swOption = 'fetch-handler';
     54 }
     55 if (originalSwOption === 'race-fetch-handler-to-fallback') {
     56  swOption = 'fetch-handler-to-fallback';
     57 }
     58 
     59 promise_test(async t => {
     60  const hostname = originOption === 'cross-site' ? '{{hosts[alt][www]}}'
     61                                                 : undefined;
     62  const win = await spawnWindow(t, { protocol: 'https', hostname: hostname });
     63  const nextUrl = win.getExecutorURL({ executor: 'counting-executor.py', protocol: 'https', page: 2 });
     64  if (swOption === 'race-fetch-handler-modify-url') {
     65    // We set:
     66    // - For the race network request: 1.5 sec delay (here).
     67    // - For the network request from the fetch handler: 0.5 sec delay (in
     68    //   `basic-service-worker.js`).
     69    // So that:
     70    // - The fetch handler wins and the modified request is used for serving.
     71    // - The requests return responses after both of the requests reach the
     72    //   server and are recorded in the server-side request counts.
     73    nextUrl.searchParams.set('delay', '1500');
     74  }
     75 
     76  const swUrl = new URL('../../resources/basic-service-worker.js?sw=' + originalSwOption, location.href).href;
     77 
     78  // Register a SW not controlling any pages below, just to confirm such
     79  // unrelated SWs in the same-origin doesn't affect the behavior.
     80  const reg_unrelated = await service_worker_unregister_and_register(
     81      t, swUrl, nextUrl + '&unrelated');
     82  await wait_for_state(t, reg_unrelated.installing, 'activated');
     83 
     84  // Register a SW for `nextUrl`.
     85  let sw;
     86  if (swOption !== 'no-controller') {
     87    const reg = await service_worker_unregister_and_register(
     88        t, swUrl, nextUrl);
     89    sw = reg.installing;
     90    await wait_for_state(t, sw, 'activated');
     91  }
     92 
     93  // Start speculation rules prefetch and navigate to the URL.
     94  await win.forceSinglePrefetch(nextUrl);
     95 
     96  await win.navigate(nextUrl);
     97 
     98  const requestCount = await (await fetch(nextUrl + '&check')).json();
     99 
    100  const headers = await win.execute_script(() => {
    101    return requestHeaders;
    102  }, []);
    103 
    104  const controllerUrl = await win.execute_script(() => {
    105    return navigator.serviceWorker.controller?.scriptURL;
    106  }, []);
    107 
    108  if (swOption === 'no-controller') {
    109    assert_equals(controllerUrl, undefined);
    110  } else {
    111    // The navigated page should be controlled by the ServiceWorker,
    112    // regardless of whether prefetch is performed/used.
    113    assert_equals(controllerUrl, swUrl);
    114  }
    115 
    116  let interceptedRequests = [];
    117  if (sw) {
    118    const messagePromise = new Promise(resolve => {
    119      navigator.serviceWorker.addEventListener('message', (event) => {
    120        resolve(event.data);
    121      }, {once: true});
    122    });
    123    sw.postMessage('getInterceptedRequests');
    124    interceptedRequests = await messagePromise;
    125  }
    126 
    127  // Current Chromium's expected behavior:
    128  // prefetch works when
    129  // - there are no controlling service worker, or
    130  // - same-site prefetches with controlling service worker.
    131  if (swOption === 'no-controller' ||
    132      (originOption === 'same-site' &&
    133          (swOption === 'fetch-handler' ||
    134           swOption === 'fetch-handler-to-fallback' ||
    135           swOption === 'no-fetch-handler'))) {
    136    assert_prefetched(headers, "Prefetched result should be served.");
    137    assert_equals(requestCount.prefetch, 1,
    138        'a prefetch request should be sent to the server.');
    139    assert_equals(requestCount.nonPrefetch, 0,
    140        'non-prefetch requests should not be sent to the server.');
    141    assert_prefetched(headers, "Prefetched result should be served.");
    142 
    143    if (swOption === 'no-controller' || swOption === 'no-fetch-handler') {
    144      assert_equals(interceptedRequests.length, 0);
    145    } else {
    146      assert_equals(interceptedRequests.length, 1);
    147      assert_intercept_prefetch(interceptedRequests[0], nextUrl);
    148    }
    149  } else if (originOption === 'same-site' &&
    150      swOption === 'fetch-handler-navigation-preload') {
    151    // Check the behavior of `FetchEvent.preloadResponse` for prefetching
    152    // requests.
    153    // Here we allow >1 intercepted requests to check `preloadResponse`
    154    // behavior even if e.g. prefetched response isn't served and there is
    155    // second intercepted request (=non-prefetch navigation request).
    156    assert_greater_than_equal(interceptedRequests.length, 1);
    157    // The first intercepted request is a prefetch request.
    158    assert_intercept_prefetch(interceptedRequests[0], nextUrl);
    159    assert_equals(interceptedRequests[0].preloadResponse, 'resolved',
    160        'preloadResponse should be resolved');
    161 
    162    assert_served_by_navigation_preload(headers);
    163    assert_prefetched(headers, "Prefetched result should be served.");
    164    assert_equals(requestCount.prefetch, 1,
    165        'a prefetch request should be sent to the server.');
    166    assert_equals(requestCount.nonPrefetch, 0,
    167        'non-prefetch requests should not be sent to the server.');
    168  } else if (originOption === 'same-site' &&
    169             (swOption === 'fetch-handler-modify-url' ||
    170              swOption === 'fetch-handler-modify-referrer' ||
    171              swOption === 'race-fetch-handler-modify-url')) {
    172    // When the ServiceWorker modifies the prefetch request
    173    // (`fetch-handler-modify-*` cases below), still prefetch can work and be
    174    // served, but Sec-Purpose header is dropped
    175    // because it's a https://fetch.spec.whatwg.org/#forbidden-request-header
    176    assert_prefetched_without_sec_purpose(headers,
    177        "Prefetched result should be served without Sec-Purpose.");
    178    // `requestCount` checks the Sec-Purpose header so the prefetch request
    179    // without Sec-Purpose is counted as nonPrefetch here.
    180    assert_equals(requestCount.nonPrefetch, 1,
    181        'a prefetch request without Sec-Purpose should be sent to the server.');
    182    if (swOption === 'race-fetch-handler-modify-url') {
    183      // This racing network request is not used.
    184      assert_equals(requestCount.prefetch, 1,
    185        'Race network request should be sent to the server with Sec-Purpose.');
    186    } else {
    187      assert_equals(requestCount.prefetch, 0,
    188        'Other requests with Sec-Purpose should not be sent to the server.');
    189    }
    190 
    191    // Check the modified URL/referrer to check if the prefetched and
    192    // ServiceWorker-modified response is actually served.
    193    if (swOption === 'fetch-handler-modify-url') {
    194      assert_equals(
    195          await win.execute_script(() => { return requestUrl; }, []),
    196          nextUrl + '&intercepted=true',
    197          'URL should be modified by ServiceWorker');
    198    }
    199    if (swOption === 'fetch-handler-modify-referrer') {
    200      assert_equals(
    201          headers.referer,
    202          new URL('/intercepted', location.href).href,
    203          'Referrer should be modified by ServiceWorker');
    204    }
    205 
    206    assert_equals(interceptedRequests.length, 1);
    207    assert_intercept_prefetch(interceptedRequests[0], nextUrl);
    208  } else {
    209    assert_not_prefetched(headers, "Prefetched result should not be served.");
    210    assert_equals(requestCount.nonPrefetch, 1,
    211        'a non-prefetch request should be sent to the server.');
    212    assert_equals(requestCount.prefetch, 0,
    213        'prefetch requests should not be sent to the server.');
    214 
    215    if (swOption === 'no-fetch-handler') {
    216      assert_equals(interceptedRequests.length, 0);
    217    } else {
    218      assert_equals(interceptedRequests.length, 1);
    219      assert_intercept_non_prefetch(interceptedRequests[0], nextUrl);
    220    }
    221  }
    222 
    223 }, "Prefetch with ServiceWorker (" + originalSwOption + ")");
    224 </script>