OLD | NEW |
1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
2 <script src="../resources/testharness.js"></script> | 2 <title>Service Worker: basic Foreign Fetch functionality</title> |
3 <script src="../resources/testharnessreport.js"></script> | 3 <script src="/resources/testharness.js"></script> |
4 <script src="../resources/get-host-info.js"></script> | 4 <script src="/resources/testharnessreport.js"></script> |
5 <script src="resources/test-helpers.js"></script> | 5 <script src="resources/get-host-info.sub.js"></script> |
| 6 <script src="resources/test-helpers.sub.js"></script> |
6 <script src="resources/foreign-fetch-helpers.js"></script> | 7 <script src="resources/foreign-fetch-helpers.js"></script> |
7 <body> | 8 <body> |
8 <script> | 9 <script> |
9 var host_info = get_host_info(); | 10 var host_info = get_host_info(); |
| 11 var resource_path = new URL('resources/', location).pathname; |
10 | 12 |
11 function worker_for_origins(origins) { | 13 function worker_for_origins(origins) { |
12 var worker = 'foreign-fetch-worker.js?'; | 14 var worker = 'foreign-fetch-worker.js?'; |
13 var params = {origins: origins, relscopes: ['/intercept']}; | 15 var params = {origins: origins, relscopes: ['/intercept']}; |
14 return worker + encodeURIComponent(JSON.stringify(params)); | 16 return worker + encodeURIComponent(JSON.stringify(params)); |
15 } | 17 } |
16 | 18 |
17 function worker_for_scopes(relative_scopes) { | 19 function worker_for_scopes(relative_scopes) { |
18 var worker = 'foreign-fetch-worker.js?'; | 20 var worker = 'foreign-fetch-worker.js?'; |
19 var params = {relscopes: relative_scopes}; | 21 var params = {relscopes: relative_scopes}; |
20 return worker + encodeURIComponent(JSON.stringify(params)); | 22 return worker + encodeURIComponent(JSON.stringify(params)); |
21 } | 23 } |
22 | 24 |
23 function intercepted_url(scope) { | 25 function intercepted_url(scope) { |
24 return host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + | 26 return host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope + '/intercept/foo
?basic'; |
25 scope + '/intercept/foo?basic'; | |
26 } | 27 } |
27 | 28 |
28 function non_intercepted_url(scope) { | 29 function non_intercepted_url(scope) { |
29 return host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + | 30 return host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope + '/foo?basic'; |
30 scope + '/foo?basic'; | |
31 } | 31 } |
32 | 32 |
33 promise_test(t => { | 33 promise_test(t => { |
34 var scope = 'foreign-fetch/scope/wildcard'; | 34 var scope = 'foreign-fetch/scope/wildcard'; |
35 return install_cross_origin_worker(t, worker_for_origins(['*']), scope) | 35 return install_cross_origin_worker(t, worker_for_origins(['*']), scope) |
36 .then(() => promise_rejects(t, new TypeError(), | 36 .then(() => promise_rejects(t, new TypeError(), |
37 fetch(non_intercepted_url(scope)))) | 37 fetch(non_intercepted_url(scope)))) |
38 .then(() => fetch(intercepted_url(scope))) | 38 .then(() => fetch(intercepted_url(scope))) |
39 .then(response => response.text()) | 39 .then(response => response.text()) |
40 .then(response_text => { | 40 .then(response_text => { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 }) | 82 }) |
83 .then(() => fetch(scope + '/intercept/foo?basic')) | 83 .then(() => fetch(scope + '/intercept/foo?basic')) |
84 .then(response => { | 84 .then(response => { |
85 assert_equals(response.status, 404); | 85 assert_equals(response.status, 404); |
86 }); | 86 }); |
87 }, 'Service Worker does not intercept same origin fetches.'); | 87 }, 'Service Worker does not intercept same origin fetches.'); |
88 | 88 |
89 promise_test(t => { | 89 promise_test(t => { |
90 var scope = 'reply-to-message.html?onmessage'; | 90 var scope = 'reply-to-message.html?onmessage'; |
91 var remote_url = | 91 var remote_url = |
92 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + scope; | 92 host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope; |
93 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) | 93 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) |
94 .then(() => with_iframe(remote_url)) | 94 .then(() => with_iframe(remote_url)) |
95 .then(frame => new Promise(resolve => { | 95 .then(frame => new Promise(resolve => { |
96 var channel = new MessageChannel(); | 96 var channel = new MessageChannel(); |
97 frame.contentWindow.postMessage('ping', '*', [channel.port1]); | 97 frame.contentWindow.postMessage('ping', '*', [channel.port1]); |
98 channel.port2.onmessage = reply => resolve(reply.data); | 98 channel.port2.onmessage = reply => resolve(reply.data); |
99 })) | 99 })) |
100 .then(reply => { | 100 .then(reply => { |
101 assert_equals(reply, 'ping'); | 101 assert_equals(reply, 'ping'); |
102 }); | 102 }); |
103 }, 'Service Worker does not intercept navigations.'); | 103 }, 'Service Worker does not intercept navigations.'); |
104 | 104 |
105 promise_test(t => { | 105 promise_test(t => { |
106 var scope = 'fetch-access-control.php?fallback&ACAOrigin=*'; | 106 var scope = 'fetch-access-control.py?fallback&ACAOrigin=*'; |
107 var remote_url = | 107 var remote_url = |
108 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + scope; | 108 host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope; |
109 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) | 109 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) |
110 .then(() => fetch(remote_url)) | 110 .then(() => fetch(remote_url)) |
111 .then(response => response.text()) | 111 .then(response => response.text()) |
112 .then(response_text => assert_true(response_text.startsWith('report('))); | 112 .then(response_text => assert_true(response_text.startsWith('report('))); |
113 }, 'Service Worker that fallback to network should fallback to network.'); | 113 }, 'Service Worker that fallback to network should fallback to network.'); |
114 | 114 |
115 promise_test(t => { | 115 promise_test(t => { |
116 var scope = 'fetch-access-control.php?fetch&ACAOrigin=*'; | 116 var scope = 'fetch-access-control.py?fetch&ACAOrigin=*'; |
117 var remote_url = | 117 var remote_url = |
118 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + scope; | 118 host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope; |
119 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) | 119 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) |
120 .then(() => fetch(remote_url)) | 120 .then(() => fetch(remote_url)) |
121 .then(response => response.text()) | 121 .then(response => response.text()) |
122 .then(response_text => assert_true(response_text.startsWith('report('))); | 122 .then(response_text => assert_true(response_text.startsWith('report('))); |
123 }, 'Service Worker that fetch from the network should fallback to network.'); | 123 }, 'Service Worker that fetch from the network should fallback to network.'); |
124 | 124 |
125 promise_test(t => { | 125 promise_test(t => { |
126 var scope = 'simple.txt?fallback'; | 126 var scope = 'simple.txt?fallback'; |
127 var remote_url = | 127 var remote_url = |
128 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + scope; | 128 host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope; |
129 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) | 129 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) |
130 .then(() => fetch(remote_url, {mode: 'no-cors'})) | 130 .then(() => fetch(remote_url, {mode: 'no-cors'})) |
131 .then(response => assert_equals(response.type, 'opaque')) | 131 .then(response => assert_equals(response.type, 'opaque')) |
132 .then(() => promise_rejects(t, new TypeError(), fetch(remote_url))); | 132 .then(() => promise_rejects(t, new TypeError(), fetch(remote_url))); |
133 }, 'Falling back to network should still respect CORS.'); | 133 }, 'Falling back to network should still respect CORS.'); |
134 | 134 |
135 promise_test(t => { | 135 promise_test(t => { |
136 var ff_scope = 'foreign-fetch/scope/controlled?basic'; | 136 var ff_scope = 'foreign-fetch/scope/controlled?basic'; |
137 var remote_url = | 137 var remote_url = |
138 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + ff_scope; | 138 host_info.HTTPS_REMOTE_ORIGIN + resource_path + ff_scope; |
139 var scope = 'resources/simple.html?fetch'; | 139 var scope = 'resources/simple.html?fetch'; |
140 var worker = 'resources/empty-worker.js'; | 140 var worker = 'resources/empty-worker.js'; |
141 return install_cross_origin_worker(t, worker_for_scopes(['']), ff_scope) | 141 return install_cross_origin_worker(t, worker_for_scopes(['']), ff_scope) |
142 .then(() => service_worker_unregister_and_register(t, worker, scope)) | 142 .then(() => service_worker_unregister_and_register(t, worker, scope)) |
143 .then(r => { | 143 .then(r => { |
144 add_completion_callback(() => r.unregister()); | 144 add_completion_callback(() => r.unregister()); |
145 return wait_for_state(t, r.installing, 'activated'); | 145 return wait_for_state(t, r.installing, 'activated'); |
146 }) | 146 }) |
147 .then(() => with_iframe(scope)) | 147 .then(() => with_iframe(scope)) |
148 .then(frame => frame.contentWindow.fetch(remote_url)) | 148 .then(frame => frame.contentWindow.fetch(remote_url)) |
149 .then(response => response.text()) | 149 .then(response => response.text()) |
150 .then(response_text => { | 150 .then(response_text => { |
151 assert_equals(response_text, 'Foreign Fetch'); | 151 assert_equals(response_text, 'Foreign Fetch'); |
152 }); | 152 }); |
153 }, 'Foreign fetch can intercept fetch requests from SW controlled pages.'); | 153 }, 'Foreign fetch can intercept fetch requests from SW controlled pages.'); |
154 | 154 |
155 promise_test(t => { | 155 promise_test(t => { |
156 var ff_scope = 'foreign-fetch/scope/controlled?script'; | 156 var ff_scope = 'foreign-fetch/scope/controlled?script'; |
157 var remote_url = | 157 var remote_url = |
158 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + ff_scope; | 158 host_info.HTTPS_REMOTE_ORIGIN + resource_path + ff_scope; |
159 var scope = 'resources/simple.html?script'; | 159 var scope = 'resources/simple.html?script'; |
160 var worker = 'resources/empty-worker.js'; | 160 var worker = 'resources/empty-worker.js'; |
161 return install_cross_origin_worker(t, worker_for_scopes(['']), ff_scope) | 161 return install_cross_origin_worker(t, worker_for_scopes(['']), ff_scope) |
162 .then(() => service_worker_unregister_and_register(t, worker, scope)) | 162 .then(() => service_worker_unregister_and_register(t, worker, scope)) |
163 .then(r => { | 163 .then(r => { |
164 add_completion_callback(() => r.unregister()); | 164 add_completion_callback(() => r.unregister()); |
165 return wait_for_state(t, r.installing, 'activated'); | 165 return wait_for_state(t, r.installing, 'activated'); |
166 }) | 166 }) |
167 .then(() => with_iframe(scope)) | 167 .then(() => with_iframe(scope)) |
168 .then(frame => new Promise(resolve => { | 168 .then(frame => new Promise(resolve => { |
169 frame.contentWindow.DidLoad = resolve; | 169 frame.contentWindow.DidLoad = resolve; |
170 let script = frame.contentWindow.document.createElement('script'); | 170 let script = frame.contentWindow.document.createElement('script'); |
171 script.setAttribute('src', remote_url); | 171 script.setAttribute('src', remote_url); |
172 script.setAttribute('crossorigin', 'use-credentials'); | 172 script.setAttribute('crossorigin', 'use-credentials'); |
173 frame.contentWindow.document.head.appendChild(script); | 173 frame.contentWindow.document.head.appendChild(script); |
174 })) | 174 })) |
175 .then(response_text => { | 175 .then(response_text => { |
176 assert_equals(response_text, 'Foreign Fetch'); | 176 assert_equals(response_text, 'Foreign Fetch'); |
177 }); | 177 }); |
178 }, 'Foreign fetch can intercept resource requests from SW controlled pages.'); | 178 }, 'Foreign fetch can intercept resource requests from SW controlled pages.'); |
179 | 179 |
180 promise_test(t => { | 180 promise_test(t => { |
181 var scope = 'simple.txt?meta'; | 181 var scope = 'simple.txt?meta'; |
182 var remote_url = | 182 var remote_url = |
183 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + scope; | 183 host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope; |
184 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) | 184 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) |
185 .then(() => fetch(remote_url, {mode: 'no-cors'})) | 185 .then(() => fetch(remote_url, {mode: 'no-cors'})) |
186 .then(response => response.json()) | 186 .then(response => response.json()) |
187 .then(response_data => { | 187 .then(response_data => { |
188 assert_equals(self.location.href, response_data.referrer); | 188 assert_equals(self.location.href, response_data.referrer); |
189 assert_equals(self.location.origin, response_data.origin); | 189 assert_equals(self.location.origin, response_data.origin); |
190 }) | 190 }) |
191 .then(() => with_iframe('resources/blank.html')) | 191 .then(() => with_iframe('resources/blank.html')) |
192 .then(frame => { | 192 .then(frame => { |
193 var meta = frame.contentDocument.createElement('meta'); | 193 var meta = frame.contentDocument.createElement('meta'); |
194 meta.setAttribute('name', 'referrer'); | 194 meta.setAttribute('name', 'referrer'); |
195 meta.setAttribute('content', 'no-referrer'); | 195 meta.setAttribute('content', 'no-referrer'); |
196 frame.contentDocument.head.appendChild(meta); | 196 frame.contentDocument.head.appendChild(meta); |
197 return frame.contentWindow.fetch(remote_url, {mode: 'no-cors'}); | 197 return frame.contentWindow.fetch(remote_url, {mode: 'no-cors'}); |
198 }) | 198 }) |
199 .then(response => response.json()) | 199 .then(response => response.json()) |
200 .then(response_data => { | 200 .then(response_data => { |
201 assert_equals('', response_data.referrer); | 201 assert_equals('', response_data.referrer); |
202 assert_equals('null', response_data.origin); | 202 assert_equals('null', response_data.origin); |
203 }); | 203 }); |
204 }, 'Referrer and origin are set correctly in ForeignFetchEvent.'); | 204 }, 'Referrer and origin are set correctly in ForeignFetchEvent.'); |
205 | 205 |
206 function fetch_from_iframe(origin, url) { | |
207 return with_iframe(origin + | |
208 '/serviceworker/resources/foreign-fetch-helper-iframe.html') | |
209 .then(frame => new Promise((resolve) => { | |
210 var channel = new MessageChannel(); | |
211 frame.contentWindow.postMessage({url: url, | |
212 port: channel.port1}, | |
213 '*', [channel.port1]); | |
214 channel.port2.onmessage = reply => resolve(reply.data); | |
215 })); | |
216 } | |
217 | |
218 promise_test(t => { | 206 promise_test(t => { |
219 var scope = 'simple.txt?basic_insecure'; | 207 var scope = 'simple.txt?basic_insecure'; |
220 var remote_url = | 208 var remote_url = |
221 host_info.AUTHENTICATED_ORIGIN + '/serviceworker/resources/' + scope; | 209 host_info.AUTHENTICATED_ORIGIN + resource_path + scope; |
222 return install_cross_origin_worker(t, worker_for_scopes(['']), scope, | 210 return install_cross_origin_worker(t, worker_for_scopes(['']), scope, |
223 host_info.AUTHENTICATED_ORIGIN) | 211 host_info.AUTHENTICATED_ORIGIN) |
224 .then(() => fetch_from_iframe(host_info.HTTPS_REMOTE_ORIGIN, remote_url)) | 212 .then(() => fetch_from_different_origin(host_info.HTTPS_REMOTE_ORIGIN, rem
ote_url)) |
225 .then(response => assert_equals(response, 'Success: Foreign Fetch')) | 213 .then(response => assert_equals(response, 'Success: Foreign Fetch')) |
226 .then(() => fetch_from_iframe(host_info.UNAUTHENTICATED_ORIGIN, | 214 .then(() => fetch_from_different_origin(host_info.UNAUTHENTICATED_ORIGIN, |
227 remote_url)) | 215 remote_url)) |
228 .then(response => assert_equals(response, | 216 .then(response => assert_true(response.startsWith('Error: TypeError'))); |
229 'Error: TypeError: Failed to fetch')); | |
230 }, 'Service Worker does not intercept fetches from an insecure context.'); | 217 }, 'Service Worker does not intercept fetches from an insecure context.'); |
231 | 218 |
232 promise_test(t => { | 219 promise_test(t => { |
233 var scope = 'fetch-access-control.php?basic&ACAOrigin=*&ACAMethods=SPECIAL'; | 220 var scope = 'fetch-access-control.py?basic&ACAOrigin=*&ACAMethods=SPECIAL'; |
234 var remote_url = | 221 var remote_url = |
235 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + scope; | 222 host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope; |
236 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) | 223 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) |
237 .then(() => fetch(remote_url, {method: 'SPECIAL'})) | 224 .then(() => fetch(remote_url, {method: 'SPECIAL'})) |
238 .then(response => response.text()) | 225 .then(response => response.text()) |
239 .then(response_text => assert_true(response_text.startsWith('report('))) | 226 .then(response_text => assert_true(response_text.startsWith('report('))) |
240 // Do the whole thing twice to test CORS preflight cache behavior. | 227 // Do the whole thing twice to test CORS preflight cache behavior. |
241 .then(() => fetch(remote_url, {method: 'SPECIAL'})) | 228 .then(() => fetch(remote_url, {method: 'SPECIAL'})) |
242 .then(response => response.text()) | 229 .then(response => response.text()) |
243 .then(response_text => assert_true(response_text.startsWith('report('))); | 230 .then(response_text => assert_true(response_text.startsWith('report('))); |
244 }, 'Service Worker does not intercept fetches with CORS preflight'); | 231 }, 'Service Worker does not intercept fetches with CORS preflight'); |
245 | 232 |
246 promise_test(t => { | 233 promise_test(t => { |
247 var scope = 'simple.txt?null'; | 234 var scope = 'simple.txt?null'; |
248 var remote_url = | 235 var remote_url = |
249 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + scope; | 236 host_info.HTTPS_REMOTE_ORIGIN + resource_path + scope; |
250 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) | 237 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) |
251 .then(() => promise_rejects(t, new TypeError(), fetch(remote_url))); | 238 .then(() => promise_rejects(t, new TypeError(), fetch(remote_url))); |
252 }, 'Foreign fetch rejects if resolved with a null response.'); | 239 }, 'Foreign fetch rejects if resolved with a null response.'); |
253 </script> | 240 </script> |
254 </body> | 241 </body> |
OLD | NEW |