summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/service-workers/service-worker/claim-fetch.https.html
blob: ae0082df06bf794d02990a7c0b7213e0d81114cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
<!doctype html>
<meta charset=utf-8>
<title></title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/test-helpers.sub.js"></script>
<body>
<script>

async function tryFetch(fetchFunc, path) {
  let response;
  try {
   response = await fetchFunc(path);
  } catch (err) {
    throw (`fetch() threw: ${err}`);
  }

  let responseText;
  try {
   responseText = await response.text();
  } catch (err) {
   throw (`text() threw: ${err}`);
  }

  return responseText;
}

promise_test(async function(t) {
  const scope = 'resources/';
  const script = 'resources/claim-worker.js';
  const resource = 'simple.txt';

  // Create the test frame.
  const frame = await with_iframe('resources/blank.html');
  t.add_cleanup(() => frame.remove());

  // Check the controller and test with fetch.
  assert_equals(frame.contentWindow.navigator.controller, undefined,
                'Should have no controller.');
  let response;
  try {
    response = await tryFetch(frame.contentWindow.fetch, resource);
  } catch (err) {
    assert_unreached(`uncontrolled fetch failed: ${err}`);
  }
  assert_equals(response, 'a simple text file\n',
                'fetch() should not be intercepted.');

  // Register a service worker.
  const registration =
    await service_worker_unregister_and_register(t, script, scope);
  t.add_cleanup(() => registration.unregister());
  const worker = registration.installing;
  await wait_for_state(t, worker, 'activated');

  // Register a controllerchange event to wait until the controller is updated
  // and check if the frame is controlled by a service worker.
  const controllerChanged = new Promise((resolve) => {
    frame.contentWindow.navigator.serviceWorker.oncontrollerchange = () => {
      resolve(frame.contentWindow.navigator.serviceWorker.controller);
    };
  });

  // Tell the service worker to claim the iframe.
  const sawMessage = new Promise((resolve) => {
    const channel = new MessageChannel();
    channel.port1.onmessage = t.step_func((event) => {
      resolve(event.data);
    });
    worker.postMessage({port: channel.port2}, [channel.port2]);
  });
  const data = await sawMessage;
  assert_equals(data, 'PASS', 'Worker call to claim() should fulfill.');

  // Check if the controller is updated after claim() and test with fetch.
  const controller = await controllerChanged;
  assert_true(controller instanceof frame.contentWindow.ServiceWorker,
              'iframe should be controlled.');
  try {
    response = await tryFetch(frame.contentWindow.fetch, resource);
  } catch (err) {
    assert_unreached(`controlled fetch failed: ${err}`);
  }
  assert_equals(response, 'Intercepted!',
                'fetch() should be intercepted.');
}, 'fetch() should be intercepted after the client is claimed.');

</script>
</body>