tor-browser

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

resource-timing-fetch-variants.https.html (4422B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4 <title>Test various interactions between fetch, service-workers and resource timing</title>
      5 <meta charset="utf-8" />
      6 <script src="/resources/testharness.js"></script>
      7 <script src="/resources/testharnessreport.js"></script>
      8 <script src="resources/test-helpers.sub.js"></script>
      9 <link rel="help" href="https://w3c.github.io/resource-timing/" >
     10 <!--
     11    This test checks that the different properties in a PerformanceResourceTimingEntry
     12    measure what they are supposed to measure according to spec.
     13 
     14    It is achieved by generating programmatic delays and redirects inside a service worker,
     15    and checking how the different metrics respond to the delays and redirects.
     16 
     17    The deltas are not measured precisely, but rather relatively to the delay.
     18    The delay needs to be long enough so that it's clear that what's measured is the test's
     19    programmatic delay and not arbitrary system delays.
     20 -->
     21 </head>
     22 
     23 <body>
     24 <script>
     25 
     26 const delay = 200;
     27 const absolutePath = `${base_path()}/simple.txt`
     28 function toSequence({before, after, entry}) {
     29    /*
     30        The order of keys is the same as in this chart:
     31        https://w3c.github.io/resource-timing/#attribute-descriptions
     32    */
     33    const keys = [
     34        'startTime',
     35        'redirectStart',
     36        'redirectEnd',
     37        'workerStart',
     38        'fetchStart',
     39        'connectStart',
     40        'requestStart',
     41        'responseStart',
     42        'responseEnd'
     43    ];
     44 
     45    let cursor = before;
     46    const step = value => {
     47        // A zero/null value, reflect that in the sequence
     48        if (!value)
     49            return value;
     50 
     51        // Value is the same as before
     52        if (value === cursor)
     53            return "same";
     54 
     55        // Oops, value is in the wrong place
     56        if (value < cursor)
     57            return "back";
     58 
     59        // Delta is greater than programmatic delay, this is where the delay is measured.
     60        if ((value - cursor) >= delay)
     61            return "delay";
     62 
     63        // Some small delta, probably measuring an actual networking stack delay
     64        return "tick";
     65    }
     66 
     67    const res = keys.map(key => {
     68        const value = step(entry[key]);
     69        if (entry[key])
     70            cursor = entry[key];
     71        return [key, value];
     72    });
     73 
     74    return Object.fromEntries([...res, ['after', step(after)]]);
     75 }
     76 async function testVariant(t, variant) {
     77    const worker_url = 'resources/fetch-variants-worker.js';
     78    const url = encodeURIComponent(`simple.txt?delay=${delay}&variant=${variant}`);
     79    const scope = `resources/iframe-with-fetch-variants.html?url=${url}`;
     80    const registration = await service_worker_unregister_and_register(t, worker_url, scope);
     81    t.add_cleanup(() => registration.unregister());
     82    await wait_for_state(t, registration.installing, 'activated');
     83    const frame = await with_iframe(scope);
     84    t.add_cleanup(() => frame.remove());
     85    const result = await new Promise(resolve => window.addEventListener('message', message => {
     86        resolve(message.data);
     87    }))
     88 
     89    return toSequence(result);
     90 }
     91 
     92 promise_test(async t => {
     93    const result = await testVariant(t, 'redirect');
     94    assert_equals(result.redirectStart, 0);
     95 }, 'Redirects done from within a service-worker should not be exposed to client ResourceTiming');
     96 
     97 promise_test(async t => {
     98    const result = await testVariant(t, 'forward');
     99    assert_equals(result.connectStart, 'same');
    100 }, 'Connection info from within a service-worker should not be exposed to client ResourceTiming');
    101 
    102 promise_test(async t => {
    103    const result = await testVariant(t, 'forward');
    104    assert_not_equals(result.requestStart, 'back');
    105 }, 'requestStart should never be before fetchStart');
    106 
    107 promise_test(async t => {
    108    const result = await testVariant(t, 'delay-after-fetch');
    109    const whereIsDelayMeasured = Object.entries(result).find(r => r[1] === 'delay')[0];
    110    assert_equals(whereIsDelayMeasured, 'responseStart');
    111 }, 'Delay from within service-worker (after internal fetching) should be accessible through `responseStart`');
    112 
    113 promise_test(async t => {
    114    const result = await testVariant(t, 'delay-before-fetch');
    115    const whereIsDelayMeasured = Object.entries(result).find(r => r[1] === 'delay')[0];
    116    assert_equals(whereIsDelayMeasured, 'responseStart');
    117 }, 'Delay from within service-worker (before internal fetching) should be measured before responseStart in the client ResourceTiming entry');
    118 </script>
    119 
    120 </body>
    121 </html>