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