| <!DOCTYPE html> |
| <meta charset="utf-8"> |
| <title>Service Worker: Update the registration with a different script type.</title> |
| <!-- common.js is for guid() --> |
| <script src="/common/security-features/resources/common.sub.js"></script> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="resources/test-helpers.sub.js"></script> |
| <script> |
| // The following two tests check that a registration is updated correctly |
| // with different script type. At first Service Worker is registered as |
| // classic script type, then it is re-registered as module script type, |
| // and vice versa. A main script is also updated at the same time. |
| promise_test(async t => { |
| const key = guid(); |
| const script = `resources/update-registration-with-type.py?classic_first=1&key=${key}`; |
| const scope = 'resources/update-registration-with-type'; |
| await service_worker_unregister(t, scope); |
| t.add_cleanup(() => service_worker_unregister(t, scope)); |
| |
| // Register with classic script type. |
| const firstRegistration = await navigator.serviceWorker.register(script, { |
| scope: scope, |
| type: 'classic' |
| }); |
| const firstWorker = firstRegistration.installing; |
| await wait_for_state(t, firstWorker, 'activated'); |
| firstWorker.postMessage(' '); |
| let msgEvent = await new Promise(r => navigator.serviceWorker.onmessage = r); |
| assert_equals(msgEvent.data, 'A classic script.'); |
| |
| // Re-register with module script type. |
| const secondRegistration = await navigator.serviceWorker.register(script, { |
| scope: scope, |
| type: 'module' |
| }); |
| const secondWorker = secondRegistration.installing; |
| secondWorker.postMessage(' '); |
| msgEvent = await new Promise(r => navigator.serviceWorker.onmessage = r); |
| assert_equals(msgEvent.data, 'A module script.'); |
| |
| assert_not_equals(firstWorker, secondWorker); |
| assert_equals(firstRegistration, secondRegistration); |
| }, 'Update the registration with a different script type (classic => module).'); |
| |
| promise_test(async t => { |
| const key = guid(); |
| const script = `resources/update-registration-with-type.py?classic_first=0&key=${key}`; |
| const scope = 'resources/update-registration-with-type'; |
| await service_worker_unregister(t, scope); |
| t.add_cleanup(() => service_worker_unregister(t, scope)); |
| |
| // Register with module script type. |
| const firstRegistration = await navigator.serviceWorker.register(script, { |
| scope: scope, |
| type: 'module' |
| }); |
| const firstWorker = firstRegistration.installing; |
| await wait_for_state(t, firstWorker, 'activated'); |
| firstWorker.postMessage(' '); |
| let msgEvent = await new Promise(r => navigator.serviceWorker.onmessage = r); |
| assert_equals(msgEvent.data, 'A module script.'); |
| |
| // Re-register with classic script type. |
| const secondRegistration = await navigator.serviceWorker.register(script, { |
| scope: scope, |
| type: 'classic' |
| }); |
| const secondWorker = secondRegistration.installing; |
| secondWorker.postMessage(' '); |
| msgEvent = await new Promise(r => navigator.serviceWorker.onmessage = r); |
| assert_equals(msgEvent.data, 'A classic script.'); |
| |
| assert_not_equals(firstWorker, secondWorker); |
| assert_equals(firstRegistration, secondRegistration); |
| }, 'Update the registration with a different script type (module => classic).'); |
| |
| // The following two tests change the script type while keeping |
| // the script identical. |
| promise_test(async t => { |
| const script = 'resources/empty-worker.js'; |
| const scope = 'resources/update-registration-with-type'; |
| await service_worker_unregister(t, scope); |
| t.add_cleanup(() => service_worker_unregister(t, scope)); |
| |
| // Register with classic script type. |
| const firstRegistration = await navigator.serviceWorker.register(script, { |
| scope: scope, |
| type: 'classic' |
| }); |
| const firstWorker = firstRegistration.installing; |
| await wait_for_state(t, firstWorker, 'activated'); |
| |
| // Re-register with module script type. |
| const secondRegistration = await navigator.serviceWorker.register(script, { |
| scope: scope, |
| type: 'module' |
| }); |
| const secondWorker = secondRegistration.installing; |
| |
| assert_not_equals(firstWorker, secondWorker); |
| assert_equals(firstRegistration, secondRegistration); |
| }, 'Update the registration with a different script type (classic => module) ' |
| + 'and with a same main script.'); |
| |
| promise_test(async t => { |
| const script = 'resources/empty-worker.js'; |
| const scope = 'resources/update-registration-with-type'; |
| await service_worker_unregister(t, scope); |
| t.add_cleanup(() => service_worker_unregister(t, scope)); |
| |
| // Register with module script type. |
| const firstRegistration = await navigator.serviceWorker.register(script, { |
| scope: scope, |
| type: 'module' |
| }); |
| const firstWorker = firstRegistration.installing; |
| await wait_for_state(t, firstWorker, 'activated'); |
| |
| // Re-register with classic script type. |
| const secondRegistration = await navigator.serviceWorker.register(script, { |
| scope: scope, |
| type: 'classic' |
| }); |
| const secondWorker = secondRegistration.installing; |
| |
| assert_not_equals(firstWorker, secondWorker); |
| assert_equals(firstRegistration, secondRegistration); |
| }, 'Update the registration with a different script type (module => classic) ' |
| + 'and with a same main script.'); |
| |
| // This test checks that a registration is not updated with the same script |
| // type and the same main script. |
| promise_test(async t => { |
| const script = 'resources/empty-worker.js'; |
| const scope = 'resources/update-registration-with-type'; |
| await service_worker_unregister(t, scope); |
| t.add_cleanup(() => service_worker_unregister(t, scope)); |
| |
| // Register with module script type. |
| const firstRegistration = await navigator.serviceWorker.register(script, { |
| scope: scope, |
| type: 'module' |
| }); |
| await wait_for_state(t, firstRegistration.installing, 'activated'); |
| |
| // Re-register with module script type. |
| const secondRegistration = await navigator.serviceWorker.register(script, { |
| scope: scope, |
| type: 'module' |
| }); |
| assert_equals(secondRegistration.installing, null); |
| |
| assert_equals(firstRegistration, secondRegistration); |
| }, 'Does not update the registration with the same script type and ' |
| + 'the same main script.'); |
| |
| // In the case (classic => module), a worker script contains importScripts() |
| // that is disallowed on module scripts, so the second registration is |
| // expected to fail script evaluation. |
| promise_test(async t => { |
| const script = 'resources/classic-worker.js'; |
| const scope = 'resources/update-registration-with-type'; |
| await service_worker_unregister(t, scope); |
| t.add_cleanup(() => service_worker_unregister(t, scope)); |
| |
| // Register with classic script type. |
| const firstRegistration = await navigator.serviceWorker.register(script, { |
| scope: scope, |
| type: 'classic' |
| }); |
| assert_not_equals(firstRegistration.installing, null); |
| await wait_for_state(t, firstRegistration.installing, 'activated'); |
| |
| // Re-register with module script type and expect TypeError. |
| return promise_rejects_js(t, TypeError, navigator.serviceWorker.register(script, { |
| scope: scope, |
| type: 'module' |
| }), 'Registering with invalid evaluation should be failed.'); |
| }, 'Update the registration with a different script type (classic => module) ' |
| + 'and with a same main script. Expect evaluation failed.'); |
| |
| // In the case (module => classic), a worker script contains static-import |
| // that is disallowed on classic scripts, so the second registration is |
| // expected to fail script evaluation. |
| promise_test(async t => { |
| const script = 'resources/module-worker.js'; |
| const scope = 'resources/update-registration-with-type'; |
| await service_worker_unregister(t, scope); |
| t.add_cleanup(() => service_worker_unregister(t, scope)); |
| |
| // Register with module script type. |
| const firstRegistration = await navigator.serviceWorker.register(script, { |
| scope: scope, |
| type: 'module' |
| }); |
| assert_not_equals(firstRegistration.installing, null); |
| await wait_for_state(t, firstRegistration.installing, 'activated'); |
| |
| // Re-register with classic script type and expect TypeError. |
| return promise_rejects_js(t, TypeError, navigator.serviceWorker.register(script, { |
| scope: scope, |
| type: 'classic' |
| }), 'Registering with invalid evaluation should be failed.'); |
| }, 'Update the registration with a different script type (module => classic) ' |
| + 'and with a same main script. Expect evaluation failed.'); |
| </script> |
| </body> |