OLD | NEW |
| (Empty) |
1 <!DOCTYPE html> | |
2 <title>Service Worker: Navigation redirection</title> | |
3 <script src="../resources/testharness.js"></script> | |
4 <script src="../resources/testharnessreport.js"></script> | |
5 <script src="../resources/get-host-info.js?pipe=sub"></script> | |
6 <script src="resources/test-helpers.js"></script> | |
7 <body> | |
8 <script> | |
9 | |
10 var host_info = get_host_info(); | |
11 | |
12 // This test registers three Service Workers at SCOPE1, SCOPE2 and | |
13 // OTHER_ORIGIN_SCOPE. And checks the redirected page's URL and the requests | |
14 // which are intercepted by Service Worker while loading redirect page. | |
15 var BASE_URL = host_info['HTTP_ORIGIN'] + base_path(); | |
16 var OTHER_BASE_URL = host_info['HTTP_REMOTE_ORIGIN'] + base_path(); | |
17 | |
18 var SCOPE1 = BASE_URL + 'resources/navigation-redirect-scope1.php?'; | |
19 var SCOPE2 = BASE_URL + 'resources/navigation-redirect-scope2.php?'; | |
20 var OUT_SCOPE = BASE_URL + 'resources/navigation-redirect-out-scope.php?'; | |
21 var SCRIPT = 'resources/navigation-redirect-worker.js'; | |
22 | |
23 var OTHER_ORIGIN_IFRAME_URL = | |
24 OTHER_BASE_URL + 'resources/navigation-redirect-other-origin.html'; | |
25 var OTHER_ORIGIN_SCOPE = | |
26 OTHER_BASE_URL + 'resources/navigation-redirect-scope1.php?'; | |
27 var OTHER_ORIGIN_OUT_SCOPE = | |
28 OTHER_BASE_URL + 'resources/navigation-redirect-out-scope.php?'; | |
29 | |
30 var workers; | |
31 var other_origin_frame; | |
32 var setup_environment_promise; | |
33 var message_resolvers = {}; | |
34 var next_message_id = 0; | |
35 | |
36 function setup_environment(t) { | |
37 if (setup_environment_promise) | |
38 return setup_environment_promise; | |
39 setup_environment_promise = | |
40 with_iframe(OTHER_ORIGIN_IFRAME_URL) | |
41 .then(function(f) { | |
42 // In this frame we register a Service Worker at OTHER_ORIGIN_SCOPE. | |
43 // And will use this frame to communicate with the worker. | |
44 other_origin_frame = f; | |
45 return Promise.all( | |
46 [service_worker_unregister_and_register(t, SCRIPT, SCOPE1), | |
47 service_worker_unregister_and_register(t, SCRIPT, SCOPE2)]); | |
48 }) | |
49 .then(function(registrations) { | |
50 add_completion_callback(function() { | |
51 registrations[0].unregister(); | |
52 registrations[1].unregister(); | |
53 send_to_iframe(other_origin_frame, 'unregister') | |
54 .then(function() { other_origin_frame.remove(); }); | |
55 }); | |
56 workers = registrations.map(get_effective_worker); | |
57 return Promise.all([ | |
58 wait_for_state(t, workers[0], 'activated'), | |
59 wait_for_state(t, workers[1], 'activated'), | |
60 // This promise will resolve when |wait_for_worker_promise| | |
61 // in OTHER_ORIGIN_IFRAME_URL resolves. | |
62 send_to_iframe(other_origin_frame, 'wait_for_worker')]); | |
63 }); | |
64 return setup_environment_promise; | |
65 } | |
66 | |
67 function get_effective_worker(registration) { | |
68 if (registration.active) | |
69 return registration.active; | |
70 if (registration.waiting) | |
71 return registration.waiting; | |
72 if (registration.installing) | |
73 return registration.installing; | |
74 } | |
75 | |
76 function check_all_intercepted_urls(expected_urls) { | |
77 return Promise.all( | |
78 [ | |
79 // Gets the request URLs which are intercepted by SCOPE1's SW. | |
80 get_intercepted_urls(workers[0]), | |
81 // Gets the request URLs which are intercepted by SCOPE2's SW. | |
82 get_intercepted_urls(workers[1]), | |
83 // Gets the request URLs which are intercepted by OTHER_ORIGIN_SCOPE's | |
84 // SW. This promise will resolve when get_intercepted_urls() in | |
85 // OTHER_ORIGIN_IFRAME_URL resolves. | |
86 send_to_iframe(other_origin_frame, 'get_intercepted_urls') | |
87 ]) | |
88 .then(function(urls) { | |
89 assert_object_equals( | |
90 urls, expected_urls, | |
91 'Intercepted URLs should match.'); | |
92 }); | |
93 } | |
94 | |
95 function test_redirect(url, expected_last_url, | |
96 expected_intercepted_urls) { | |
97 var message_promise = new Promise(function(resolve) { | |
98 // A message which ID is 'last_url' will be sent from the iframe. | |
99 message_resolvers['last_url'] = resolve; | |
100 }); | |
101 return with_iframe(url) | |
102 .then(function(f) { | |
103 f.remove(); | |
104 return check_all_intercepted_urls(expected_intercepted_urls); | |
105 }) | |
106 .then(function() { return message_promise; }) | |
107 .then(function(last_url) { | |
108 assert_equals( | |
109 last_url, expected_last_url, | |
110 'Last URL should match.'); | |
111 }); | |
112 } | |
113 | |
114 window.addEventListener('message', on_message, false); | |
115 | |
116 function on_message(e) { | |
117 if (e.origin != host_info['HTTP_REMOTE_ORIGIN'] && | |
118 e.origin != host_info['HTTP_ORIGIN'] ) { | |
119 console.error('invalid origin: ' + e.origin); | |
120 return; | |
121 } | |
122 var resolve = message_resolvers[e.data.id]; | |
123 delete message_resolvers[e.data.id]; | |
124 resolve(e.data.result); | |
125 } | |
126 | |
127 function send_to_iframe(frame, message) { | |
128 var message_id = next_message_id++; | |
129 return new Promise(function(resolve) { | |
130 message_resolvers[message_id] = resolve; | |
131 frame.contentWindow.postMessage( | |
132 {id: message_id, message: message}, | |
133 host_info['HTTP_REMOTE_ORIGIN']); | |
134 }); | |
135 } | |
136 | |
137 function get_intercepted_urls(worker) { | |
138 return new Promise(function(resolve) { | |
139 var channel = new MessageChannel(); | |
140 channel.port1.onmessage = function(msg) { resolve(msg.data.urls); }; | |
141 worker.postMessage({port: channel.port2}, [channel.port2]); | |
142 }); | |
143 } | |
144 | |
145 // Normal redirect. | |
146 promise_test(function(t) { | |
147 return setup_environment(t).then(function() { | |
148 return test_redirect( | |
149 OUT_SCOPE + 'url=' + encodeURIComponent(SCOPE1), | |
150 SCOPE1, | |
151 [[SCOPE1], [], []]); | |
152 }); | |
153 }, 'Normal redirect to same-origin scope.'); | |
154 promise_test(function(t) { | |
155 return setup_environment(t).then(function() { | |
156 return test_redirect( | |
157 OUT_SCOPE + 'url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE), | |
158 OTHER_ORIGIN_SCOPE, | |
159 [[], [], [OTHER_ORIGIN_SCOPE]]); | |
160 }); | |
161 }, 'Normal redirect to other-origin scope.'); | |
162 | |
163 // SW fallbacked redirect. SW doesn't handle the fetch request. | |
164 promise_test(function(t) { | |
165 return setup_environment(t).then(function() { | |
166 return test_redirect( | |
167 SCOPE1 + 'url=' + encodeURIComponent(OUT_SCOPE), | |
168 OUT_SCOPE, | |
169 [[SCOPE1 + 'url=' + encodeURIComponent(OUT_SCOPE)], [], []]); | |
170 }); | |
171 }, 'SW-fallbacked redirect to same-origin out-scope.'); | |
172 promise_test(function(t) { | |
173 return setup_environment(t).then(function() { | |
174 return test_redirect( | |
175 SCOPE1 + 'url=' + encodeURIComponent(SCOPE1), | |
176 SCOPE1, | |
177 [[SCOPE1 + 'url=' + encodeURIComponent(SCOPE1), SCOPE1], [], []]); | |
178 }); | |
179 }, 'SW-fallbacked redirect to same-origin same-scope.'); | |
180 promise_test(function(t) { | |
181 return setup_environment(t).then(function() { | |
182 return test_redirect( | |
183 SCOPE1 + 'url=' + encodeURIComponent(SCOPE2), | |
184 SCOPE2, | |
185 [[SCOPE1 + 'url=' + encodeURIComponent(SCOPE2)], [SCOPE2], []]); | |
186 }); | |
187 }, 'SW-fallbacked redirect to same-origin other-scope.'); | |
188 promise_test(function(t) { | |
189 return setup_environment(t).then(function() { | |
190 return test_redirect( | |
191 SCOPE1 + 'url=' + encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE), | |
192 OTHER_ORIGIN_OUT_SCOPE, | |
193 [[SCOPE1 + 'url=' + encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE)], | |
194 [], | |
195 []]); | |
196 }); | |
197 }, 'SW-fallbacked redirect to other-origin out-scope.'); | |
198 promise_test(function(t) { | |
199 return setup_environment(t).then(function() { | |
200 return test_redirect( | |
201 SCOPE1 + 'url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE), | |
202 OTHER_ORIGIN_SCOPE, | |
203 [[SCOPE1 + 'url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE)], | |
204 [], | |
205 [OTHER_ORIGIN_SCOPE]]); | |
206 }); | |
207 }, 'SW-fallbacked redirect to other-origin in-scope.'); | |
208 | |
209 // SW generated redirect. | |
210 // SW: event.respondWith(Response.redirect(params['url'])); | |
211 promise_test(function(t) { | |
212 return setup_environment(t).then(function() { | |
213 return test_redirect( | |
214 SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OUT_SCOPE), | |
215 OUT_SCOPE, | |
216 [[SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OUT_SCOPE)], [], []]); | |
217 }); | |
218 }, 'SW-generated redirect to same-origin out-scope.'); | |
219 promise_test(function(t) { | |
220 return setup_environment(t).then(function() { | |
221 return test_redirect( | |
222 SCOPE1 + 'sw=gen&url=' + encodeURIComponent(SCOPE1), | |
223 SCOPE1, | |
224 [[SCOPE1 + 'sw=gen&url=' + encodeURIComponent(SCOPE1), SCOPE1], | |
225 [], | |
226 []]); | |
227 }); | |
228 }, 'SW-generated redirect to same-origin same-scope.'); | |
229 promise_test(function(t) { | |
230 return setup_environment(t).then(function() { | |
231 return test_redirect( | |
232 SCOPE1 + 'sw=gen&url=' + encodeURIComponent(SCOPE2), | |
233 SCOPE2, | |
234 [[SCOPE1 + 'sw=gen&url=' + encodeURIComponent(SCOPE2)], | |
235 [SCOPE2], | |
236 []]); | |
237 }); | |
238 }, 'SW-generated redirect to same-origin other-scope.'); | |
239 promise_test(function(t) { | |
240 return setup_environment(t).then(function() { | |
241 return test_redirect( | |
242 SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE), | |
243 OTHER_ORIGIN_OUT_SCOPE, | |
244 [[SCOPE1 + 'sw=gen&url=' + | |
245 encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE)], | |
246 [], | |
247 []]); | |
248 }); | |
249 }, 'SW-generated redirect to other-origin out-scope.'); | |
250 promise_test(function(t) { | |
251 return setup_environment(t).then(function() { | |
252 return test_redirect( | |
253 SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE), | |
254 OTHER_ORIGIN_SCOPE, | |
255 [[SCOPE1 + 'sw=gen&url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE)], | |
256 [], | |
257 [OTHER_ORIGIN_SCOPE]]); | |
258 }); | |
259 }, 'SW-generated redirect to other-origin in-scope.'); | |
260 | |
261 // SW fetched redirect. | |
262 // SW: event.respondWith(fetch(event.request)); | |
263 promise_test(function(t) { | |
264 return setup_environment(t).then(function() { | |
265 return test_redirect( | |
266 SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(OUT_SCOPE), | |
267 OUT_SCOPE, | |
268 [[SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(OUT_SCOPE)], | |
269 [], | |
270 []]); | |
271 }); | |
272 }, 'SW-fetched redirect to same-origin out-scope.'); | |
273 promise_test(function(t) { | |
274 return setup_environment(t).then(function() { | |
275 return test_redirect( | |
276 SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(SCOPE1), | |
277 SCOPE1, | |
278 [[SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(SCOPE1), SCOPE1], | |
279 [], | |
280 []]); | |
281 }); | |
282 }, 'SW-fetched redirect to same-origin same-scope.'); | |
283 promise_test(function(t) { | |
284 return setup_environment(t).then(function() { | |
285 return test_redirect( | |
286 SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(SCOPE2), | |
287 SCOPE2, | |
288 [[SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(SCOPE2)], | |
289 [SCOPE2], | |
290 []]); | |
291 }); | |
292 }, 'SW-fetched redirect to same-origin other-scope.'); | |
293 promise_test(function(t) { | |
294 return setup_environment(t).then(function() { | |
295 return test_redirect( | |
296 SCOPE1 + 'sw=fetch&url=' + | |
297 encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE), | |
298 OTHER_ORIGIN_OUT_SCOPE, | |
299 [[SCOPE1 + 'sw=fetch&url=' + | |
300 encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE)], | |
301 [], | |
302 []]); | |
303 }); | |
304 }, 'SW-fetched redirect to other-origin out-scope.'); | |
305 promise_test(function(t) { | |
306 return setup_environment(t).then(function() { | |
307 return test_redirect( | |
308 SCOPE1 + 'sw=fetch&url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE), | |
309 OTHER_ORIGIN_SCOPE, | |
310 [[SCOPE1 + 'sw=fetch&url=' + | |
311 encodeURIComponent(OTHER_ORIGIN_SCOPE)], | |
312 [], | |
313 [OTHER_ORIGIN_SCOPE]]); | |
314 }); | |
315 }, 'SW-fetched redirect to other-origin in-scope.'); | |
316 | |
317 // Opaque redirect. | |
318 // SW: event.respondWith(fetch( | |
319 // new Request(event.request.url, {redirect: 'manual'}))); | |
320 promise_test(function(t) { | |
321 return setup_environment(t).then(function() { | |
322 return test_redirect( | |
323 SCOPE1 + 'sw=opaque&url=' + encodeURIComponent(OUT_SCOPE), | |
324 OUT_SCOPE, | |
325 [[SCOPE1 + 'sw=opaque&url=' + encodeURIComponent(OUT_SCOPE)], | |
326 [], | |
327 []]); | |
328 }); | |
329 }, 'Redirect to same-origin out-scope with opaque redirect response.'); | |
330 promise_test(function(t) { | |
331 return setup_environment(t).then(function() { | |
332 return test_redirect( | |
333 SCOPE1 + 'sw=opaque&url=' + encodeURIComponent(SCOPE1), | |
334 SCOPE1, | |
335 [[SCOPE1 + 'sw=opaque&url=' + encodeURIComponent(SCOPE1), SCOPE1], | |
336 [], | |
337 []]); | |
338 }); | |
339 }, 'Redirect to same-origin same-scope with opaque redirect response.'); | |
340 promise_test(function(t) { | |
341 return setup_environment(t).then(function() { | |
342 return test_redirect( | |
343 SCOPE1 + 'sw=opaque&url=' + encodeURIComponent(SCOPE2), | |
344 SCOPE2, | |
345 [[SCOPE1 + 'sw=opaque&url=' + encodeURIComponent(SCOPE2)], | |
346 [SCOPE2], | |
347 []]); | |
348 }); | |
349 }, 'Redirect to same-origin other-scope with opaque redirect response.'); | |
350 promise_test(function(t) { | |
351 return setup_environment(t).then(function() { | |
352 return test_redirect( | |
353 SCOPE1 + 'sw=opaque&url=' + | |
354 encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE), | |
355 OTHER_ORIGIN_OUT_SCOPE, | |
356 [[SCOPE1 + 'sw=opaque&url=' + | |
357 encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE)], | |
358 [], | |
359 []]); | |
360 }); | |
361 }, 'Redirect to other-origin out-scope with opaque redirect response.'); | |
362 promise_test(function(t) { | |
363 return setup_environment(t).then(function() { | |
364 return test_redirect( | |
365 SCOPE1 + 'sw=opaque&url=' + encodeURIComponent(OTHER_ORIGIN_SCOPE), | |
366 OTHER_ORIGIN_SCOPE, | |
367 [[SCOPE1 + 'sw=opaque&url=' + | |
368 encodeURIComponent(OTHER_ORIGIN_SCOPE)], | |
369 [], | |
370 [OTHER_ORIGIN_SCOPE]]); | |
371 }); | |
372 }, 'Redirect to other-origin in-scope with opaque redirect response.'); | |
373 promise_test(function(t) { | |
374 return setup_environment(t).then(function() { | |
375 return test_redirect( | |
376 SCOPE1 + 'sw=opaque&noLocationRedirect', | |
377 SCOPE1 + 'sw=opaque&noLocationRedirect', | |
378 [[SCOPE1 + 'sw=opaque&noLocationRedirect'], | |
379 [], | |
380 []]); | |
381 }); | |
382 }, 'No location redirect response.'); | |
383 | |
384 // Opaque redirect passed through Cache. | |
385 // SW responds with an opaque redirectresponse from the Cache API. | |
386 promise_test(function(t) { | |
387 return setup_environment(t).then(function() { | |
388 return test_redirect( | |
389 SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
390 encodeURIComponent(OUT_SCOPE), | |
391 OUT_SCOPE, | |
392 [[SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
393 encodeURIComponent(OUT_SCOPE)], | |
394 [], | |
395 []]); | |
396 }); | |
397 }, | |
398 'Redirect to same-origin out-scope with opaque redirect response which ' + | |
399 'is passed through Cache.'); | |
400 promise_test(function(t) { | |
401 return setup_environment(t).then(function() { | |
402 return test_redirect( | |
403 SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
404 encodeURIComponent(SCOPE1), | |
405 SCOPE1, | |
406 [[SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
407 encodeURIComponent(SCOPE1), SCOPE1], | |
408 [], | |
409 []]); | |
410 }); | |
411 }, | |
412 'Redirect to same-origin same-scope with opaque redirect response which ' + | |
413 'is passed through Cache.'); | |
414 promise_test(function(t) { | |
415 return setup_environment(t).then(function() { | |
416 return test_redirect( | |
417 SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
418 encodeURIComponent(SCOPE2), | |
419 SCOPE2, | |
420 [[SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
421 encodeURIComponent(SCOPE2)], | |
422 [SCOPE2], | |
423 []]); | |
424 }); | |
425 }, | |
426 'Redirect to same-origin other-scope with opaque redirect response which ' + | |
427 'is passed through Cache.'); | |
428 promise_test(function(t) { | |
429 return setup_environment(t).then(function() { | |
430 return test_redirect( | |
431 SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
432 encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE), | |
433 OTHER_ORIGIN_OUT_SCOPE, | |
434 [[SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
435 encodeURIComponent(OTHER_ORIGIN_OUT_SCOPE)], | |
436 [], | |
437 []]); | |
438 }); | |
439 }, | |
440 'Redirect to other-origin out-scope with opaque redirect response which ' + | |
441 'is passed through Cache.'); | |
442 promise_test(function(t) { | |
443 return setup_environment(t).then(function() { | |
444 return test_redirect( | |
445 SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
446 encodeURIComponent(OTHER_ORIGIN_SCOPE), | |
447 OTHER_ORIGIN_SCOPE, | |
448 [[SCOPE1 + 'sw=opaqueThroughCache&url=' + | |
449 encodeURIComponent(OTHER_ORIGIN_SCOPE)], | |
450 [], | |
451 [OTHER_ORIGIN_SCOPE]]); | |
452 }); | |
453 }, | |
454 'Redirect to other-origin in-scope with opaque redirect response which ' + | |
455 'is passed through Cache.'); | |
456 promise_test(function(t) { | |
457 return setup_environment(t).then(function() { | |
458 return test_redirect( | |
459 SCOPE1 + 'sw=opaqueThroughCache&noLocationRedirect', | |
460 SCOPE1 + 'sw=opaqueThroughCache&noLocationRedirect', | |
461 [[SCOPE1 + 'sw=opaqueThroughCache&noLocationRedirect'], | |
462 [], | |
463 []]); | |
464 }); | |
465 }, 'No location redirect response via Cache.'); | |
466 | |
467 </script> | |
468 </body> | |
OLD | NEW |