getregistrations.https.html (5783B)
1 <!DOCTYPE html> 2 <title>Service Worker: getRegistrations()</title> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <script src="resources/test-helpers.sub.js"></script> 6 <script src="/common/get-host-info.sub.js"></script> 7 <script> 8 // Purge the existing registrations for the origin. 9 // getRegistrations() is used in order to avoid adding additional complexity 10 // e.g. adding an internal function. 11 promise_test(async () => { 12 const registrations = await navigator.serviceWorker.getRegistrations(); 13 await Promise.all(registrations.map(r => r.unregister())); 14 const value = await navigator.serviceWorker.getRegistrations(); 15 assert_array_equals( 16 value, [], 17 'getRegistrations should resolve with an empty array.'); 18 }, 'registrations are not returned following unregister'); 19 20 promise_test(async t => { 21 const scope = 'resources/scope/getregistrations/normal'; 22 const script = 'resources/empty-worker.js'; 23 const registrations = [ 24 await service_worker_unregister_and_register(t, script, scope)]; 25 t.add_cleanup(() => registrations[0].unregister()); 26 const value = await navigator.serviceWorker.getRegistrations(); 27 assert_array_equals(value, registrations, 28 'getRegistrations should resolve with an array of registrations'); 29 }, 'Register then getRegistrations'); 30 31 promise_test(async t => { 32 const scope1 = 'resources/scope/getregistrations/scope1'; 33 const scope2 = 'resources/scope/getregistrations/scope2'; 34 const scope3 = 'resources/scope/getregistrations/scope12'; 35 36 const script = 'resources/empty-worker.js'; 37 t.add_cleanup(() => service_worker_unregister(t, scope1)); 38 t.add_cleanup(() => service_worker_unregister(t, scope2)); 39 t.add_cleanup(() => service_worker_unregister(t, scope3)); 40 41 const registrations = [ 42 await service_worker_unregister_and_register(t, script, scope1), 43 await service_worker_unregister_and_register(t, script, scope2), 44 await service_worker_unregister_and_register(t, script, scope3), 45 ]; 46 47 const value = await navigator.serviceWorker.getRegistrations(); 48 assert_array_equals(value, registrations); 49 }, 'Register multiple times then getRegistrations'); 50 51 promise_test(async t => { 52 const scope = 'resources/scope/getregistrations/register-unregister'; 53 const script = 'resources/empty-worker.js'; 54 const registration = await service_worker_unregister_and_register(t, script, scope); 55 await registration.unregister(); 56 const value = await navigator.serviceWorker.getRegistrations(); 57 assert_array_equals( 58 value, [], 'getRegistrations should resolve with an empty array.'); 59 }, 'Register then Unregister then getRegistrations'); 60 61 promise_test(async t => { 62 const scope = 'resources/scope/getregistrations/register-unregister-controlled'; 63 const script = 'resources/empty-worker.js'; 64 const registration = await service_worker_unregister_and_register(t, script, scope); 65 await wait_for_state(t, registration.installing, 'activated'); 66 67 // Create a frame controlled by the service worker and unregister the 68 // worker. 69 const frame = await with_iframe(scope); 70 t.add_cleanup(() => frame.remove()); 71 await registration.unregister(); 72 73 const value = await navigator.serviceWorker.getRegistrations(); 74 assert_array_equals( 75 value, [], 76 'getRegistrations should resolve with an empty array.'); 77 assert_equals(registration.installing, null); 78 assert_equals(registration.waiting, null); 79 assert_equals(registration.active.state, 'activated'); 80 }, 'Register then Unregister with controlled frame then getRegistrations'); 81 82 promise_test(async t => { 83 const host_info = get_host_info(); 84 // Rewrite the url to point to remote origin. 85 const frame_same_origin_url = new URL("resources/frame-for-getregistrations.html", window.location); 86 const frame_url = host_info['HTTPS_REMOTE_ORIGIN'] + frame_same_origin_url.pathname; 87 const scope = 'resources/scope-for-getregistrations'; 88 const script = 'resources/empty-worker.js'; 89 90 // Loads an iframe and waits for 'ready' message from it to resolve promise. 91 // Caller is responsible for removing frame. 92 function with_iframe_ready(url) { 93 return new Promise(resolve => { 94 const frame = document.createElement('iframe'); 95 frame.src = url; 96 window.addEventListener('message', function onMessage(e) { 97 window.removeEventListener('message', onMessage); 98 if (e.data == 'ready') { 99 resolve(frame); 100 } 101 }); 102 document.body.appendChild(frame); 103 }); 104 } 105 106 // We need this special frame loading function because the frame is going 107 // to register it's own service worker and there is the possibility that that 108 // register() finishes after the register() for the same domain later in the 109 // test. So we have to wait until the cross origin register() is done, and not 110 // just until the frame loads. 111 const frame = await with_iframe_ready(frame_url); 112 t.add_cleanup(async () => { 113 // Wait until the cross-origin worker is unregistered. 114 let resolve; 115 const channel = new MessageChannel(); 116 channel.port1.onmessage = e => { 117 if (e.data == 'unregistered') 118 resolve(); 119 }; 120 frame.contentWindow.postMessage('unregister', '*', [channel.port2]); 121 await new Promise(r => { resolve = r; }); 122 123 frame.remove(); 124 }); 125 126 const registrations = [ 127 await service_worker_unregister_and_register(t, script, scope)]; 128 t.add_cleanup(() => registrations[0].unregister()); 129 const value = await navigator.serviceWorker.getRegistrations(); 130 assert_array_equals( 131 value, registrations, 132 'getRegistrations should only return same origin registrations.'); 133 }, 'getRegistrations promise resolves only with same origin registrations.'); 134 </script>