<!DOCTYPE html>
<title>Service Worker: controlling a SharedWorker</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>
// This tests service worker interception for worker clients, when the request
// for the worker script goes through redirects. For example, a request can go
// through a chain of URLs like A -> B -> C -> D and each URL might fall in the
// scope of a different service worker, if any.
// The two key questions are:
// 1. Upon a redirect from A -> B, should a service worker for scope B
//    intercept the request?
// 2. After the final response, which service worker controls the resulting
//    client?
//
// The standard prescribes the following:
// 1. The service worker for scope B intercepts the redirect. *However*, once a
//    request falls back to network (i.e., a service worker did not call
//    respondWith()) and a redirect is then received from network, no service
//    worker should intercept that redirect or any subsequent redirects.
// 2. The final service worker that got a fetch event (or would have, in the
//    case of a non-fetch-event worker) becomes the controller of the client.
//
// The standard may change later, see:
// https://github.com/w3c/ServiceWorker/issues/1289
//
// The basic test setup is:
// 1. Page registers service workers for scope1 and scope2.
// 2. Page requests a worker from scope1.
// 3. The request is redirected to scope2 or out-of-scope.
// 4. The worker posts message to the page describing where the final response
//   was served from (service worker or network).
// 5. The worker does an importScripts() and fetch(), and posts back the
//   responses, which describe where the responses where served from.
//
// Currently this only tests shared worker but dedicated worker tests should be
// added in a future patch.

// Globals for easier cleanup.
const scope1 = 'resources/scope1';
const scope2 = 'resources/scope2';
let frame;

function get_message_from_worker(worker) {
  return new Promise(resolve => {
      worker.port.onmessage = evt => {
        resolve(evt.data);
      }
    });
}

async function cleanup() {
  if (frame)
    frame.remove();

  const reg1 = await navigator.serviceWorker.getRegistration(scope1);
  if (reg1)
    await reg1.unregister();
  const reg2 = await navigator.serviceWorker.getRegistration(scope2);
  if (reg2)
    await reg2.unregister();
}

// Builds the worker script URL, which encodes information about where
// to redirect to. The URL falls in sw1's scope.
//
// - |redirector| is "network" or "serviceworker". If "serviceworker", sw1 will
// respondWith() a redirect. Otherwise, it falls back to network and the server
// responds with a redirect.
// - |redirect_location| is "scope2" or "out-of-scope". If "scope2", the
// redirect ends up in sw2's scope2. Otherwise it's out of scope.
function build_worker_url(redirector, redirect_location) {
  let redirect_path;
  // Set path to redirect.py, a file on the server that serves
  // a redirect. When sw1 sees this URL, it falls back to network.
  if (redirector == 'network')
    redirector_path = 'redirect.py';
  // Set path to 'sw-redirect', to tell the service worker
  // to respond with redirect.
  else if (redirector == 'serviceworker')
    redirector_path = 'sw-redirect';

  let redirect_to = base_path() + 'resources/';
  // Append "scope2/" to redirect_to, so the redirect falls in scope2.
  // Otherwise no change is needed, as the parent "resources/" directory is
  // used, and is out-of-scope.
  if (redirect_location == 'scope2')
    redirect_to += 'scope2/';
  // Append the name of the file which serves the worker script.
  redirect_to += 'worker_interception_redirect_webworker.py';

  return `scope1/${redirector_path}?Redirect=${redirect_to}`
}

promise_test(async t => {
  await cleanup();
  const service_worker = 'resources/worker-interception-redirect-serviceworker.js';
  const registration1 = await navigator.serviceWorker.register(service_worker, {scope: scope1});
  await wait_for_state(t, registration1.installing, 'activated');
  const registration2 = await navigator.serviceWorker.register(service_worker, {scope: scope2});
  await wait_for_state(t, registration2.installing, 'activated');

  promise_test(t => {
    return cleanup();
  }, 'cleanup global state');
}, 'initialize global state');

function worker_redirect_test(worker_request_url,
                              worker_expected_url,
                              expected_main_resource_message,
                              expected_import_scripts_message,
                              expected_fetch_message,
                              description) {
  promise_test(async t => {
    // Create a frame to load the worker from. This way we can remove the frame
    // to destroy the worker client when the test is done.
    frame = await with_iframe('resources/blank.html');
    t.add_cleanup(() => { frame.remove(); });

    // Start the worker.
    const w = new frame.contentWindow.SharedWorker(worker_request_url);
    w.port.start();

    // Expect a message from the worker indicating which service worker
    // provided the response for the worker script request, if any.
    const data = await get_message_from_worker(w);
    assert_equals(data, expected_main_resource_message);

    // The worker does an importScripts(). Expect a message from the worker
    // indicating which service worker provided the response for the
    // importScripts(), if any.
    const import_scripts_message = await get_message_from_worker(w);
    assert_equals(import_scripts_message, expected_import_scripts_message);

    // The worker does a fetch(). Expect a message from the worker indicating
    // which service worker provided the response for the fetch(), if any.
    const fetch_message = await get_message_from_worker(w);
    assert_equals(fetch_message, expected_fetch_message);

    // Expect a message from the worker indicating |self.location|.
    const worker_actual_url = await get_message_from_worker(w);
    assert_equals(
      worker_actual_url,
      (new URL(worker_expected_url, location.href)).toString(),
      'location.href');
  }, description);
}

worker_redirect_test(
    build_worker_url('network', 'scope2'),
    'resources/scope2/worker_interception_redirect_webworker.py',
    'the shared worker script was served from network',
    'sw1 saw importScripts from the worker',
    'fetch(): sw1 saw the fetch from the worker',
    'request to sw1 scope gets network redirect to sw2 scope');

worker_redirect_test(
    build_worker_url('network', 'out-scope'),
    'resources/worker_interception_redirect_webworker.py',
    'the shared worker script was served from network',
    'sw1 saw importScripts from the worker',
    'fetch(): sw1 saw the fetch from the worker',
    'request to sw1 scope gets network redirect to out-of-scope');

worker_redirect_test(
    build_worker_url('serviceworker', 'scope2'),
    'resources/worker_interception_redirect_webworker.py?greeting=sw2%20saw%20the%20request%20for%20the%20worker%20script',
    'sw2 saw the request for the worker script',
    'sw2 saw importScripts from the worker',
    'fetch(): sw2 saw the fetch from the worker',
    'request to sw1 scope gets service-worker redirect to sw2 scope');

worker_redirect_test(
    build_worker_url('serviceworker', 'out-scope'),
    'resources/worker_interception_redirect_webworker.py',
    'the shared worker script was served from network',
    'sw1 saw importScripts from the worker',
    'fetch(): sw1 saw the fetch from the worker',
    'request to sw1 scope gets service-worker redirect to out-of-scope');
</script>
</body>
