OLD | NEW |
| (Empty) |
1 <!DOCTYPE html> | |
2 <script src="../resources/testharness.js"></script> | |
3 <script src="../resources/testharnessreport.js"></script> | |
4 <script src="../resources/get-host-info.js"></script> | |
5 <script src="resources/test-helpers.js"></script> | |
6 <script src="resources/foreign-fetch-helpers.js"></script> | |
7 <body> | |
8 <script> | |
9 var host_info = get_host_info(); | |
10 var origin = new URL(self.location).origin; | |
11 var wrong_origin = 'https://example.com/'; | |
12 var test_header = 'X-ServiceWorker-ServerHeader'; | |
13 | |
14 function url_to_fetch(scope) { | |
15 return host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + scope; | |
16 } | |
17 | |
18 function worker_for_response(response) { | |
19 return 'foreign-fetch-cors-worker.js?' + | |
20 encodeURIComponent(JSON.stringify(response)); | |
21 } | |
22 | |
23 function scope_for_params(params) { | |
24 return 'simple.txt?' + encodeURIComponent(JSON.stringify(params)); | |
25 } | |
26 | |
27 // Method used for tests that expect to result in an opaque response. | |
28 function verify_opaque_fetch(url, t) { | |
29 return promise_rejects(t, new TypeError(), fetch(url)) | |
30 .then(() => fetch(url, {mode: 'no-cors'})) | |
31 .then(response => assert_equals(response.type, 'opaque')) | |
32 .then(() => new Promise(resolve => { | |
33 var request = new XMLHttpRequest(); | |
34 request.open('GET', url); | |
35 request.onreadystatechange = () => { | |
36 if (request.readyState == 4) resolve(request); | |
37 }; | |
38 request.send(); | |
39 })) | |
40 .then(xhr => { | |
41 assert_equals(xhr.status, 0); | |
42 assert_equals(xhr.responseText, ''); | |
43 }); | |
44 } | |
45 | |
46 // Verify that fetching an url results in a network error. | |
47 function verify_network_error(url, t) { | |
48 return promise_rejects(t, new TypeError(), fetch(url)) | |
49 .then(() => promise_rejects(t, new TypeError(), | |
50 fetch(url, {mode: 'no-cors'}))) | |
51 .then(() => new Promise(resolve => { | |
52 var request = new XMLHttpRequest(); | |
53 request.open('GET', url); | |
54 request.onreadystatechange = () => { | |
55 if (request.readyState == 4) resolve(request); | |
56 }; | |
57 request.send(); | |
58 })) | |
59 .then(xhr => { | |
60 assert_equals(xhr.status, 0); | |
61 assert_equals(xhr.responseText, ''); | |
62 }); | |
63 } | |
64 | |
65 // Verifies that fetching the URL returns a cors response, with a specific value | |
66 // for a test_header on the response. Also verifies that round-tripping this | |
67 // response through the cache doesn't cause issues. | |
68 function verify_cors_fetch_with_header_value(url, header_value) { | |
69 var response; | |
70 var cache; | |
71 return fetch(url) | |
72 .then(r => { | |
73 response = r.clone(); | |
74 assert_equals(r.type, 'cors'); | |
75 assert_equals(r.headers.get(test_header), header_value, 'From fetch'); | |
76 return r.text(); | |
77 }) | |
78 .then(response_text => { | |
79 assert_true(response_text.startsWith('report(')); | |
80 return self.caches.open(url); | |
81 }) | |
82 .then(c => { | |
83 cache = c; | |
84 return cache.put(url, response); | |
85 }) | |
86 .then(() => cache.match(url)) | |
87 .then(r => { | |
88 assert_equals(r.type, 'cors'); | |
89 assert_equals(r.headers.get(test_header), header_value, 'From cache'); | |
90 return r.text(); | |
91 }) | |
92 .then(response_text => { | |
93 assert_true(response_text.startsWith('report(')); | |
94 return self.caches.delete(url); | |
95 }) | |
96 .then(() => new Promise(resolve => { | |
97 var request = new XMLHttpRequest(); | |
98 request.open('GET', url); | |
99 request.onreadystatechange = () => { | |
100 if (request.readyState == 4) resolve(request); | |
101 }; | |
102 request.send(); | |
103 })) | |
104 .then(xhr => { | |
105 assert_true(xhr.responseText.startsWith('report(')); | |
106 assert_equals(xhr.getResponseHeader(test_header), header_value); | |
107 var headers = xhr.getAllResponseHeaders().toLowerCase(); | |
108 if (header_value) { | |
109 assert_true(headers.includes(test_header.toLowerCase() + ': ' + | |
110 header_value.toLowerCase())); | |
111 } else { | |
112 assert_false(headers.includes(test_header.toLowerCase())); | |
113 } | |
114 }); | |
115 } | |
116 | |
117 verify_cors_fetch_with_header = | |
118 url => verify_cors_fetch_with_header_value(url, 'SetInTheServer'); | |
119 verify_cors_fetch_without_header = | |
120 url => verify_cors_fetch_with_header_value(url, null); | |
121 | |
122 var tests = [ | |
123 { | |
124 description: 'Same origin fetch without CORS headers, not exposed', | |
125 params: { | |
126 cross_origin: false, | |
127 with_aceheaders: false, | |
128 with_acaorigin: false | |
129 }, | |
130 response: {}, | |
131 expectation: verify_opaque_fetch | |
132 }, | |
133 { | |
134 description: 'Same origin fetch without CORS headers, only origin exposed', | |
135 params: { | |
136 cross_origin: false, | |
137 with_aceheaders: false, | |
138 with_acaorigin: false | |
139 }, | |
140 response: {origin: origin}, | |
141 expectation: verify_cors_fetch_without_header | |
142 }, | |
143 { | |
144 description: | |
145 'Same origin fetch without CORS headers, headers and origin exposed', | |
146 params: { | |
147 cross_origin: false, | |
148 with_aceheaders: false, | |
149 with_acaorigin: false | |
150 }, | |
151 response: {origin: origin, headers: [test_header]}, | |
152 expectation: verify_cors_fetch_with_header | |
153 }, | |
154 { | |
155 description: | |
156 'Same origin fetch without CORS headers, exposed to wrong origin', | |
157 params: { | |
158 cross_origin: false, | |
159 with_aceheaders: false, | |
160 with_acaorigin: false | |
161 }, | |
162 response: {origin: wrong_origin, headers: [test_header]}, | |
163 expectation: verify_network_error | |
164 }, | |
165 { | |
166 description: 'Same origin fetch with CORS headers, not exposed', | |
167 params: { | |
168 cross_origin: false, | |
169 with_aceheaders: true, | |
170 with_acaorigin: true | |
171 }, | |
172 response: {}, | |
173 expectation: verify_opaque_fetch | |
174 }, | |
175 { | |
176 description: 'Same origin fetch with CORS headers, only origin exposed', | |
177 params: { | |
178 cross_origin: false, | |
179 with_aceheaders: true, | |
180 with_acaorigin: true | |
181 }, | |
182 response: {origin: origin}, | |
183 expectation: verify_cors_fetch_without_header | |
184 }, | |
185 { | |
186 description: | |
187 'Same origin fetch with CORS headers, headers and origin exposed', | |
188 params: { | |
189 cross_origin: false, | |
190 with_aceheaders: true, | |
191 with_acaorigin: true | |
192 }, | |
193 response: {origin: origin, headers: [test_header]}, | |
194 expectation: verify_cors_fetch_with_header | |
195 }, | |
196 { | |
197 description: 'Same origin fetch with CORS headers, exposed to wrong origin', | |
198 params: { | |
199 cross_origin: false, | |
200 with_aceheaders: true, | |
201 with_acaorigin: true | |
202 }, | |
203 response: {origin: wrong_origin, headers: [test_header]}, | |
204 expectation: verify_network_error | |
205 }, | |
206 { | |
207 description: 'Cross origin fetch without CORS headers, not exposed', | |
208 params: { | |
209 cross_origin: true, | |
210 with_aceheaders: false, | |
211 with_acaorigin: false | |
212 }, | |
213 response: {}, | |
214 expectation: verify_opaque_fetch | |
215 }, | |
216 { | |
217 description: 'Cross origin fetch with ACEHeaders header, not exposed', | |
218 params: { | |
219 cross_origin: true, | |
220 with_aceheaders: true, | |
221 with_acaorigin: true | |
222 }, | |
223 response: {}, | |
224 expectation: verify_opaque_fetch | |
225 }, | |
226 { | |
227 description: | |
228 'Cross origin fetch with ACEHeaders header, only origin exposed', | |
229 params: { | |
230 cross_origin: true, | |
231 with_aceheaders: true, | |
232 with_acaorigin: true | |
233 }, | |
234 response: {origin: origin}, | |
235 expectation: verify_cors_fetch_without_header | |
236 }, | |
237 { | |
238 description: | |
239 'Cross origin fetch with ACEHeaders header, headers and origin exposed', | |
240 params: { | |
241 cross_origin: true, | |
242 with_aceheaders: true, | |
243 with_acaorigin: true | |
244 }, | |
245 response: {origin: origin, headers: [test_header]}, | |
246 expectation: verify_cors_fetch_with_header | |
247 }, | |
248 { | |
249 description: | |
250 'Cross origin fetch with ACEHeaders header, exposed to wrong origin', | |
251 params: { | |
252 cross_origin: true, | |
253 with_aceheaders: true, | |
254 with_acaorigin: true | |
255 }, | |
256 response: {origin: wrong_origin, headers: [test_header]}, | |
257 expectation: verify_network_error | |
258 }, | |
259 { | |
260 description: 'Cross origin fetch without ACEHeaders header, not exposed', | |
261 params: { | |
262 cross_origin: true, | |
263 with_aceheaders: false, | |
264 with_acaorigin: true | |
265 }, | |
266 response: {}, | |
267 expectation: verify_opaque_fetch | |
268 }, | |
269 { | |
270 description: | |
271 'Cross origin fetch without ACEHeaders header, only origin exposed', | |
272 params: { | |
273 cross_origin: true, | |
274 with_aceheaders: false, | |
275 with_acaorigin: true | |
276 }, | |
277 response: {origin: origin}, | |
278 expectation: verify_cors_fetch_without_header | |
279 }, | |
280 { | |
281 description: 'Cross origin fetch without ACEHeaders header, ' + | |
282 'headers and origin exposed', | |
283 params: { | |
284 cross_origin: true, | |
285 with_aceheaders: false, | |
286 with_acaorigin: true | |
287 }, | |
288 response: {origin: origin, headers: [test_header]}, | |
289 expectation: verify_cors_fetch_without_header | |
290 } | |
291 ]; | |
292 | |
293 for (var i = 0; i < tests.length; ++i) (data => { | |
294 promise_test(t => { | |
295 var scope = scope_for_params(data.params); | |
296 var worker = worker_for_response(data.response); | |
297 return install_cross_origin_worker(t, worker, scope) | |
298 .then(() => data.expectation(url_to_fetch(scope), t)); | |
299 }, data.description); | |
300 })(tests[i]); | |
301 </script> | |
302 </body> | |
OLD | NEW |