Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
| 2 <title>Service Worker: the fallback behavior of FetchEvent</title> | 2 <title>Service Worker: the fallback behavior of FetchEvent</title> |
| 3 <script src="/resources/testharness.js"></script> | 3 <script src="/resources/testharness.js"></script> |
| 4 <script src="/resources/testharnessreport.js"></script> | 4 <script src="/resources/testharnessreport.js"></script> |
| 5 <script src="/common/get-host-info.sub.js"></script> | 5 <script src="/common/get-host-info.sub.js"></script> |
| 6 <script src="resources/test-helpers.sub.js?pipe=sub"></script> | 6 <script src="resources/test-helpers.sub.js"></script> |
| 7 <script> | 7 <script> |
| 8 var expected_urls = []; | 8 function get_fetched_urls(worker) { |
| 9 | 9 return new Promise(function(resolve) { |
| 10 function xhr_fail_test(frame, url) { | 10 var channel = new MessageChannel(); |
| 11 expected_urls.push(url); | 11 channel.port1.onmessage = function(msg) { resolve(msg); }; |
| 12 return new Promise(function(resolve, reject) { | 12 worker.postMessage({port: channel.port2}, [channel.port2]); |
| 13 frame.contentWindow.xhr(url) | |
| 14 .then(function(){ | |
| 15 reject(url + ' should fail.'); | |
| 16 }) | |
| 17 .catch(function(){ | |
| 18 resolve(); | |
| 19 }); | |
| 20 }); | 13 }); |
| 21 } | 14 } |
| 22 | 15 |
| 23 function xhr_succeed_test(frame, url) { | 16 function check_urls(worker, expected_requests) { |
| 24 expected_urls.push(url); | 17 return get_fetched_urls(worker) |
| 25 return new Promise(function(resolve, reject) { | 18 .then(function(msg) { |
| 26 frame.contentWindow.xhr(url) | 19 var requests = msg.data.requests; |
| 27 .then(function(){ | 20 assert_object_equals(requests, expected_requests); |
| 28 resolve(); | |
| 29 }) | |
| 30 .catch(function(){ | |
| 31 reject(url + ' should succeed.'); | |
| 32 }); | |
| 33 }); | 21 }); |
| 34 } | 22 } |
| 35 | 23 |
| 36 async_test(function(t) { | 24 var path = new URL(".", window.location).pathname; |
| 37 var path = new URL(".", window.location).pathname; | 25 var SCOPE = 'resources/fetch-request-fallback-iframe.html'; |
| 38 var SCOPE = 'resources/fetch-request-fallback-iframe.html'; | 26 var SCRIPT = 'resources/fetch-request-fallback-worker.js'; |
| 39 var SCRIPT = 'resources/fetch-request-fallback-worker.js'; | 27 var host_info = get_host_info(); |
| 40 var host_info = get_host_info(); | 28 var BASE_URL = host_info['HTTPS_ORIGIN'] + |
| 41 var BASE_URL = host_info['HTTPS_ORIGIN'] + | 29 path + 'resources/fetch-access-control.py?'; |
| 42 path + 'resources/fetch-access-control.py?'; | 30 var BASE_PNG_URL = BASE_URL + 'PNGIMAGE&'; |
| 43 var OTHER_BASE_URL = host_info['HTTPS_REMOTE_ORIGIN'] + | 31 var OTHER_BASE_URL = host_info['HTTPS_REMOTE_ORIGIN'] + |
| 44 path + 'resources/fetch-access-control.py?'; | 32 path + 'resources/fetch-access-control.py?'; |
| 45 var REDIRECT_URL = host_info['HTTPS_ORIGIN'] + | 33 var OTHER_BASE_PNG_URL = OTHER_BASE_URL + 'PNGIMAGE&'; |
| 46 path + 'resources/redirect.py?Redirect='; | 34 var REDIRECT_URL = host_info['HTTPS_ORIGIN'] + |
| 47 var frame; | 35 path + 'resources/redirect.py?Redirect='; |
| 48 var worker; | 36 var register; |
| 49 service_worker_unregister_and_register(t, SCRIPT, SCOPE) | 37 |
| 50 .then(function(registration) { | 38 promise_test(function(t) { |
| 51 worker = registration.installing; | 39 var registration; |
| 52 return wait_for_state(t, worker, 'activated'); | 40 var worker; |
| 53 }) | 41 |
| 54 .then(function() { return with_iframe(SCOPE); }) | 42 register = service_worker_unregister_and_register(t, SCRIPT, SCOPE) |
| 55 .then(function(f) { | 43 .then(function(r) { |
| 56 frame = f; | 44 registration = r; |
| 57 return xhr_succeed_test(frame, BASE_URL); | 45 worker = registration.installing; |
| 58 }) | 46 return wait_for_state(t, worker, 'activated'); |
| 59 .then(function(f) { | 47 }) |
| 60 return xhr_fail_test(frame, OTHER_BASE_URL); | 48 .then(function() { return with_iframe(SCOPE); }) |
| 61 }) | 49 .then(function(frame) { |
| 62 .then(function(f) { | 50 // This test should not be considered complete until after the service |
| 63 return xhr_succeed_test(frame, OTHER_BASE_URL + 'ACAOrigin=*'); | 51 // worker has been unregistered. Currently, `testharness.js` does not |
| 64 }) | 52 // support asynchronous global "tear down" logic, so this must be |
| 65 .then(function(f) { | 53 // expressed using a dedicated `promise_test`. Because the other |
| 66 return xhr_succeed_test(frame, | 54 // sub-tests in this file are declared synchronously, this test will be |
| 67 REDIRECT_URL + encodeURIComponent(BASE_URL)); | 55 // the final test executed. |
| 68 }) | 56 promise_test(function(t) { |
| 69 .then(function() { | 57 t.add_cleanup(function() { |
| 70 return xhr_fail_test( | 58 frame.remove(); |
| 71 frame, | 59 }); |
| 72 REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL)); | 60 return registration.unregister(); |
| 73 }) | 61 }, 'restore global state'); |
| 74 .then(function() { | 62 |
| 75 return xhr_succeed_test( | 63 return {frame: frame, worker: worker}; |
| 76 frame, | 64 }); |
| 77 REDIRECT_URL + | 65 |
| 78 encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*')); | 66 return register; |
| 79 }) | 67 }, 'initialize global state'); |
| 80 .then(function() { | 68 |
| 81 return new Promise(function(resolve) { | 69 function promise_frame_test(body, desc) { |
| 82 var channel = new MessageChannel(); | 70 promise_test(function(test) { |
| 83 channel.port1.onmessage = t.step_func(function(msg) { | 71 return register.then(function(result) { |
| 84 frame.remove(); | 72 return body(test, result.frame, result.worker); |
| 85 resolve(msg); | 73 }); |
| 86 }); | 74 }, desc); |
| 87 worker.postMessage({port: channel.port2}, [channel.port2]); | 75 } |
| 88 }); | 76 |
| 89 }) | 77 promise_frame_test(function(t, frame, worker) { |
| 90 .then(function(msg) { | 78 return check_urls( |
| 91 var requests = msg.data.requests; | 79 worker, |
| 92 assert_equals(requests.length, expected_urls.length + 1, | 80 [{ |
| 93 'The count of the requests which are passed to the ' + | 81 url: host_info['HTTPS_ORIGIN'] + path + SCOPE, |
| 94 'ServiceWorker must be correct.'); | 82 mode: 'navigate' |
| 95 assert_equals(requests[0].url, new URL(SCOPE, location).toString(), | 83 }]); |
| 96 'The first request to the SW must be the request for ' + | 84 }, 'The SW must intercept the request for a main resource.'); |
| 97 'the page.'); | 85 |
| 98 assert_equals(requests[0].mode, 'navigate', | 86 promise_frame_test(function(t, frame, worker) { |
| 99 'The mode of the first request to the SW must be ' + | 87 return frame.contentWindow.xhr(BASE_URL) |
| 100 'navigate'); | 88 .then(function() { |
| 101 for (var i = 0; i < expected_urls.length; ++i) { | 89 return check_urls( |
| 102 assert_equals(requests[i + 1].url, expected_urls[i], | 90 worker, |
| 103 'The URL of the request which was passed from XHR ' + | 91 [{ url: BASE_URL, mode: 'cors' }]); |
| 104 'to the ServiceWorker must be correct.'); | 92 }); |
| 105 assert_equals(requests[i + 1].mode, 'cors', | 93 }, 'The SW must intercept the request of same origin XHR.'); |
| 106 'The mode of the request which was passed from XHR ' + | 94 |
| 107 'to the ServiceWorker must be cors.'); | 95 promise_frame_test(function(t, frame, worker) { |
| 108 } | 96 return promise_rejects( |
| 109 service_worker_unregister_and_done(t, SCOPE); | 97 t, |
| 110 }) | 98 null, |
| 111 .catch(unreached_rejection(t)); | 99 frame.contentWindow.xhr(OTHER_BASE_URL), |
| 112 }, 'Verify the fallback behavior of FetchEvent'); | 100 'SW fallbacked CORS-unsupported other origin XHR should fail.') |
| 101 .then(function() { | |
| 102 return check_urls( | |
| 103 worker, | |
| 104 [{ url: OTHER_BASE_URL, mode: 'cors' }]); | |
| 105 }); | |
| 106 }, 'The SW must intercept the request of CORS-unsupported other origin XHR.'); | |
| 107 | |
| 108 promise_frame_test(function(t, frame, worker) { | |
| 109 return frame.contentWindow.xhr(OTHER_BASE_URL + 'ACAOrigin=*') | |
| 110 .then(function() { | |
| 111 return check_urls( | |
| 112 worker, | |
| 113 [{ url: OTHER_BASE_URL + 'ACAOrigin=*', mode: 'cors' }]); | |
| 114 }) | |
| 115 }, 'The SW must intercept the request of CORS-supported other origin XHR.'); | |
| 116 | |
| 117 promise_frame_test(function(t, frame, worker) { | |
| 118 return frame.contentWindow.xhr( | |
| 119 REDIRECT_URL + encodeURIComponent(BASE_URL)) | |
| 120 .then(function() { | |
| 121 return check_urls( | |
| 122 worker, | |
| 123 [{ | |
| 124 url: REDIRECT_URL + encodeURIComponent(BASE_URL), | |
| 125 mode: 'cors' | |
| 126 }]); | |
| 127 }); | |
| 128 }, 'The SW must intercept only the first request of redirected XHR.'); | |
| 129 | |
| 130 promise_frame_test(function(t, frame, worker) { | |
| 131 return promise_rejects( | |
| 132 t, | |
| 133 null, | |
|
Marijn Kruisselbrink
2017/05/09 18:09:09
my mistake, but as this landed, annevk landed a ch
| |
| 134 frame.contentWindow.xhr( | |
| 135 REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL)), | |
| 136 'SW fallbacked XHR which is redirected to CORS-unsupported ' + | |
| 137 'other origin should fail.') | |
| 138 .then(function() { | |
| 139 return check_urls( | |
| 140 worker, | |
| 141 [{ | |
| 142 url: REDIRECT_URL + encodeURIComponent(OTHER_BASE_URL), | |
| 143 mode: 'cors' | |
| 144 }]); | |
| 145 }); | |
| 146 }, 'The SW must intercept only the first request for XHR which is' + | |
| 147 ' redirected to CORS-unsupported other origin.'); | |
| 148 | |
| 149 promise_frame_test(function(t, frame, worker) { | |
| 150 return frame.contentWindow.xhr( | |
| 151 REDIRECT_URL + | |
| 152 encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*')) | |
| 153 .then(function() { | |
| 154 return check_urls( | |
| 155 worker, | |
| 156 [{ | |
| 157 url: REDIRECT_URL + | |
| 158 encodeURIComponent(OTHER_BASE_URL + 'ACAOrigin=*'), | |
| 159 mode: 'cors' | |
| 160 }]); | |
| 161 }); | |
| 162 }, 'The SW must intercept only the first request for XHR which is ' + | |
| 163 'redirected to CORS-supported other origin.'); | |
| 164 | |
| 165 promise_frame_test(function(t, frame, worker) { | |
| 166 return frame.contentWindow.load_image(BASE_PNG_URL, '') | |
| 167 .then(function() { | |
| 168 return check_urls( | |
| 169 worker, | |
| 170 [{ url: BASE_PNG_URL, mode: 'no-cors' }]); | |
| 171 }); | |
| 172 }, 'The SW must intercept the request for image.'); | |
| 173 | |
| 174 promise_frame_test(function(t, frame, worker) { | |
| 175 return frame.contentWindow.load_image(OTHER_BASE_PNG_URL, '') | |
| 176 .then(function() { | |
| 177 return check_urls( | |
| 178 worker, | |
| 179 [{ url: OTHER_BASE_PNG_URL, mode: 'no-cors' }]); | |
| 180 }); | |
| 181 }, 'The SW must intercept the request for other origin image.'); | |
| 182 | |
| 183 promise_frame_test(function(t, frame, worker) { | |
| 184 return promise_rejects( | |
| 185 t, | |
| 186 null, | |
| 187 frame.contentWindow.load_image(OTHER_BASE_PNG_URL, 'anonymous'), | |
| 188 'SW fallbacked CORS-unsupported other origin image request ' + | |
| 189 'should fail.') | |
| 190 .then(function() { | |
| 191 return check_urls( | |
| 192 worker, | |
| 193 [{ url: OTHER_BASE_PNG_URL, mode: 'cors' }]); | |
| 194 }) | |
| 195 }, 'The SW must intercept the request for CORS-unsupported other ' + | |
| 196 'origin image.'); | |
| 197 | |
| 198 promise_frame_test(function(t, frame, worker) { | |
| 199 return frame.contentWindow.load_image( | |
| 200 OTHER_BASE_PNG_URL + 'ACAOrigin=*', 'anonymous') | |
| 201 .then(function() { | |
| 202 return check_urls( | |
| 203 worker, | |
| 204 [{ url: OTHER_BASE_PNG_URL + 'ACAOrigin=*', mode: 'cors' }]); | |
| 205 }); | |
| 206 }, 'The SW must intercept the request for CORS-supported other ' + | |
| 207 'origin image.'); | |
| 208 | |
| 209 promise_frame_test(function(t, frame, worker) { | |
| 210 return frame.contentWindow.load_image( | |
| 211 REDIRECT_URL + encodeURIComponent(BASE_PNG_URL), '') | |
| 212 .catch(function() { | |
| 213 assert_unreached( | |
| 214 'SW fallbacked redirected image request should succeed.'); | |
| 215 }) | |
| 216 .then(function() { | |
| 217 return check_urls( | |
| 218 worker, | |
| 219 [{ | |
| 220 url: REDIRECT_URL + encodeURIComponent(BASE_PNG_URL), | |
| 221 mode: 'no-cors' | |
| 222 }]); | |
| 223 }); | |
| 224 }, 'The SW must intercept only the first request for redirected ' + | |
| 225 'image resource.'); | |
| 226 | |
| 227 promise_frame_test(function(t, frame, worker) { | |
| 228 return frame.contentWindow.load_image( | |
| 229 REDIRECT_URL + encodeURIComponent(OTHER_BASE_PNG_URL), '') | |
| 230 .catch(function() { | |
| 231 assert_unreached( | |
| 232 'SW fallbacked image request which is redirected to ' + | |
| 233 'other origin should succeed.'); | |
| 234 }) | |
| 235 .then(function() { | |
| 236 return check_urls( | |
| 237 worker, | |
| 238 [{ | |
| 239 url: REDIRECT_URL + encodeURIComponent(OTHER_BASE_PNG_URL), | |
| 240 mode: 'no-cors' | |
| 241 }]); | |
| 242 }) | |
| 243 }, 'The SW must intercept only the first request for image ' + | |
| 244 'resource which is redirected to other origin.'); | |
| 245 | |
| 246 promise_frame_test(function(t, frame, worker) { | |
| 247 return promise_rejects( | |
| 248 t, | |
| 249 null, | |
| 250 frame.contentWindow.load_image( | |
| 251 REDIRECT_URL + encodeURIComponent(OTHER_BASE_PNG_URL), | |
| 252 'anonymous'), | |
| 253 'SW fallbacked image request which is redirected to ' + | |
| 254 'CORS-unsupported other origin should fail.') | |
| 255 .then(function() { | |
| 256 return check_urls( | |
| 257 worker, | |
| 258 [{ | |
| 259 url: REDIRECT_URL + encodeURIComponent(OTHER_BASE_PNG_URL), | |
| 260 mode: 'cors' | |
| 261 }]); | |
| 262 }); | |
| 263 }, 'The SW must intercept only the first request for image ' + | |
| 264 'resource which is redirected to CORS-unsupported other origin.'); | |
| 265 | |
| 266 promise_frame_test(function(t, frame, worker) { | |
| 267 return frame.contentWindow.load_image( | |
| 268 REDIRECT_URL + | |
| 269 encodeURIComponent(OTHER_BASE_PNG_URL + 'ACAOrigin=*'), | |
| 270 'anonymous') | |
| 271 .then(function() { | |
| 272 return check_urls( | |
| 273 worker, | |
| 274 [{ | |
| 275 url: REDIRECT_URL + | |
| 276 encodeURIComponent(OTHER_BASE_PNG_URL + 'ACAOrigin=*'), | |
| 277 mode: 'cors' | |
| 278 }]); | |
| 279 }); | |
| 280 }, 'The SW must intercept only the first request for image ' + | |
| 281 'resource which is redirected to CORS-supported other origin.'); | |
| 113 </script> | 282 </script> |
| OLD | NEW |