ready.https.window.js (8159B)
1 // META: title=Service Worker: navigator.serviceWorker.ready 2 // META: script=resources/test-helpers.sub.js 3 4 test(() => { 5 assert_equals( 6 navigator.serviceWorker.ready, 7 navigator.serviceWorker.ready, 8 'repeated access to ready without intervening registrations should return the same Promise object' 9 ); 10 }, 'ready returns the same Promise object'); 11 12 promise_test(async t => { 13 const frame = await with_iframe('resources/blank.html?uncontrolled'); 14 t.add_cleanup(() => frame.remove()); 15 16 const promise = frame.contentWindow.navigator.serviceWorker.ready; 17 18 assert_equals( 19 Object.getPrototypeOf(promise), 20 frame.contentWindow.Promise.prototype, 21 'the Promise should be in the context of the related document' 22 ); 23 }, 'ready returns a Promise object in the context of the related document'); 24 25 promise_test(async t => { 26 const url = 'resources/empty-worker.js'; 27 const scope = 'resources/blank.html?ready-controlled'; 28 const expectedURL = normalizeURL(url); 29 const registration = await service_worker_unregister_and_register(t, url, scope); 30 t.add_cleanup(() => registration.unregister()); 31 32 await wait_for_state(t, registration.installing, 'activated'); 33 34 const frame = await with_iframe(scope); 35 t.add_cleanup(() => frame.remove()); 36 37 const readyReg = await frame.contentWindow.navigator.serviceWorker.ready; 38 39 assert_equals(readyReg.installing, null, 'installing should be null'); 40 assert_equals(readyReg.waiting, null, 'waiting should be null'); 41 assert_equals(readyReg.active.scriptURL, expectedURL, 'active after ready should not be null'); 42 assert_equals( 43 frame.contentWindow.navigator.serviceWorker.controller, 44 readyReg.active, 45 'the controller should be the active worker' 46 ); 47 assert_in_array( 48 readyReg.active.state, 49 ['activating', 'activated'], 50 '.ready should be resolved when the registration has an active worker' 51 ); 52 }, 'ready on a controlled document'); 53 54 promise_test(async t => { 55 const url = 'resources/empty-worker.js'; 56 const scope = 'resources/blank.html?ready-potential-controlled'; 57 const expected_url = normalizeURL(url); 58 const frame = await with_iframe(scope); 59 t.add_cleanup(() => frame.remove()); 60 61 const registration = await navigator.serviceWorker.register(url, { scope }); 62 t.add_cleanup(() => registration.unregister()); 63 64 const readyReg = await frame.contentWindow.navigator.serviceWorker.ready; 65 66 assert_equals(readyReg.installing, null, 'installing should be null'); 67 assert_equals(readyReg.waiting, null, 'waiting should be null.') 68 assert_equals(readyReg.active.scriptURL, expected_url, 'active after ready should not be null'); 69 assert_in_array( 70 readyReg.active.state, 71 ['activating', 'activated'], 72 '.ready should be resolved when the registration has an active worker' 73 ); 74 assert_equals( 75 frame.contentWindow.navigator.serviceWorker.controller, 76 null, 77 'uncontrolled document should not have a controller' 78 ); 79 }, 'ready on a potential controlled document'); 80 81 promise_test(async t => { 82 const url = 'resources/empty-worker.js'; 83 const scope = 'resources/blank.html?ready-installing'; 84 85 await service_worker_unregister(t, scope); 86 87 const frame = await with_iframe(scope); 88 const promise = frame.contentWindow.navigator.serviceWorker.ready; 89 navigator.serviceWorker.register(url, { scope }); 90 const registration = await promise; 91 92 t.add_cleanup(async () => { 93 await registration.unregister(); 94 frame.remove(); 95 }); 96 97 assert_equals(registration.installing, null, 'installing should be null'); 98 assert_equals(registration.waiting, null, 'waiting should be null'); 99 assert_not_equals(registration.active, null, 'active after ready should not be null'); 100 assert_in_array( 101 registration.active.state, 102 ['activating', 'activated'], 103 '.ready should be resolved when the registration has an active worker' 104 ); 105 }, 'ready on an iframe whose parent registers a new service worker'); 106 107 promise_test(async t => { 108 const scope = 'resources/register-iframe.html'; 109 const frame = await with_iframe(scope); 110 111 const registration = await frame.contentWindow.navigator.serviceWorker.ready; 112 113 t.add_cleanup(async () => { 114 await registration.unregister(); 115 frame.remove(); 116 }); 117 118 assert_equals(registration.installing, null, 'installing should be null'); 119 assert_equals(registration.waiting, null, 'waiting should be null'); 120 assert_not_equals(registration.active, null, 'active after ready should not be null'); 121 assert_in_array( 122 registration.active.state, 123 ['activating', 'activated'], 124 '.ready should be resolved with "active worker"' 125 ); 126 }, 'ready on an iframe that installs a new service worker'); 127 128 promise_test(async t => { 129 const url = 'resources/empty-worker.js'; 130 const matchedScope = 'resources/blank.html?ready-after-match'; 131 const longerMatchedScope = 'resources/blank.html?ready-after-match-longer'; 132 133 await service_worker_unregister(t, matchedScope); 134 await service_worker_unregister(t, longerMatchedScope); 135 136 const frame = await with_iframe(longerMatchedScope); 137 const registration = await navigator.serviceWorker.register(url, { scope: matchedScope }); 138 139 t.add_cleanup(async () => { 140 await registration.unregister(); 141 frame.remove(); 142 }); 143 144 await wait_for_state(t, registration.installing, 'activated'); 145 146 const longerRegistration = await navigator.serviceWorker.register(url, { scope: longerMatchedScope }); 147 148 t.add_cleanup(() => longerRegistration.unregister()); 149 150 const readyReg = await frame.contentWindow.navigator.serviceWorker.ready; 151 152 assert_equals( 153 readyReg.scope, 154 normalizeURL(longerMatchedScope), 155 'longer matched registration should be returned' 156 ); 157 assert_equals( 158 frame.contentWindow.navigator.serviceWorker.controller, 159 null, 160 'controller should be null' 161 ); 162 }, 'ready after a longer matched registration registered'); 163 164 promise_test(async t => { 165 const url = 'resources/empty-worker.js'; 166 const matchedScope = 'resources/blank.html?ready-after-resolve'; 167 const longerMatchedScope = 'resources/blank.html?ready-after-resolve-longer'; 168 const registration = await service_worker_unregister_and_register(t, url, matchedScope); 169 t.add_cleanup(() => registration.unregister()); 170 171 await wait_for_state(t, registration.installing, 'activated'); 172 173 const frame = await with_iframe(longerMatchedScope); 174 t.add_cleanup(() => frame.remove()); 175 176 const readyReg1 = await frame.contentWindow.navigator.serviceWorker.ready; 177 178 assert_equals( 179 readyReg1.scope, 180 normalizeURL(matchedScope), 181 'matched registration should be returned' 182 ); 183 184 const longerReg = await navigator.serviceWorker.register(url, { scope: longerMatchedScope }); 185 t.add_cleanup(() => longerReg.unregister()); 186 187 const readyReg2 = await frame.contentWindow.navigator.serviceWorker.ready; 188 189 assert_equals( 190 readyReg2.scope, 191 normalizeURL(matchedScope), 192 'ready should only be resolved once' 193 ); 194 }, 'access ready after it has been resolved'); 195 196 promise_test(async t => { 197 const url1 = 'resources/empty-worker.js'; 198 const url2 = url1 + '?2'; 199 const matchedScope = 'resources/blank.html?ready-after-unregister'; 200 const reg1 = await service_worker_unregister_and_register(t, url1, matchedScope); 201 t.add_cleanup(() => reg1.unregister()); 202 203 await wait_for_state(t, reg1.installing, 'activating'); 204 205 const frame = await with_iframe(matchedScope); 206 t.add_cleanup(() => frame.remove()); 207 208 await reg1.unregister(); 209 210 // Ready promise should be pending, waiting for a new registration to arrive 211 const readyPromise = frame.contentWindow.navigator.serviceWorker.ready; 212 213 const reg2 = await navigator.serviceWorker.register(url2, { scope: matchedScope }); 214 t.add_cleanup(() => reg2.unregister()); 215 216 const readyReg = await readyPromise; 217 218 // Wait for registration update, since it comes from another global, the states are racy. 219 await wait_for_state(t, reg2.installing || reg2.waiting || reg2.active, 'activated'); 220 221 assert_equals(readyReg.active.scriptURL, reg2.active.scriptURL, 'Resolves with the second registration'); 222 assert_not_equals(reg1, reg2, 'Registrations should be different'); 223 }, 'resolve ready after unregistering');