basic.sub.https.html (10346B)
1 <!DOCTYPE html> 2 <meta name="timeout" content="long"> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <script src="/common/utils.js"></script> 6 <script src="/common/dispatcher/dispatcher.js"></script> 7 <script src="../../../resources/utils.js"></script> 8 <script src="../../resources/utils.sub.js"></script> 9 <script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script> 10 11 <meta name="variant" content="?origin=same-site&sw=fetch-handler"> 12 <meta name="variant" content="?origin=same-site&sw=fetch-handler-to-fallback"> 13 <meta name="variant" content="?origin=same-site&sw=fetch-handler-modify-url"> 14 <meta name="variant" content="?origin=same-site&sw=fetch-handler-modify-referrer"> 15 <meta name="variant" content="?origin=same-site&sw=fetch-handler-navigation-preload"> 16 <meta name="variant" content="?origin=same-site&sw=no-fetch-handler"> 17 <meta name="variant" content="?origin=same-site&sw=no-controller"> 18 <meta name="variant" content="?origin=same-site&sw=race-fetch-handler"> 19 <meta name="variant" content="?origin=same-site&sw=race-fetch-handler-to-fallback"> 20 <meta name="variant" content="?origin=same-site&sw=race-fetch-handler-modify-url"> 21 22 <meta name="variant" content="?origin=same-site&sw=fetch-handler&clientId"> 23 <meta name="variant" content="?origin=same-site&sw=fetch-handler-to-fallback&clientId"> 24 <meta name="variant" content="?origin=same-site&sw=fetch-handler-modify-url&clientId"> 25 <meta name="variant" content="?origin=same-site&sw=fetch-handler-modify-referrer&clientId"> 26 <meta name="variant" content="?origin=same-site&sw=no-fetch-handler&clientId"> 27 <meta name="variant" content="?origin=same-site&sw=no-controller&clientId"> 28 29 <meta name="variant" content="?origin=cross-site&sw=fetch-handler"> 30 <meta name="variant" content="?origin=cross-site&sw=fetch-handler-to-fallback"> 31 <meta name="variant" content="?origin=cross-site&sw=no-fetch-handler"> 32 <meta name="variant" content="?origin=cross-site&sw=no-controller"> 33 34 <meta name="variant" content="?origin=cross-site&sw=fetch-handler&clientId"> 35 <meta name="variant" content="?origin=cross-site&sw=fetch-handler-to-fallback&clientId"> 36 <meta name="variant" content="?origin=cross-site&sw=no-fetch-handler&clientId"> 37 <meta name="variant" content="?origin=cross-site&sw=no-controller&clientId"> 38 39 <script> 40 setup(() => assertSpeculationRulesIsSupported()); 41 42 // TODO(https://crbug.com/404573972): Rename "same-site" tests to 43 // "same-origin", and add same-site cross-origin tests. 44 const originOption = new URL(location.href).searchParams.get('origin'); 45 const originalSwOption = new URL(location.href).searchParams.get('sw'); 46 47 // Used when checking the resulting behavior. 48 // In the following race-network cases, race network requests work in parallel 49 // with fetch handlers and the checked observed behavior are the same with 50 // non-race-network cases. 51 let swOption = originalSwOption; 52 if (originalSwOption === 'race-fetch-handler') { 53 swOption = 'fetch-handler'; 54 } 55 if (originalSwOption === 'race-fetch-handler-to-fallback') { 56 swOption = 'fetch-handler-to-fallback'; 57 } 58 59 promise_test(async t => { 60 const hostname = originOption === 'cross-site' ? '{{hosts[alt][www]}}' 61 : undefined; 62 const win = await spawnWindow(t, { protocol: 'https', hostname: hostname }); 63 const nextUrl = win.getExecutorURL({ executor: 'counting-executor.py', protocol: 'https', page: 2 }); 64 if (swOption === 'race-fetch-handler-modify-url') { 65 // We set: 66 // - For the race network request: 1.5 sec delay (here). 67 // - For the network request from the fetch handler: 0.5 sec delay (in 68 // `basic-service-worker.js`). 69 // So that: 70 // - The fetch handler wins and the modified request is used for serving. 71 // - The requests return responses after both of the requests reach the 72 // server and are recorded in the server-side request counts. 73 nextUrl.searchParams.set('delay', '1500'); 74 } 75 76 const swUrl = new URL('../../resources/basic-service-worker.js?sw=' + originalSwOption, location.href).href; 77 78 // Register a SW not controlling any pages below, just to confirm such 79 // unrelated SWs in the same-origin doesn't affect the behavior. 80 const reg_unrelated = await service_worker_unregister_and_register( 81 t, swUrl, nextUrl + '&unrelated'); 82 await wait_for_state(t, reg_unrelated.installing, 'activated'); 83 84 // Register a SW for `nextUrl`. 85 let sw; 86 if (swOption !== 'no-controller') { 87 const reg = await service_worker_unregister_and_register( 88 t, swUrl, nextUrl); 89 sw = reg.installing; 90 await wait_for_state(t, sw, 'activated'); 91 } 92 93 // Start speculation rules prefetch and navigate to the URL. 94 await win.forceSinglePrefetch(nextUrl); 95 96 await win.navigate(nextUrl); 97 98 const requestCount = await (await fetch(nextUrl + '&check')).json(); 99 100 const headers = await win.execute_script(() => { 101 return requestHeaders; 102 }, []); 103 104 const controllerUrl = await win.execute_script(() => { 105 return navigator.serviceWorker.controller?.scriptURL; 106 }, []); 107 108 if (swOption === 'no-controller') { 109 assert_equals(controllerUrl, undefined); 110 } else { 111 // The navigated page should be controlled by the ServiceWorker, 112 // regardless of whether prefetch is performed/used. 113 assert_equals(controllerUrl, swUrl); 114 } 115 116 let interceptedRequests = []; 117 if (sw) { 118 const messagePromise = new Promise(resolve => { 119 navigator.serviceWorker.addEventListener('message', (event) => { 120 resolve(event.data); 121 }, {once: true}); 122 }); 123 sw.postMessage('getInterceptedRequests'); 124 interceptedRequests = await messagePromise; 125 } 126 127 // Current Chromium's expected behavior: 128 // prefetch works when 129 // - there are no controlling service worker, or 130 // - same-site prefetches with controlling service worker. 131 if (swOption === 'no-controller' || 132 (originOption === 'same-site' && 133 (swOption === 'fetch-handler' || 134 swOption === 'fetch-handler-to-fallback' || 135 swOption === 'no-fetch-handler'))) { 136 assert_prefetched(headers, "Prefetched result should be served."); 137 assert_equals(requestCount.prefetch, 1, 138 'a prefetch request should be sent to the server.'); 139 assert_equals(requestCount.nonPrefetch, 0, 140 'non-prefetch requests should not be sent to the server.'); 141 assert_prefetched(headers, "Prefetched result should be served."); 142 143 if (swOption === 'no-controller' || swOption === 'no-fetch-handler') { 144 assert_equals(interceptedRequests.length, 0); 145 } else { 146 assert_equals(interceptedRequests.length, 1); 147 assert_intercept_prefetch(interceptedRequests[0], nextUrl); 148 } 149 } else if (originOption === 'same-site' && 150 swOption === 'fetch-handler-navigation-preload') { 151 // Check the behavior of `FetchEvent.preloadResponse` for prefetching 152 // requests. 153 // Here we allow >1 intercepted requests to check `preloadResponse` 154 // behavior even if e.g. prefetched response isn't served and there is 155 // second intercepted request (=non-prefetch navigation request). 156 assert_greater_than_equal(interceptedRequests.length, 1); 157 // The first intercepted request is a prefetch request. 158 assert_intercept_prefetch(interceptedRequests[0], nextUrl); 159 assert_equals(interceptedRequests[0].preloadResponse, 'resolved', 160 'preloadResponse should be resolved'); 161 162 assert_served_by_navigation_preload(headers); 163 assert_prefetched(headers, "Prefetched result should be served."); 164 assert_equals(requestCount.prefetch, 1, 165 'a prefetch request should be sent to the server.'); 166 assert_equals(requestCount.nonPrefetch, 0, 167 'non-prefetch requests should not be sent to the server.'); 168 } else if (originOption === 'same-site' && 169 (swOption === 'fetch-handler-modify-url' || 170 swOption === 'fetch-handler-modify-referrer' || 171 swOption === 'race-fetch-handler-modify-url')) { 172 // When the ServiceWorker modifies the prefetch request 173 // (`fetch-handler-modify-*` cases below), still prefetch can work and be 174 // served, but Sec-Purpose header is dropped 175 // because it's a https://fetch.spec.whatwg.org/#forbidden-request-header 176 assert_prefetched_without_sec_purpose(headers, 177 "Prefetched result should be served without Sec-Purpose."); 178 // `requestCount` checks the Sec-Purpose header so the prefetch request 179 // without Sec-Purpose is counted as nonPrefetch here. 180 assert_equals(requestCount.nonPrefetch, 1, 181 'a prefetch request without Sec-Purpose should be sent to the server.'); 182 if (swOption === 'race-fetch-handler-modify-url') { 183 // This racing network request is not used. 184 assert_equals(requestCount.prefetch, 1, 185 'Race network request should be sent to the server with Sec-Purpose.'); 186 } else { 187 assert_equals(requestCount.prefetch, 0, 188 'Other requests with Sec-Purpose should not be sent to the server.'); 189 } 190 191 // Check the modified URL/referrer to check if the prefetched and 192 // ServiceWorker-modified response is actually served. 193 if (swOption === 'fetch-handler-modify-url') { 194 assert_equals( 195 await win.execute_script(() => { return requestUrl; }, []), 196 nextUrl + '&intercepted=true', 197 'URL should be modified by ServiceWorker'); 198 } 199 if (swOption === 'fetch-handler-modify-referrer') { 200 assert_equals( 201 headers.referer, 202 new URL('/intercepted', location.href).href, 203 'Referrer should be modified by ServiceWorker'); 204 } 205 206 assert_equals(interceptedRequests.length, 1); 207 assert_intercept_prefetch(interceptedRequests[0], nextUrl); 208 } else { 209 assert_not_prefetched(headers, "Prefetched result should not be served."); 210 assert_equals(requestCount.nonPrefetch, 1, 211 'a non-prefetch request should be sent to the server.'); 212 assert_equals(requestCount.prefetch, 0, 213 'prefetch requests should not be sent to the server.'); 214 215 if (swOption === 'no-fetch-handler') { 216 assert_equals(interceptedRequests.length, 0); 217 } else { 218 assert_equals(interceptedRequests.length, 1); 219 assert_intercept_non_prefetch(interceptedRequests[0], nextUrl); 220 } 221 } 222 223 }, "Prefetch with ServiceWorker (" + originalSwOption + ")"); 224 </script>