registration-updateviacache.https.html (8105B)
1 <!DOCTYPE html> 2 <title>Service Worker: Registration-updateViaCache</title> 3 <meta name="timeout" content="long"> 4 <script src="/resources/testharness.js"></script> 5 <script src="resources/testharness-helpers.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="resources/test-helpers.sub.js"></script> 8 <script> 9 const UPDATE_VIA_CACHE_VALUES = [undefined, 'imports', 'all', 'none']; 10 const SCRIPT_URL = 'resources/update-max-aged-worker.py'; 11 const SCOPE = 'resources/blank.html'; 12 13 async function cleanup() { 14 const reg = await navigator.serviceWorker.getRegistration(SCOPE); 15 if (!reg) return; 16 if (reg.scope == new URL(SCOPE, location).href) { 17 return reg.unregister(); 18 }; 19 } 20 21 function getScriptTimes(sw, testName) { 22 return new Promise(resolve => { 23 navigator.serviceWorker.addEventListener('message', function listener(event) { 24 if (event.data.test !== testName) return; 25 navigator.serviceWorker.removeEventListener('message', listener); 26 resolve({ 27 mainTime: event.data.mainTime, 28 importTime: event.data.importTime 29 }); 30 }); 31 32 sw.postMessage(''); 33 }); 34 } 35 36 // Test creating registrations & triggering an update. 37 for (const updateViaCache of UPDATE_VIA_CACHE_VALUES) { 38 const testName = `register-with-updateViaCache-${updateViaCache}`; 39 40 promise_test(async t => { 41 await cleanup(); 42 43 const opts = {scope: SCOPE}; 44 45 if (updateViaCache) opts.updateViaCache = updateViaCache; 46 47 const reg = await navigator.serviceWorker.register( 48 `${SCRIPT_URL}?test=${testName}`, 49 opts 50 ); 51 52 assert_equals(reg.updateViaCache, updateViaCache || 'imports', "reg.updateViaCache"); 53 54 const sw = reg.installing || reg.waiting || reg.active; 55 await wait_for_state(t, sw, 'activated'); 56 const values = await getScriptTimes(sw, testName); 57 await reg.update(); 58 59 if (updateViaCache == 'all') { 60 assert_equals(reg.installing, null, "No new service worker"); 61 } 62 else { 63 const newWorker = reg.installing; 64 assert_true(!!newWorker, "New worker installing"); 65 const newValues = await getScriptTimes(newWorker, testName); 66 67 if (!updateViaCache || updateViaCache == 'imports') { 68 assert_not_equals(values.mainTime, newValues.mainTime, "Main script should have updated"); 69 assert_equals(values.importTime, newValues.importTime, "Imported script should be the same"); 70 } 71 else if (updateViaCache == 'none') { 72 assert_not_equals(values.mainTime, newValues.mainTime, "Main script should have updated"); 73 assert_not_equals(values.importTime, newValues.importTime, "Imported script should have updated"); 74 } 75 else { 76 // We should have handled all of the possible values for updateViaCache. 77 // If this runs, something's gone very wrong. 78 throw Error(`Unexpected updateViaCache value: ${updateViaCache}`); 79 } 80 } 81 82 await cleanup(); 83 }, testName); 84 } 85 86 // Test changing the updateViaCache value of an existing registration. 87 for (const updateViaCache1 of UPDATE_VIA_CACHE_VALUES) { 88 for (const updateViaCache2 of UPDATE_VIA_CACHE_VALUES) { 89 const testName = `register-with-updateViaCache-${updateViaCache1}-then-${updateViaCache2}`; 90 91 promise_test(async t => { 92 await cleanup(); 93 94 const fullScriptUrl = `${SCRIPT_URL}?test=${testName}`; 95 let opts = {scope: SCOPE}; 96 if (updateViaCache1) opts.updateViaCache = updateViaCache1; 97 98 const reg = await navigator.serviceWorker.register(fullScriptUrl, opts); 99 100 const sw = reg.installing; 101 await wait_for_state(t, sw, 'activated'); 102 const values = await getScriptTimes(sw, testName); 103 104 const frame = await with_iframe(SCOPE); 105 const reg_in_frame = await frame.contentWindow.navigator.serviceWorker.getRegistration(normalizeURL(SCOPE)); 106 assert_equals(reg_in_frame.updateViaCache, updateViaCache1 || 'imports', "reg_in_frame.updateViaCache"); 107 108 opts = {scope: SCOPE}; 109 if (updateViaCache2) opts.updateViaCache = updateViaCache2; 110 111 await navigator.serviceWorker.register(fullScriptUrl, opts); 112 113 const expected_updateViaCache = updateViaCache2 || 'imports'; 114 115 assert_equals(reg.updateViaCache, expected_updateViaCache, "reg.updateViaCache updated"); 116 // If the update happens via the cache, the scripts will come back byte-identical. 117 // We bypass the byte-identical check if the script URL has changed, but not if 118 // only the updateViaCache value has changed. 119 if (updateViaCache2 == 'all') { 120 assert_equals(reg.installing, null, "No new service worker"); 121 } 122 // If there's no change to the updateViaCache value, register should be a no-op. 123 // The default value should behave as 'imports'. 124 else if ((updateViaCache1 || 'imports') == (updateViaCache2 || 'imports')) { 125 assert_equals(reg.installing, null, "No new service worker"); 126 } 127 else { 128 const newWorker = reg.installing; 129 assert_true(!!newWorker, "New worker installing"); 130 const newValues = await getScriptTimes(newWorker, testName); 131 132 if (!updateViaCache2 || updateViaCache2 == 'imports') { 133 assert_not_equals(values.mainTime, newValues.mainTime, "Main script should have updated"); 134 assert_equals(values.importTime, newValues.importTime, "Imported script should be the same"); 135 } 136 else if (updateViaCache2 == 'none') { 137 assert_not_equals(values.mainTime, newValues.mainTime, "Main script should have updated"); 138 assert_not_equals(values.importTime, newValues.importTime, "Imported script should have updated"); 139 } 140 else { 141 // We should have handled all of the possible values for updateViaCache2. 142 // If this runs, something's gone very wrong. 143 throw Error(`Unexpected updateViaCache value: ${updateViaCache}`); 144 } 145 } 146 147 // Wait for all registration related tasks on |frame| to complete. 148 await wait_for_activation_on_sample_scope(t, frame.contentWindow); 149 // The updateViaCache change should have been propagated to all 150 // corresponding JS registration objects. 151 assert_equals(reg_in_frame.updateViaCache, expected_updateViaCache, "reg_in_frame.updateViaCache updated"); 152 frame.remove(); 153 154 await cleanup(); 155 }, testName); 156 } 157 } 158 159 // Test accessing updateViaCache of an unregistered registration. 160 for (const updateViaCache of UPDATE_VIA_CACHE_VALUES) { 161 const testName = `access-updateViaCache-after-unregister-${updateViaCache}`; 162 163 promise_test(async t => { 164 await cleanup(); 165 166 const opts = {scope: SCOPE}; 167 168 if (updateViaCache) opts.updateViaCache = updateViaCache; 169 170 const reg = await navigator.serviceWorker.register( 171 `${SCRIPT_URL}?test=${testName}`, 172 opts 173 ); 174 175 const expected_updateViaCache = updateViaCache || 'imports'; 176 assert_equals(reg.updateViaCache, expected_updateViaCache, "reg.updateViaCache"); 177 178 await reg.unregister(); 179 180 // Keep the original value. 181 assert_equals(reg.updateViaCache, expected_updateViaCache, "reg.updateViaCache"); 182 183 await cleanup(); 184 }, testName); 185 } 186 187 promise_test(async t => { 188 await cleanup(); 189 t.add_cleanup(cleanup); 190 191 const registration = await navigator.serviceWorker.register( 192 'resources/empty.js', 193 {scope: SCOPE}); 194 assert_equals(registration.updateViaCache, 'imports', 195 'before update attempt'); 196 197 const fail = navigator.serviceWorker.register( 198 'resources/malformed-worker.py?parse-error', 199 {scope: SCOPE, updateViaCache: 'none'}); 200 await promise_rejects_js(t, TypeError, fail); 201 assert_equals(registration.updateViaCache, 'imports', 202 'after update attempt'); 203 }, 'updateViaCache is not updated if register() rejects'); 204 </script>