tor-browser

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

static-router-resource-timing.https.html (14914B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <title>
      4  Static Router: timing information should be shown when used.
      5 </title>
      6 <script src="/common/get-host-info.sub.js"></script>
      7 <script src="/resources/testharness.js"></script>
      8 <script src="/resources/testharnessreport.js"></script>
      9 <script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
     10 <script src="/service-workers/service-worker/resources/static-router-helpers.sub.js"></script>
     11 <body>
     12 <script>
     13 const ROUTER_RULE_KEY = 'condition-urlpattern-constructed-source-network';
     14 const ROUTER_RULE_KEY_URLPATTERN_CACHE =
     15  'condition-urlpattern-string-source-cache';
     16 const ROUTER_RULE_KEY_REQUEST_CACHE = 'condition-request-navigate-source-cache';
     17 const ROUTER_RULE_KEY_URL_PATTERN_CONSTRUCTED_MATCH_ALL_CACHE =
     18  'condition-urlpattern-constructed-match-all-source-cache';
     19 const ROUTER_RULE_KEY_REQUEST_FETCH = 'condition-urlpattern-string-source-fetch-event';
     20 const REGISTERED_ROUTE = '/service-workers/service-worker/resources/direct.txt';
     21 const CACHED_ROUTE = '/service-workers/service-worker/resources/cache.txt';
     22 const NON_REGISTERED_ROUTE = '/service-workers/service-worker/resources/simple.html';
     23 
     24 const RACE_ROUTER_KEY =
     25  'condition-urlpattern-string-source-race-network-and-fetch-handler';
     26 const RACE_SW_SRC = '/service-workers/service-worker/resources/static-router-race-network-and-fetch-handler-sw.js';
     27 const RACE_ROUTE = '/service-workers/service-worker/resources/direct.py';
     28 
     29 const host_info = get_host_info();
     30 
     31 function resourceUrl(resource) {
     32  return `${host_info['HTTPS_ORIGIN']}${resource}`;
     33 }
     34 
     35 // Verify existance of a PerformanceEntry and the order between the timings of
     36 // ServiceWorker Static routing API.
     37 //
     38 // |options| has these properties:
     39 // performance: Performance interface to verify existance of the entry.
     40 // url: the URL of resource
     41 // description: the description passed to each assertion.
     42 // matched_source: the expected matched source of router evaluation.
     43 // actual_source: the expected actual source used to get the resource.
     44 function test_resource_timing(options) {
     45  const description = options.description;
     46  const entryList = options.performance.getEntriesByName(resourceUrl(options.url));
     47  assert_equals(entryList.length, 1, description);
     48  const entry = entryList[0];
     49 
     50  assert_equals(entry.workerMatchedSourceType, options.matched_source_type, description);
     51  assert_equals(entry.workerFinalSourceType, options.final_source_type, description);
     52 
     53  assert_greater_than(entry.workerRouterEvaluationStart, 0, description);
     54  switch (entry.matchedSouceType) {
     55    case 'network':
     56      assert_equals(entry.workerStart, 0, description);
     57      assert_equals(entry.workerCacheLookupStart, 0, description);
     58      assert_less_than_equal(entry.workerRouterEvaluationStart, entry.fetchStart, description);
     59      assert_greater_than(entry.encodedBodySize, 0, description);
     60      break;
     61    case 'cache':
     62      assert_equals(entry.workerStart, 0, description);
     63      assert_greater_than_equal(entry.workerCacheLookupStart, entry.workerRouterEvaluationStart, description);
     64      assert_greater_than(entry.encodedBodySize, 0, description);
     65      if (entry.workerFinalSourceType === 'cache') {
     66        assert_equals(entry.fetchStart, entry.responseStart, description);
     67        assert_less_than_equal(entry.workerCacheLookupStart, entry.responseStart, description);
     68        assert_equals(entry.deliveryType, 'cache-storage', description);
     69      } else {
     70        assert_less_than_equal(entry.workerCacheLookupStart, entry.fetchStart, description);
     71      }
     72      break;
     73    case 'race-network-and-fetch-handler':
     74      assert_equals(entry.workerCacheLookupStart, 0, description);
     75      assert_greater_than(entry.encodedBodySize, 0, description);
     76      if (entry.workerFinalSourceType === 'network') {
     77        assert_equals(entry.workerStart, 0, description);
     78        assert_less_than_equal(entry.workerRouterEvaluationStart, entry.fetchStart, description);
     79      } else {
     80        assert_greater_than_equal(entry.workerStart, entry.workerRouterEvaluationStart, description);
     81        assert_greater_than_equal(entry.fetchStart, entry.workerStart, description);
     82      }
     83      break;
     84    case 'fetch-event':
     85      assert_greater_than(entry.encodedBodySize, 0, description);
     86      break;
     87    case '':  // i.e. no matching rules
     88      assert_equals(entry.workerCacheLookupStart, 0, description);
     89      assert_greater_than_equal(entry.workerStart, entry.workerRouterEvaluationStart, description);
     90      assert_greater_than_equal(entry.fetchStart, entry.workerStart, description);
     91      break;
     92  }
     93 }
     94 
     95 promise_test(async t => {
     96  const worker = await registerAndActivate(t, ROUTER_RULE_KEY_REQUEST_FETCH);
     97  const rnd = randomString();
     98  const url = `${NON_REGISTERED_ROUTE}?nonce=${rnd}`;
     99  const iframe = await createIframe(t, url);
    100  const {errors, requests} = await get_info_from_worker(worker);
    101 
    102  assert_equals(errors.length, 0);
    103  assert_equals(requests.length, 1);
    104  assert_equals(iframe.contentWindow.document.body.innerText, rnd);
    105 
    106  test_resource_timing({
    107    performance: iframe.contentWindow.performance,
    108    url: url,
    109    matched_source_type: 'fetch-event',
    110    final_source_type: 'fetch-event',
    111    description: "fetch-event as source on main resource"
    112  });
    113 }, 'Main resource matched the rule with fetch-event source');
    114 
    115 iframeTest(REGISTERED_ROUTE, ROUTER_RULE_KEY, async (t, iwin, worker) => {
    116  const {requests} = await get_info_from_worker(worker);
    117  assert_equals(requests.length, 0);
    118  assert_equals(iwin.document.body.innerText, "Network\n");
    119  test_resource_timing({
    120    performance: iwin.performance,
    121    url: REGISTERED_ROUTE,
    122    matched_source_type: 'network',
    123    final_source_type: 'network',
    124    description: "network as source on main resource"
    125  });
    126 }, 'Main resource load matched with the condition and resource timing');
    127 
    128 iframeTest(NON_REGISTERED_ROUTE, ROUTER_RULE_KEY, async (t, iwin, worker) => {
    129  const {requests} = await get_info_from_worker(worker);
    130  assert_equals(requests.length, 1);
    131  assert_equals(
    132    requests[0].url,
    133    resourceUrl(NON_REGISTERED_ROUTE));
    134  assert_equals(requests[0].mode, 'navigate');
    135  test_resource_timing({
    136    performance: iwin.performance,
    137    url: NON_REGISTERED_ROUTE,
    138    matched_source_type: '',
    139    final_source_type: '',
    140    description: "no rule matched on main resource"
    141  });
    142 }, 'Main resource load not matched with the condition and resource timing');
    143 
    144 iframeTest(CACHED_ROUTE, ROUTER_RULE_KEY_URLPATTERN_CACHE, async (t, iwin, worker) => {
    145  const {requests} = await get_info_from_worker(worker);
    146  assert_equals(requests.length, 0);
    147  assert_equals(iwin.document.body.innerText, "From cache");
    148  test_resource_timing({
    149    performance: iwin.performance,
    150    url: CACHED_ROUTE,
    151    matched_source_type: 'cache',
    152    final_source_type: 'cache',
    153    description: "cache as source on main resource and cache hit"
    154  });
    155 }, 'Main resource load matched with the cache source and resource timing');
    156 
    157 iframeTest(NON_REGISTERED_ROUTE, ROUTER_RULE_KEY_REQUEST_CACHE, async (t, iwin, worker) => {
    158  const {requests} = await get_info_from_worker(worker);
    159  // When the request matched to the rule with the "cache" source but failed to
    160  // get the cache entry, the fetch handler is not involved and the network
    161  // fallback is triggered instead.
    162  assert_equals(requests.length, 0);
    163  assert_equals(iwin.document.body.innerText, "Here's a simple html file.");
    164  test_resource_timing({
    165    performance: iwin.performance,
    166    url: NON_REGISTERED_ROUTE,
    167    matched_source_type: 'cache',
    168    final_source_type: 'network',
    169    description: "cache as source on main resource and cache miss, fallback to network"
    170  });
    171 }, 'Main resource fallback to the network when there is no cache entry and resource timing');
    172 
    173 // Subresource
    174 iframeTest(NON_REGISTERED_ROUTE, ROUTER_RULE_KEY_REQUEST_FETCH, async (t, iwin, worker) => {
    175  const rnd = randomString();
    176  const subresource = `?nonce=${rnd}`;
    177  const response = await iwin.fetch(subresource);
    178 
    179  assert_equals(response.status, 200);
    180  assert_equals(await response.text(), rnd);
    181  const {requests} = await get_info_from_worker(worker);
    182  // Main resource request + subreosurce request = 2.
    183  assert_equals(requests.length, 2);
    184 
    185  test_resource_timing({
    186    performance: iwin.performance,
    187    url: `${NON_REGISTERED_ROUTE}${subresource}`,
    188    matched_source_type: 'fetch-event',
    189    final_source_type: 'fetch-event',
    190    description: "fetch-event as source on sub resource"
    191  });
    192 }, 'Subresource load matched the rule fetch-event source');
    193 
    194 iframeTest(NON_REGISTERED_ROUTE, ROUTER_RULE_KEY, async (t, iwin) => {
    195  const rnd = randomString();
    196  const subresource = `?nonce=${rnd}`;
    197  const response = await iwin.fetch(subresource);
    198  assert_equals(await response.text(), rnd);
    199  test_resource_timing({
    200    performance: iwin.performance,
    201    url: NON_REGISTERED_ROUTE + subresource,
    202    matched_source_type: '',
    203    final_source_type: '',
    204    description: "no source type matched"
    205  });
    206 }, 'Subresource load not matched with URLPattern condition');
    207 
    208 iframeTest(REGISTERED_ROUTE, ROUTER_RULE_KEY, async (t, iwin) => {
    209  const rnd = randomString();
    210  const subresource = `?nonce=${rnd}`;
    211  const response = await iwin.fetch(subresource);
    212  assert_equals(await response.text(), "Network\n");
    213  test_resource_timing({
    214    performance: iwin.performance,
    215    url: REGISTERED_ROUTE + subresource,
    216    matched_source_type: 'network',
    217    final_source_type: 'network',
    218    description: "network as source on subresource"
    219  });
    220 }, 'Subresource load matched with URLPattern condition');
    221 
    222 iframeTest(NON_REGISTERED_ROUTE, ROUTER_RULE_KEY_URLPATTERN_CACHE, async (t, iwin) => {
    223  // No need to set `resources/` because the request is dispatched from iframe.
    224  const CACHED_FILE = 'cache.txt';
    225  const response = await iwin.fetch(CACHED_FILE);
    226  assert_equals(await response.text(), "From cache");
    227  test_resource_timing({
    228    performance: iwin.performance,
    229    url: CACHED_ROUTE, // We need a path including `resources/` to get the resource
    230    matched_source_type: 'cache',
    231    final_source_type: 'cache',
    232    description: "cache as source on subresource and cache hits"
    233  });
    234 }, 'Subresource load matched with the cache source rule');
    235 
    236 iframeTest(REGISTERED_ROUTE, ROUTER_RULE_KEY_URL_PATTERN_CONSTRUCTED_MATCH_ALL_CACHE, async (t, iwin, worker) => {
    237  // Send a request, which is not stored in the cache, but it exists over the network.
    238  const rnd = randomString();
    239  let subresource = `?nonce=${rnd}`;
    240  let response = await iwin.fetch(subresource);
    241  assert_equals(await response.text(), "Network\n");
    242  assert_equals(response.status, 200);
    243 
    244  // Request is not handled by ServiceWorker.
    245  const {requests} = await get_info_from_worker(worker);
    246  assert_equals(requests.length, 0);
    247  test_resource_timing({
    248    performance: iwin.performance,
    249    url: `${REGISTERED_ROUTE}${subresource}`,
    250    matched_source_type: 'cache',
    251    final_source_type: 'network',
    252    description: "cache as source on subresource and cache misses"
    253  });
    254 }, 'Subresource load did not match with the cache and fallback to the network');
    255 
    256 // Race Tests
    257 promise_test(async t => {
    258  const rnd = randomString();
    259  const url = `${RACE_ROUTE}?nonce=${rnd}&server_slow`;
    260  const worker = await registerAndActivate(t, RACE_ROUTER_KEY, RACE_SW_SRC);
    261  const iframe = await createIframe(t, url);
    262  // Expect the response from the fetch handler.
    263  assert_equals(iframe.contentWindow.document.body.innerText, rnd);
    264  const {requests}  = await get_info_from_worker(worker);
    265  assert_equals(requests.length, 1);
    266  test_resource_timing({
    267    performance: iframe.contentWindow.performance,
    268    url: url,
    269    matched_source_type: 'race-network-and-fetch-handler',
    270    final_source_type: 'fetch-event',
    271    description: "race as source on main resource, and fetch-event wins"
    272  });
    273 }, 'Main resource load matched the rule with race-network-and-fetch-handler source, and the fetch handler response is faster than the server response');
    274 
    275 promise_test(async t => {
    276  const rnd = randomString();
    277  const url = `${RACE_ROUTE}?nonce=${rnd}&sw_slow`;
    278  const worker = await registerAndActivate(t, RACE_ROUTER_KEY, RACE_SW_SRC);
    279  const iframe = await createIframe(t, url);
    280  // Expect the response from the netowrk request.
    281  assert_equals(iframe.contentWindow.document.body.innerText, "Network with GET request");
    282  // Ensure the fetch handler is also executed.
    283  const {requests}  = await get_info_from_worker(worker);
    284  assert_equals(requests.length, 1);
    285  test_resource_timing({
    286    performance: iframe.contentWindow.performance,
    287    url: url,
    288    matched_source_type: 'race-network-and-fetch-handler',
    289    final_source_type: 'network',
    290    description: "race as source on main resource, and network wins"
    291  });
    292 }, 'Main resource load matched the rule with race-network-and-fetch-handler source, and the server reseponse is faster than the fetch handler');
    293 
    294 promise_test(async t => {
    295  const rnd = randomString();
    296  const worker = await registerAndActivate(t, RACE_ROUTER_KEY, RACE_SW_SRC);
    297  const iframe = await createIframe(t, RACE_ROUTE);
    298  const subresource = `?nonce=${rnd}&server_slow`;
    299  // Expect the response from the fetch handler.
    300  const response = await iframe.contentWindow.fetch(subresource);
    301  assert_equals(response.status, 200);
    302  assert_equals(await response.text(), rnd);
    303  const {requests}  = await get_info_from_worker(worker);
    304  assert_equals(requests.length, 2);
    305 
    306  test_resource_timing({
    307    performance: iframe.contentWindow.performance,
    308    url: `${RACE_ROUTE}${subresource}`,
    309    matched_source_type: 'race-network-and-fetch-handler',
    310    final_source_type: 'fetch-event',
    311    description: "race as source on subresource and fetch wins"
    312  });
    313 }, 'Subresource load matched the rule with race-network-and-fetch-handler source, and the fetch handler response is faster than the server response');
    314 
    315 promise_test(async t => {
    316  const rnd = randomString();
    317  const worker = await registerAndActivate(t, RACE_ROUTER_KEY, RACE_SW_SRC);
    318  const iframe = await createIframe(t, RACE_ROUTE);
    319  const subresource = `?nonce=${rnd}&sw_slow`;
    320  // Expect the response from the network request.
    321  const response = await iframe.contentWindow.fetch(subresource);
    322  assert_equals(response.status, 200);
    323  assert_equals(await response.text(), "Network with GET request");
    324  // Ensure the fetch handler is also executed.
    325  const {requests}  = await get_info_from_worker(worker);
    326  assert_equals(requests.length, 2);
    327 
    328  test_resource_timing({
    329    performance: iframe.contentWindow.performance,
    330    url: `${RACE_ROUTE}${subresource}`,
    331    matched_source_type: 'race-network-and-fetch-handler',
    332    final_source_type: 'network',
    333    description: "race as source on subresource and network wins"
    334  });
    335 }, 'Subresource load matched the rule with race-network-and-fetch-handler source, and the server reseponse is faster than the fetch handler');
    336 </script>
    337 </body>