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 |