| <!DOCTYPE html> |
| <title>DedicatedWorker: ServiceWorker interception</title> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="resources/test-helpers.js"></script> |
| <script> |
| |
| // These tests should not be upstreamed to WPT because these check Chrome's |
| // spec-incompatible behavior (https://crbug.com/731599). These should be |
| // superseded by tests in WPT after the issue is fixed. See also |
| // external/wpt/service-workers/service-worker/dedicated-worker-service-worker-interception.https.html |
| |
| const kServiceWorkerScriptURL = |
| 'resources/service-worker-interception-service-worker.js'; |
| const kWindowURL = 'resources/new-worker-window.html'; |
| |
| function openWindow(url) { |
| return new Promise(resolve => { |
| let win = window.open(url, '_blank'); |
| add_result_callback(() => win.close()); |
| window.onmessage = e => { |
| assert_equals(e.data, 'LOADED'); |
| resolve(win); |
| }; |
| }); |
| } |
| |
| // Tests that a dedicated worker should be served by the owner document's |
| // service worker. |
| // |
| // [Current document] registers a service worker for Window's URL. |
| // --(open)--> [Window] should be controlled by the service worker. |
| // --(new Worker)--> [Worker] should be served by the service worker. |
| promise_test(async t => { |
| const registration = await service_worker_unregister_and_register( |
| t, kServiceWorkerScriptURL + '?controlled', kWindowURL); |
| add_result_callback(() => registration.unregister()); |
| await wait_for_state(t, registration.installing, 'activated'); |
| |
| const win = await openWindow(kWindowURL); |
| assert_not_equals(win.navigator.serviceWorker.controller, null, |
| 'The document should be controlled.'); |
| |
| // |win| is controlled by the service worker, so a new dedicated worker |
| // created from |win| should also be controlled by the service worker. |
| const kWorkerScriptURL = 'service-worker-interception-network-worker.js'; |
| win.postMessage(kWorkerScriptURL, '*'); |
| const msg_event = await new Promise(resolve => window.onmessage = resolve); |
| assert_equals(msg_event.data, 'LOADED_FROM_SERVICE_WORKER'); |
| }, 'Module loading for new Worker() on a controlled document should be ' + |
| 'intercepted by a service worker.'); |
| |
| // Tests that a dedicated worker should not be served by a service worker other |
| // than the owner document's service worker. |
| // |
| // [Current document] registers a service worker for Worker's URL. |
| // --(open)--> [Window] should not be controlled by the service worker. |
| // --(new Worker)--> [Worker] should not be served by the service worker. |
| promise_test(async t => { |
| const kWorkerScriptURL = 'service-worker-interception-network-worker.js'; |
| const kScope = 'resources/' + kWorkerScriptURL; |
| |
| const registration = await service_worker_unregister_and_register( |
| t, kServiceWorkerScriptURL + '?non-controlled', kScope); |
| add_result_callback(() => registration.unregister()); |
| await wait_for_state(t, registration.installing, 'activated'); |
| |
| const win = await openWindow(kWindowURL); |
| assert_equals(win.navigator.serviceWorker.controller, null, |
| 'The document should not be controlled.'); |
| |
| // |win| is not controlled by the service worker, so a new dedicated worker |
| // created from |win| should not be controlled by the service worker even if |
| // the script URL of the dedicated worker is under the scope of the service |
| // worker. |
| win.postMessage(kWorkerScriptURL, '*'); |
| const msg_event = await new Promise(resolve => window.onmessage = resolve); |
| assert_equals(msg_event.data, 'LOADED_FROM_NETWORK'); |
| }, 'Module loading for new Worker() on a non-controlled document should not ' + |
| 'be intercepted by a service worker even if the script URL is under the ' + |
| 'scope.'); |
| |
| // Tests that static import should be served by the owner document's service |
| // worker. |
| // |
| // [Current document] registers a service worker for Window's URL. |
| // --(open)--> [Window] should be controlled by the service worker. |
| // --(new Worker)--> [Worker] should be controlled by the service worker. |
| // --(static import)--> [Script] should be served by the service worker. |
| promise_test(async t => { |
| const registration = await service_worker_unregister_and_register( |
| t, kServiceWorkerScriptURL + '?static', kWindowURL); |
| add_result_callback(() => registration.unregister()); |
| await wait_for_state(t, registration.installing, 'activated'); |
| |
| const win = await openWindow(kWindowURL); |
| assert_not_equals(win.navigator.serviceWorker.controller, null, |
| 'The document should be controlled.'); |
| |
| // |win| is controlled by the service worker, so a new dedicated worker |
| // created from |win| and static import from the dedicated worker should |
| // also be controlled by the service worker. |
| const kWorkerScriptURL = |
| 'service-worker-interception-static-import-worker.js'; |
| win.postMessage(kWorkerScriptURL, '*'); |
| const msg_event = await new Promise(resolve => window.onmessage = resolve); |
| assert_equals(msg_event.data, 'LOADED_FROM_SERVICE_WORKER'); |
| }, 'Static import on a controlled dedicated worker should be intercepted by ' + |
| 'a service worker.'); |
| |
| // Tests that dynamic import should be served by the owner document's service |
| // worker. |
| // |
| // [Current document] registers a service worker for Window's URL. |
| // --(open)--> [Window] should be controlled by the service worker. |
| // --(new Worker)--> [Worker] should be controlled by the service worker. |
| // --(dynamic import)--> [Script] should be served by the service worker. |
| promise_test(async t => { |
| const registration = await service_worker_unregister_and_register( |
| t, kServiceWorkerScriptURL + '?dynamic', kWindowURL); |
| add_result_callback(() => registration.unregister()); |
| await wait_for_state(t, registration.installing, 'activated'); |
| |
| const win = await openWindow(kWindowURL); |
| assert_not_equals(win.navigator.serviceWorker.controller, null, |
| 'The document should be controlled.'); |
| |
| // |win| is controlled by the service worker, so a new dedicated worker |
| // created from |win| and dynamic import from the dedicated worker should |
| // also be controlled by the service worker. |
| const kWorkerScriptURL = |
| 'service-worker-interception-dynamic-import-worker.js'; |
| win.postMessage(kWorkerScriptURL, '*'); |
| const msg_event = await new Promise(resolve => window.onmessage = resolve); |
| assert_equals(msg_event.data, 'LOADED_FROM_SERVICE_WORKER'); |
| }, 'Dynamic import on a controlled dedicated worker should be intercepted by ' + |
| 'a service worker.'); |
| |
| </script> |