<!DOCTYPE html>
<meta charset="utf-8">
<title>Service WorkerRegistration from a removed iframe</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
</body>
<script>
// NOTE: This file tests corner case behavior that might not be defined in the
// spec. See https://github.com/w3c/ServiceWorker/issues/1221

promise_test(t => {
    const url = 'resources/blank.html';
    const scope_for_iframe = 'removed-registration'
    const scope_for_main = 'resources/' + scope_for_iframe;
    const script = 'resources/empty-worker.js';
    let frame;
    let resolvedCount = 0;

    return service_worker_unregister(t, scope_for_main)
      .then(() => {
          return with_iframe(url);
        })
      .then(f => {
          frame = f;
          return navigator.serviceWorker.register(script,
                                                  {scope: scope_for_main});
        })
      .then(r => {
          add_completion_callback(() => { r.unregister(); });
          return wait_for_state(t, r.installing, 'activated');
        })
      .then(() => {
          return frame.contentWindow.navigator.serviceWorker.getRegistration(
            scope_for_iframe);
        })
      .then(r => {
          frame.remove();
          assert_equals(r.installing, null);
          assert_equals(r.waiting, null);
          assert_equals(r.active.state, 'activated');
          assert_equals(r.scope, normalizeURL(scope_for_main));
          r.onupdatefound = () => { /* empty */ };

          // We want to verify that unregister() and update() do not
          // resolve on a detached registration.  We can't check for
          // an explicit rejection, though, because not all browsers
          // fire rejection callbacks on detached promises.  Instead
          // we wait for a dummy scope to install, activate, and
          // unregister before declaring that the promises did not
          // resolve.
          r.unregister().then(() => resolvedCount += 1,
                              () => {});
          r.update().then(() => resolvedCount += 1,
                          () => {});
          return wait_for_activation_on_dummy_scope(t, window);
        })
      .then(() => {
          assert_equals(resolvedCount, 0,
                        'methods called on a detached registration should not resolve');
          frame.remove();
        })
  }, 'accessing a ServiceWorkerRegistration from a removed iframe');

promise_test(t => {
    const script = 'resources/empty-worker.js';
    const scope = 'resources/scope/serviceworker-from-detached';

    return service_worker_unregister_and_register(t, script, scope)
      .then(registration => {
          add_completion_callback(() => { registration.unregister(); });
          return wait_for_state(t, registration.installing, 'activated');
        })
      .then(() => { return with_iframe(scope); })
      .then(frame => {
          const worker = frame.contentWindow.navigator.serviceWorker.controller;
          frame.remove();
          assert_equals(worker.scriptURL, normalizeURL(script));
          assert_equals(worker.state, 'activated');
          worker.onstatechange = () => { /* empty */ };
          assert_throws(
              { name: 'InvalidStateError' },
              () => { worker.postMessage(''); },
              'postMessage on a detached client should throw an exception.');
        });
  }, 'accessing a ServiceWorker object from a removed iframe');

promise_test(t => {
    const iframe = document.createElement('iframe');
    iframe.src = 'resources/blank.html';
    document.body.appendChild(iframe);
    const f = iframe.contentWindow.Function;
    function get_navigator() {
      return f('return navigator')();
    }
    return new Promise(resolve => {
        assert_equals(iframe.contentWindow.navigator, get_navigator());
        iframe.src = 'resources/blank.html?navigate-to-new-url';
        iframe.onload = resolve;
      }).then(function() {
        assert_not_equals(get_navigator().serviceWorker, null);
        assert_equals(
            get_navigator().serviceWorker,
            iframe.contentWindow.navigator.serviceWorker);
        iframe.remove();
      });
  }, 'accessing navigator.serviceWorker on a detached iframe');

test(t => {
    const iframe = document.createElement('iframe');
    iframe.src = 'resources/blank.html';
    document.body.appendChild(iframe);
    const f = iframe.contentWindow.Function;
    function get_navigator() {
      return f('return navigator')();
    }
    assert_not_equals(get_navigator().serviceWorker, null);
    iframe.remove();
    assert_throws({name: 'TypeError'}, () => get_navigator());
  }, 'accessing navigator on a removed frame');

// It seems weird that about:blank and blank.html (the test above) have
// different behavior. These expectations are based on Chromium behavior, which
// might not be right.
test(t => {
    const iframe = document.createElement('iframe');
    iframe.src = 'about:blank';
    document.body.appendChild(iframe);
    const f = iframe.contentWindow.Function;
    function get_navigator() {
      return f('return navigator')();
    }
    assert_not_equals(get_navigator().serviceWorker, null);
    iframe.remove();
    assert_equals(get_navigator().serviceWorker, null);
  }, 'accessing navigator.serviceWorker on a removed about:blank frame');

</script>
