OLD | NEW |
---|---|
1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
2 <title>Service Worker: Tainting of responses fetched via SW.</title> | 2 <title>Service Worker: Tainting of responses fetched via SW.</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?pipe=sub"></script> | 5 <script src="/common/get-host-info.sub.js?pipe=sub"></script> |
Marijn Kruisselbrink
2017/05/03 17:23:58
nit:
I believe you don't need the "?pipe=sub" whe
mike3
2017/05/03 18:44:03
You are correct:
| |
6 <script src="resources/test-helpers.js"></script> | 6 <script src="resources/test-helpers.sub.js"></script> |
7 <body> | 7 <body> |
8 <script> | 8 <script> |
9 var host_info = get_host_info(); | 9 var host_info = get_host_info(); |
10 var BASE_ORIGIN = host_info.HTTP_ORIGIN; | 10 var BASE_ORIGIN = host_info.HTTPS_ORIGIN; |
11 var OTHER_ORIGIN = host_info.HTTP_REMOTE_ORIGIN; | 11 var OTHER_ORIGIN = host_info.HTTPS_REMOTE_ORIGIN; |
12 var BASE_URL = BASE_ORIGIN + base_path() + | 12 var BASE_URL = BASE_ORIGIN + base_path() + |
13 'resources/fetch-access-control.php?'; | 13 'resources/fetch-access-control.py?'; |
14 var OTHER_BASE_URL = OTHER_ORIGIN + base_path() + | 14 var OTHER_BASE_URL = OTHER_ORIGIN + base_path() + |
15 'resources/fetch-access-control.php?'; | 15 'resources/fetch-access-control.py?'; |
16 | 16 |
17 function frame_fetch(frame, url, mode, credentials) { | 17 function frame_fetch(frame, url, mode, credentials) { |
18 return frame.contentWindow.fetch( | 18 var foreignPromise = frame.contentWindow.fetch( |
19 new Request(url, {mode: mode, credentials: credentials})); | 19 new Request(url, {mode: mode, credentials: credentials})) |
20 | |
21 // Event loops should be shared between contexts of similar origin, not all | |
22 // browsers adhere to this expectation at the time of this writing. Incorrect | |
23 // behavior in this regard can interfere with test execution when the | |
24 // provided iframe is removed from the document. | |
25 // | |
26 // WPT maintains a test dedicated the expected treatment of event loops, so | |
27 // the following workaround is acceptable in this context. | |
28 return Promise.resolve(foreignPromise); | |
20 } | 29 } |
21 | 30 |
22 function ng_test(frame, url, mode, credentials) { | 31 function ng_test(frame, url, mode, credentials) { |
23 return frame_fetch(frame, url, mode, credentials).then( | 32 var prms = frame_fetch(frame, url, mode, credentials).then( |
24 function() { | 33 function() { |
25 throw new Error('fetching url:\"' + url + '\" mode:\"' + mode + | 34 throw new Error('Expected request to fail, but it succeeded.'); |
26 '\" credentials:\"' + credentials + '\" should fail.'); | |
27 }, | 35 }, |
28 function() {}); | 36 function() {}); |
37 | |
38 promise_test(function() { | |
39 return prms; | |
40 }, 'url:\"' + url + '\" mode:\"' + mode + | |
41 '\" credentials:\"' + credentials + '\" should fail.'); | |
42 | |
43 return prms; | |
29 } | 44 } |
30 | 45 |
31 function ok_test(frame, url, mode, credentials, expected_type, | 46 function ok_test(frame, url, mode, credentials, expected_type, |
32 expected_username) { | 47 expected_username) { |
33 return frame_fetch(frame, url, mode, credentials) | 48 var prms = frame_fetch(frame, url, mode, credentials) |
34 .then(function(res) { | 49 .then(function(res) { |
35 assert_equals(res.type, expected_type); | 50 assert_equals(res.type, expected_type, 'response type'); |
36 return res.text(); | 51 return res.text(); |
37 }) | 52 }) |
38 .then(function(text) { | 53 .then(function(text) { |
39 if (expected_type == 'opaque') { | 54 if (expected_type == 'opaque') { |
40 assert_equals(text, ''); | 55 assert_equals(text, ''); |
41 } else { | 56 } else { |
42 return new Promise(function(resolve) { | 57 return new Promise(function(resolve) { |
43 var report = resolve; | 58 var report = resolve; |
44 // text must contain report() call. | 59 // text must contain report() call. |
45 eval(text); | 60 eval(text); |
46 }) | 61 }) |
47 .then(function(result) { | 62 .then(function(result) { |
48 assert_equals(result.username, expected_username); | 63 assert_equals(result.username, expected_username); |
49 }); | 64 }); |
50 } | 65 } |
51 }) | 66 }); |
52 .catch(function(reason) { | 67 |
53 throw new Error('fetching url:\"' + url + '\" mode:\"' + mode + | 68 promise_test(function() { |
69 return prms; | |
70 }, 'fetching url:\"' + url + '\" mode:\"' + mode + | |
54 '\" credentials:\"' + credentials + '\" should ' + | 71 '\" credentials:\"' + credentials + '\" should ' + |
55 'success. - ' + reason.message); | 72 'succeed.'); |
56 }); | 73 |
74 return prms; | |
57 } | 75 } |
58 | 76 |
59 function build_rewrite_url(origin, url, mode, credentials) { | 77 function build_rewrite_url(origin, url, mode, credentials) { |
60 return origin + '/?url=' + encodeURIComponent(url) + '&mode=' + mode + | 78 return origin + '/?url=' + encodeURIComponent(url) + '&mode=' + mode + |
61 '&credentials=' + credentials + '&'; | 79 '&credentials=' + credentials + '&'; |
62 } | 80 } |
63 | 81 |
64 function for_each_origin_mode_credentials(callback) { | 82 function for_each_origin_mode_credentials(callback) { |
65 [BASE_ORIGIN, OTHER_ORIGIN].forEach(function(origin) { | 83 [BASE_ORIGIN, OTHER_ORIGIN].forEach(function(origin) { |
66 ['same-origin', 'no-cors', 'cors'].forEach(function(mode) { | 84 ['same-origin', 'no-cors', 'cors'].forEach(function(mode) { |
67 ['omit', 'same-origin', 'include'].forEach(function(credentials) { | 85 ['omit', 'same-origin', 'include'].forEach(function(credentials) { |
68 callback(origin, mode, credentials); | 86 callback(origin, mode, credentials); |
69 }); | 87 }); |
70 }); | 88 }); |
71 }); | 89 }); |
72 } | 90 } |
73 | 91 |
92 // Create a Promise that is fulfilled when all the provided Promises have | |
93 // settled. This is necessary to correctly defer test clean up until all sub | |
94 // tests have completed (regardless of their passing or failing status). | |
95 function allSettled(promises) { | |
96 var noop = function() {}; | |
97 var caught = promises.map(function(promise) { return promise.catch(noop); }); | |
98 return Promise.all(caught); | |
99 } | |
100 | |
74 promise_test(function(t) { | 101 promise_test(function(t) { |
75 var SCOPE = 'resources/fetch-response-taint-iframe.html'; | 102 var SCOPE = 'resources/fetch-response-taint-iframe.html'; |
76 var SCRIPT = 'resources/fetch-rewrite-worker.js'; | 103 var SCRIPT = 'resources/fetch-rewrite-worker.js'; |
77 var frame = undefined; | |
78 | 104 |
79 return login(t, host_info.HTTP_ORIGIN, host_info.HTTP_REMOTE_ORIGIN) | 105 return login_https(t, host_info.HTTPS_ORIGIN, host_info.HTTPS_REMOTE_ORIGIN) |
80 .then(function() { | 106 .then(function() { |
81 return service_worker_unregister_and_register(t, SCRIPT, SCOPE); | 107 return service_worker_unregister_and_register(t, SCRIPT, SCOPE); |
82 }) | 108 }) |
83 .then(function(registration) { | 109 .then(function(registration) { |
84 return wait_for_state(t, registration.installing, 'activated'); | 110 return wait_for_state(t, registration.installing, 'activated'); |
85 }) | 111 }) |
86 .then(function() { return with_iframe(SCOPE); }) | 112 .then(function() { return with_iframe(SCOPE); }) |
87 .then(function(f) { | 113 .then(function(f) { |
88 frame = f; | 114 t.add_cleanup(function() { f.remove(); }); |
89 var promises = [ | 115 var promises = [ |
90 ok_test(f, BASE_URL, 'same-origin', 'omit', 'basic', 'undefined'), | 116 ok_test(f, BASE_URL, 'same-origin', 'omit', 'basic', 'undefined'), |
91 ok_test(f, BASE_URL, 'same-origin', 'same-origin', 'basic', | 117 ok_test(f, BASE_URL, 'same-origin', 'same-origin', 'basic', |
92 'username1'), | 118 'username2s'), |
93 ok_test(f, BASE_URL, 'same-origin', 'include', 'basic', | 119 ok_test(f, BASE_URL, 'same-origin', 'include', 'basic', |
94 'username1'), | 120 'username2s'), |
95 ok_test(f, BASE_URL, 'no-cors', 'omit', 'basic', 'undefined'), | 121 ok_test(f, BASE_URL, 'no-cors', 'omit', 'basic', 'undefined'), |
96 ok_test(f, BASE_URL, 'no-cors', 'same-origin', 'basic', | 122 ok_test(f, BASE_URL, 'no-cors', 'same-origin', 'basic', |
97 'username1'), | 123 'username2s'), |
98 ok_test(f, BASE_URL, 'no-cors', 'include', 'basic', 'username1'), | 124 ok_test(f, BASE_URL, 'no-cors', 'include', 'basic', 'username2s'), |
99 ok_test(f, BASE_URL, 'cors', 'omit', 'basic', 'undefined'), | 125 ok_test(f, BASE_URL, 'cors', 'omit', 'basic', 'undefined'), |
100 ok_test(f, BASE_URL, 'cors', 'same-origin', 'basic', 'username1'), | 126 ok_test(f, BASE_URL, 'cors', 'same-origin', 'basic', 'username2s'), |
101 ok_test(f, BASE_URL, 'cors', 'include', 'basic', 'username1'), | 127 ok_test(f, BASE_URL, 'cors', 'include', 'basic', 'username2s'), |
102 ng_test(f, OTHER_BASE_URL, 'same-origin', 'omit'), | 128 ng_test(f, OTHER_BASE_URL, 'same-origin', 'omit'), |
103 ng_test(f, OTHER_BASE_URL, 'same-origin', 'same-origin'), | 129 ng_test(f, OTHER_BASE_URL, 'same-origin', 'same-origin'), |
104 ng_test(f, OTHER_BASE_URL, 'same-origin', 'include'), | 130 ng_test(f, OTHER_BASE_URL, 'same-origin', 'include'), |
105 ok_test(f, OTHER_BASE_URL, 'no-cors', 'omit', 'opaque'), | 131 ok_test(f, OTHER_BASE_URL, 'no-cors', 'omit', 'opaque'), |
106 ok_test(f, OTHER_BASE_URL, 'no-cors', 'same-origin', 'opaque'), | 132 ok_test(f, OTHER_BASE_URL, 'no-cors', 'same-origin', 'opaque'), |
107 ok_test(f, OTHER_BASE_URL, 'no-cors', 'include', 'opaque'), | 133 ok_test(f, OTHER_BASE_URL, 'no-cors', 'include', 'opaque'), |
108 ng_test(f, OTHER_BASE_URL, 'cors', 'omit'), | 134 ng_test(f, OTHER_BASE_URL, 'cors', 'omit'), |
109 ng_test(f, OTHER_BASE_URL, 'cors', 'same-origin'), | 135 ng_test(f, OTHER_BASE_URL, 'cors', 'same-origin'), |
110 ng_test(f, OTHER_BASE_URL, 'cors', 'include'), | 136 ng_test(f, OTHER_BASE_URL, 'cors', 'include'), |
111 ok_test(f, OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'omit', 'cors', | 137 ok_test(f, OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'omit', 'cors', |
112 'undefined'), | 138 'undefined'), |
113 ok_test(f, OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'same-origin', | 139 ok_test(f, OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'same-origin', |
114 'cors', 'undefined'), | 140 'cors', 'undefined'), |
115 ng_test(f, OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'include'), | 141 ng_test(f, OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'include'), |
116 ok_test(f, | 142 ok_test(f, |
117 OTHER_BASE_URL + 'ACAOrigin=' + BASE_ORIGIN + | 143 OTHER_BASE_URL + 'ACAOrigin=' + BASE_ORIGIN + |
118 '&ACACredentials=true', | 144 '&ACACredentials=true', |
119 'cors', 'include', 'cors', 'username2') | 145 'cors', 'include', 'cors', 'username1s') |
120 ]; | 146 ]; |
121 | 147 |
122 for_each_origin_mode_credentials(function(origin, mode, credentials) { | 148 for_each_origin_mode_credentials(function(origin, mode, credentials) { |
123 var url = build_rewrite_url( | 149 var url = build_rewrite_url( |
124 origin, BASE_URL, 'same-origin', 'omit'); | 150 origin, BASE_URL, 'same-origin', 'omit'); |
125 // Fetch to the other origin with same-origin mode should fail. | 151 // Fetch to the other origin with same-origin mode should fail. |
126 if (origin == OTHER_ORIGIN && mode == 'same-origin') | 152 if (origin == OTHER_ORIGIN && mode == 'same-origin') { |
127 return promises.push(ng_test(f, url, mode, credentials)); | 153 promises.push(ng_test(f, url, mode, credentials)); |
128 // The response type from the SW should be basic | 154 } else { |
129 promises.push( | 155 // The response type from the SW should be basic |
156 promises.push( | |
130 ok_test(f, url, mode, credentials, 'basic', 'undefined')); | 157 ok_test(f, url, mode, credentials, 'basic', 'undefined')); |
158 } | |
131 }); | 159 }); |
132 | 160 |
133 for_each_origin_mode_credentials(function(origin, mode, credentials) { | 161 for_each_origin_mode_credentials(function(origin, mode, credentials) { |
134 var url = build_rewrite_url( | 162 var url = build_rewrite_url( |
135 origin, BASE_URL, 'same-origin', 'same-origin'); | 163 origin, BASE_URL, 'same-origin', 'same-origin'); |
164 | |
136 // Fetch to the other origin with same-origin mode should fail. | 165 // Fetch to the other origin with same-origin mode should fail. |
137 if (origin == OTHER_ORIGIN && mode == 'same-origin') | 166 if (origin == OTHER_ORIGIN && mode == 'same-origin') { |
138 return promises.push(ng_test(f, url, mode, credentials)); | 167 promises.push(ng_test(f, url, mode, credentials)); |
139 // The response type from the SW should be basic. | 168 // The response type from the SW should be basic. |
140 promises.push( | 169 } else { |
141 ok_test(f, url, mode, credentials, 'basic', 'username1')); | 170 promises.push( |
171 ok_test(f, url, mode, credentials, 'basic', 'username2s')); | |
172 } | |
142 }); | 173 }); |
143 | 174 |
144 for_each_origin_mode_credentials(function(origin, mode, credentials) { | 175 for_each_origin_mode_credentials(function(origin, mode, credentials) { |
145 var url = build_rewrite_url( | 176 var url = build_rewrite_url( |
146 origin, OTHER_BASE_URL, 'same-origin', 'omit'); | 177 origin, OTHER_BASE_URL, 'same-origin', 'omit'); |
147 // The response from the SW should be an error. | 178 // The response from the SW should be an error. |
148 promises.push(ng_test(f, url, mode, credentials)); | 179 promises.push(ng_test(f, url, mode, credentials)); |
149 }); | 180 }); |
150 | 181 |
151 for_each_origin_mode_credentials(function(origin, mode, credentials) { | 182 for_each_origin_mode_credentials(function(origin, mode, credentials) { |
152 var url = build_rewrite_url( | 183 var url = build_rewrite_url( |
153 origin, OTHER_BASE_URL, 'no-cors', 'omit'); | 184 origin, OTHER_BASE_URL, 'no-cors', 'omit'); |
185 | |
154 // SW can respond only to no-cors requests. | 186 // SW can respond only to no-cors requests. |
155 if (mode != 'no-cors') | 187 if (mode != 'no-cors') { |
156 return promises.push(ng_test(f, url, mode, credentials)); | 188 promises.push(ng_test(f, url, mode, credentials)); |
157 // The response type from the SW should be opaque. | 189 } else { |
158 promises.push(ok_test(f, url, mode, credentials, 'opaque')); | 190 // The response type from the SW should be opaque. |
191 promises.push(ok_test(f, url, mode, credentials, 'opaque')); | |
192 } | |
159 }); | 193 }); |
160 | 194 |
161 for_each_origin_mode_credentials(function(origin, mode, credentials) { | 195 for_each_origin_mode_credentials(function(origin, mode, credentials) { |
162 var url = build_rewrite_url( | 196 var url = build_rewrite_url( |
163 origin, OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'omit'); | 197 origin, OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'omit'); |
198 | |
164 // Fetch to the other origin with same-origin mode should fail. | 199 // Fetch to the other origin with same-origin mode should fail. |
165 if (origin == OTHER_ORIGIN && mode == 'same-origin') | 200 if (origin == OTHER_ORIGIN && mode == 'same-origin') { |
166 return promises.push(ng_test(f, url, mode, credentials)); | 201 promises.push(ng_test(f, url, mode, credentials)); |
167 // The response from the SW should be cors. | 202 } else { |
168 promises.push( | 203 // The response from the SW should be cors. |
204 promises.push( | |
169 ok_test(f, url, mode, credentials, 'cors', 'undefined')); | 205 ok_test(f, url, mode, credentials, 'cors', 'undefined')); |
206 } | |
170 }); | 207 }); |
171 | 208 |
172 for_each_origin_mode_credentials(function(origin, mode, credentials) { | 209 for_each_origin_mode_credentials(function(origin, mode, credentials) { |
173 var url = build_rewrite_url( | 210 var url = build_rewrite_url( |
174 origin, | 211 origin, |
175 OTHER_BASE_URL + 'ACAOrigin=' + BASE_ORIGIN + | 212 OTHER_BASE_URL + 'ACAOrigin=' + BASE_ORIGIN + |
176 '&ACACredentials=true', | 213 '&ACACredentials=true', |
177 'cors', 'include'); | 214 'cors', 'include'); |
178 // Fetch to the other origin with same-origin mode should fail. | 215 // Fetch to the other origin with same-origin mode should fail. |
179 if (origin == OTHER_ORIGIN && mode == 'same-origin') | 216 if (origin == OTHER_ORIGIN && mode == 'same-origin') { |
180 return promises.push(ng_test(f, url, mode, credentials)); | 217 promises.push(ng_test(f, url, mode, credentials)); |
181 // The response from the SW should be cors. | 218 } else { |
182 promises.push( | 219 // The response from the SW should be cors. |
183 ok_test(f, url, mode, credentials, 'cors', 'username2')); | 220 promises.push( |
221 ok_test(f, url, mode, credentials, 'cors', 'username1s')); | |
222 } | |
184 }); | 223 }); |
185 return Promise.all(promises); | 224 |
186 }) | 225 return allSettled(promises) |
187 .then(function(f) { | 226 .then(function() { |
188 frame.remove() | 227 return service_worker_unregister_and_done(t, SCOPE); |
189 }) | 228 }); |
190 .catch(unreached_rejection(t)); | 229 }); |
191 }, 'Verify the tainting of responses fetched via SW'); | 230 }, 'Verify the tainting of responses fetched via SW'); |
192 </script> | 231 </script> |
193 </body> | 232 </body> |
OLD | NEW |