tor-browser

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

detached-context.https.html (4895B)


      1 <!DOCTYPE html>
      2 <meta charset="utf-8">
      3 <title>Service WorkerRegistration from a removed iframe</title>
      4 <script src="/resources/testharness.js"></script>
      5 <script src="/resources/testharnessreport.js"></script>
      6 <script src="resources/test-helpers.sub.js"></script>
      7 <body>
      8 </body>
      9 <script>
     10 // NOTE: This file tests corner case behavior that might not be defined in the
     11 // spec. See https://github.com/w3c/ServiceWorker/issues/1221
     12 
     13 promise_test(t => {
     14    const url = 'resources/blank.html';
     15    const scope_for_iframe = 'removed-registration'
     16    const scope_for_main = 'resources/' + scope_for_iframe;
     17    const script = 'resources/empty-worker.js';
     18    let frame;
     19    let resolvedCount = 0;
     20 
     21    return service_worker_unregister(t, scope_for_main)
     22      .then(() => {
     23          return with_iframe(url);
     24        })
     25      .then(f => {
     26          frame = f;
     27          return navigator.serviceWorker.register(script,
     28                                                  {scope: scope_for_main});
     29        })
     30      .then(r => {
     31          add_completion_callback(() => { r.unregister(); });
     32          return wait_for_state(t, r.installing, 'activated');
     33        })
     34      .then(() => {
     35          return frame.contentWindow.navigator.serviceWorker.getRegistration(
     36            scope_for_iframe);
     37        })
     38      .then(r => {
     39          frame.remove();
     40          assert_equals(r.installing, null);
     41          assert_equals(r.waiting, null);
     42          assert_equals(r.active.state, 'activated');
     43          assert_equals(r.scope, normalizeURL(scope_for_main));
     44          r.onupdatefound = () => { /* empty */ };
     45 
     46          // We want to verify that unregister() and update() do not
     47          // resolve on a detached registration.  We can't check for
     48          // an explicit rejection, though, because not all browsers
     49          // fire rejection callbacks on detached promises.  Instead
     50          // we wait for a sample scope to install, activate, and
     51          // unregister before declaring that the promises did not
     52          // resolve.
     53          r.unregister().then(() => resolvedCount += 1,
     54                              () => {});
     55          r.update().then(() => resolvedCount += 1,
     56                          () => {});
     57          return wait_for_activation_on_sample_scope(t, window);
     58        })
     59      .then(() => {
     60          assert_equals(resolvedCount, 0,
     61                        'methods called on a detached registration should not resolve');
     62          frame.remove();
     63        })
     64  }, 'accessing a ServiceWorkerRegistration from a removed iframe');
     65 
     66 promise_test(t => {
     67    const script = 'resources/empty-worker.js';
     68    const scope = 'resources/scope/serviceworker-from-detached';
     69 
     70    return service_worker_unregister_and_register(t, script, scope)
     71      .then(registration => {
     72          add_completion_callback(() => { registration.unregister(); });
     73          return wait_for_state(t, registration.installing, 'activated');
     74        })
     75      .then(() => { return with_iframe(scope); })
     76      .then(frame => {
     77          const worker = frame.contentWindow.navigator.serviceWorker.controller;
     78          const ctor = frame.contentWindow.DOMException;
     79          frame.remove();
     80          assert_equals(worker.scriptURL, normalizeURL(script));
     81          assert_equals(worker.state, 'activated');
     82          worker.onstatechange = () => { /* empty */ };
     83          assert_throws_dom(
     84              'InvalidStateError',
     85               ctor,
     86              () => { worker.postMessage(''); },
     87              'postMessage on a detached client should throw an exception.');
     88        });
     89  }, 'accessing a ServiceWorker object from a removed iframe');
     90 
     91 promise_test(t => {
     92    const iframe = document.createElement('iframe');
     93    iframe.src = 'resources/blank.html';
     94    document.body.appendChild(iframe);
     95    const f = iframe.contentWindow.Function;
     96    function get_navigator() {
     97      return f('return navigator')();
     98    }
     99    return new Promise(resolve => {
    100        assert_equals(iframe.contentWindow.navigator, get_navigator());
    101        iframe.src = 'resources/blank.html?navigate-to-new-url';
    102        iframe.onload = resolve;
    103      }).then(function() {
    104        assert_not_equals(get_navigator().serviceWorker, null);
    105        assert_equals(
    106            get_navigator().serviceWorker,
    107            iframe.contentWindow.navigator.serviceWorker);
    108        iframe.remove();
    109      });
    110  }, 'accessing navigator.serviceWorker on a detached iframe');
    111 
    112 test(t => {
    113    const iframe = document.createElement('iframe');
    114    iframe.src = 'resources/blank.html';
    115    document.body.appendChild(iframe);
    116    const f = iframe.contentWindow.Function;
    117    function get_navigator() {
    118      return f('return navigator')();
    119    }
    120    assert_not_equals(get_navigator().serviceWorker, null);
    121    iframe.remove();
    122    assert_not_equals(get_navigator().serviceWorker, null);
    123  }, 'accessing navigator on a removed frame');
    124 </script>