<!doctype html>
<meta charset=utf-8>
<title>Use Clear-Site-Data to immediately unregister service workers</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<script src="resources/unregister-immediately-helpers.js"></script>
<body>
<script>
'use strict';

// These tests use the Clear-Site-Data network response header to immediately
// unregister a service worker registration with a worker whose state is
// 'installed', 'waiting', 'activating' or 'activated'.  Immediately
// unregistering runs the "Clear Registration" algorithm without waiting for the
// active worker's controlled clients to unload.

promise_test(async test => {
  // This test keeps the the service worker in the 'activating' state by using a
  // script with an activate event waitUntil() promise that never resolves.
  const script_url = 'resources/onactivate-waituntil-forever.js';
  const scope_url =
    'resources/scope-for-unregister-immediately-with-waiting-worker';

  const registration = await service_worker_unregister_and_register(
    test, script_url, scope_url);
  const service_worker = registration.installing;

  await wait_for_state(test, service_worker, 'activating');

  // Clear-Site-Data must cause activation to fail.
  await Promise.all([
    clear_site_data(),
    wait_for_state(test, service_worker, 'redundant')]);

  await assert_no_registrations_exist();
 }, 'Clear-Site-Data must unregister a registration with a worker '
     + 'in the "activating" state.');

promise_test(async test => {
  // Create an registration with two service workers: one activated and one
  // installed.
  const script_url = 'resources/update_shell.py';
  const scope_url =
    'resources/scope-for-unregister-immediately-with-with-update';

  const registration = await service_worker_unregister_and_register(
    test, script_url, scope_url);
  const first_service_worker = registration.installing;

  await wait_for_state(test, first_service_worker, 'activated');
  registration.update();

  const event_watcher = new EventWatcher(test, registration, 'updatefound');
  await event_watcher.wait_for('updatefound');

  const second_service_worker = registration.installing;
  await wait_for_state(test, second_service_worker, 'installed');

  // Clear-Site-Data must clear both workers from the registration.
  await Promise.all([
    clear_site_data(),
    wait_for_state(test, first_service_worker, 'redundant'),
    wait_for_state(test, second_service_worker, 'redundant')]);

  await assert_no_registrations_exist();
}, 'Clear-Site-Data must unregister an activated registration with '
    + 'an update waiting.');

promise_test(async test => {
  const script_url = 'resources/empty.js';
  const scope_url =
    'resources/blank.html?unregister-immediately-with-controlled-client';

  const registration = await service_worker_unregister_and_register(
    test, script_url, scope_url);
  const service_worker = registration.installing;

  await wait_for_state(test, service_worker, 'activated');
  const frame = await add_controlled_iframe(test, scope_url);
  const frame_registration =
    await frame.contentWindow.navigator.serviceWorker.ready;

  const event_watcher = new EventWatcher(
    test, frame.contentWindow.navigator.serviceWorker, 'controllerchange');

  // Clear-Site-Data must remove the iframe's controller.
  await Promise.all([
    clear_site_data(),
    event_watcher.wait_for('controllerchange'),
    wait_for_state(test, service_worker, 'redundant')]);

  assert_equals(frame.contentWindow.navigator.serviceWorker.controller, null);
  await assert_no_registrations_exist();

  // The ready promise must continue to resolve with the unregistered
  // registration.
  assert_equals(frame_registration,
    await frame.contentWindow.navigator.serviceWorker.ready);
}, 'Clear-Site-Data must unregister an activated registration with controlled '
   + 'clients.');

promise_test(async test => {
  const script_url = 'resources/empty.js';
  const scope_url =
    'resources/blank.html?unregister-immediately-while-waiting-to-clear';

  const registration = await service_worker_unregister_and_register(
    test, script_url, scope_url);
  const service_worker = registration.installing;

  await wait_for_state(test, service_worker, 'activated');
  const frame = await add_controlled_iframe(test, scope_url);

  const event_watcher = new EventWatcher(
    test, frame.contentWindow.navigator.serviceWorker, 'controllerchange');

  // Unregister waits to clear the registration until no controlled clients
  // exist.
  await registration.unregister();

  // Clear-Site-Data must clear the unregistered registration immediately.
  await Promise.all([
    clear_site_data(),
    event_watcher.wait_for('controllerchange'),
    wait_for_state(test, service_worker, 'redundant')]);

  assert_equals(frame.contentWindow.navigator.serviceWorker.controller, null);
  await assert_no_registrations_exist();
}, 'Clear-Site-Data must clear an unregistered registration waiting for '
   + ' controlled clients to unload.');

</script>
</body>
