tor-browser

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

navigation-timing-requestStart-responseStart.https.html (5542B)


      1 <!DOCTYPE html>
      2 <script src="/resources/testharness.js"></script>
      3 <script src="/resources/testharnessreport.js"></script>
      4 <script src="/common/dispatcher/dispatcher.js"></script>
      5 <script src="/common/utils.js"></script>
      6 <script src="../resources/utils.js"></script>
      7 <script src="resources/utils.sub.js"></script>
      8 <script src="/common/subset-tests-by-key.js"></script>
      9 
     10 <meta name="variant" content="?include=noPrefetch">
     11 <meta name="variant" content="?include=afterResponse">
     12 <meta name="variant" content="?include=waitingForResponse">
     13 <meta name="variant" content="?include=waitingForRedirect">
     14 
     15 <script>
     16 const setupProperties = {};
     17 if (shouldRunSubTest('waitingForResponse') || shouldRunSubTest('waitingForRedirect')) {
     18  // These tests rely on the relationship between these timeouts, the delays
     19  // on the server, and any vendor specific timeouts. Force a multiplier of 1,
     20  // since using setTimeout directly incurs the wrath of `wpt lint`.
     21  setupProperties.timeout_multiplier = 1;
     22 }
     23 setup(() => assertSpeculationRulesIsSupported(), setupProperties);
     24 
     25 subsetTestByKey('noPrefetch', promise_test, async t => {
     26  const agent = await spawnWindow(t);
     27  const landingUrl = agent.getExecutorURL({page: 2});
     28 
     29  await agent.navigate(landingUrl);
     30  assert_not_prefetched(await agent.getRequestHeaders(), `${landingUrl} should not be prefetched.`);
     31 
     32  // It's generally expected that events occur in this order:
     33  //   ... -> connectEnd --> requestStart --> responseStart --> ...
     34  const [entry] = await agent.execute_script(
     35      () => performance.getEntriesByType('navigation'));
     36  assert_less_than_equal(entry.connectEnd, entry.requestStart);
     37  assert_less_than_equal(entry.requestStart, entry.responseStart);
     38 }, "PerformanceNavigationTiming data should be in the correct order (no prefetch)");
     39 
     40 subsetTestByKey('afterResponse', promise_test, async t => {
     41  const agent = await spawnWindow(t);
     42  const landingUrl = agent.getExecutorURL({page: 2});
     43  await agent.forceSinglePrefetch(landingUrl);
     44 
     45  await agent.navigate(landingUrl);
     46  assert_prefetched(await agent.getRequestHeaders(), `${landingUrl} should have been prefetched.`);
     47 
     48  // Since the response should have started before the navigation, these should
     49  // all have the same value (i.e., the start of the fetch).
     50  const [entry] = await agent.execute_script(
     51      () => performance.getEntriesByType('navigation'));
     52  assert_equals(entry.connectEnd, entry.requestStart);
     53  assert_equals(entry.requestStart, entry.responseStart);
     54 }, "PerformanceNavigationTiming data should show 'instantaneous' events completed beforehand");
     55 
     56 subsetTestByKey('waitingForResponse', promise_test, async t => {
     57  const agent = await spawnWindow(t);
     58  const landingUrl = agent.getExecutorURL({executor: 'slow-executor.py', delay: '3', page: 2});
     59  await agent.forceSinglePrefetch(landingUrl, {}, /*wait_for_completion=*/false);
     60 
     61  // Chromium, at least, will give up the prefetch if the response head doesn't
     62  // come back within 1 second of navigation. So since the server will take
     63  // 3 seconds to respond, we wait 2.5 seconds before navigating, to ensure the
     64  // response comes back within about 0.5 seconds.
     65  await new Promise(resolve => t.step_timeout(resolve, 2_500));
     66 
     67  await agent.navigate(landingUrl);
     68  assert_prefetched(await agent.getRequestHeaders(), `${landingUrl} should have been prefetched.`);
     69 
     70  // Unlike the `afterResponse` test, we expect delays between `requestStart`
     71  // and `responseStart` here. If our timing was perfect and server round-trips
     72  // were instantaneous, that delay would be 0.5 seconds. To give ourselves a
     73  // bit of wiggle room, instead we assert that it's at least 0.1 seconds.
     74  const [entry] = await agent.execute_script(
     75      () => performance.getEntriesByType('navigation'));
     76  assert_less_than_equal(entry.connectEnd, entry.requestStart, "connectEnd must be before requestStart");
     77  assert_greater_than(entry.responseStart, entry.requestStart + 100, "responseStart must be > 100 ms after requestStart");
     78 }, "PerformanceNavigationTiming data should show noticeable TTFB if the response is slow");
     79 
     80 subsetTestByKey('waitingForRedirect', promise_test, async t => {
     81  const agent = await spawnWindow(t);
     82  const landingUrl = agent.getExecutorURL({page: 2});
     83  const slowRedirectUrl = new URL(`/common/slow-redirect.py?delay=3&location=${encodeURIComponent(landingUrl)}`, document.baseURI);
     84  await agent.forceSinglePrefetch(slowRedirectUrl, {}, /*wait_for_completion=*/false);
     85 
     86  // Considerations here are the same as for `waitingForResponse`.
     87  await new Promise(resolve => t.step_timeout(resolve, 2_500));
     88 
     89  await agent.navigate(slowRedirectUrl, {expectedDestinationUrl: landingUrl});
     90  assert_prefetched(await agent.getRequestHeaders(), `${landingUrl} should have been prefetched.`);
     91 
     92  // As in `waitingForResponse`, we expect at least 0.1 seconds TTFB. Unlike in
     93  // that test, the delta isn't captured by `requestStart` vs. `responseStart`,
     94  // because these stats only measure the final request/response pair, which is
     95  // not delayed.
     96  const [entry] = await agent.execute_script(
     97      () => performance.getEntriesByType('navigation'));
     98  assert_less_than_equal(entry.connectEnd, entry.requestStart, "connectEnd must be before requestStart");
     99  assert_less_than_equal(entry.requestStart, entry.responseStart, "requestStart must be before responseStart");
    100  assert_greater_than(entry.connectEnd, 100, "connectEnd must be > 100 ms");
    101 }, "PerformanceNavigationTiming data should show noticeable TTFB if the response is slow");
    102 </script>