| 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 | |
| 11 function worker_for_origins(origins) { | |
| 12 var worker = 'foreign-fetch-worker.js?'; | |
| 13 var params = {origins: origins, relscopes: ['/intercept']}; | |
| 14 return worker + encodeURIComponent(JSON.stringify(params)); | |
| 15 } | |
| 16 | |
| 17 function worker_for_scopes(relative_scopes) { | |
| 18 var worker = 'foreign-fetch-worker.js?'; | |
| 19 var params = {relscopes: relative_scopes}; | |
| 20 return worker + encodeURIComponent(JSON.stringify(params)); | |
| 21 } | |
| 22 | |
| 23 function intercepted_url(scope) { | |
| 24 return host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + | |
| 25 scope + '/intercept/foo?basic'; | |
| 26 } | |
| 27 | |
| 28 function non_intercepted_url(scope) { | |
| 29 return host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + | |
| 30 scope + '/foo?basic'; | |
| 31 } | |
| 32 | |
| 33 promise_test(t => { | |
| 34 var scope = 'foreign-fetch/scope/wildcard'; | |
| 35 return install_cross_origin_worker(t, worker_for_origins(['*']), scope) | |
| 36 .then(() => promise_rejects(t, new TypeError(), | |
| 37 fetch(non_intercepted_url(scope)))) | |
| 38 .then(() => fetch(intercepted_url(scope))) | |
| 39 .then(response => response.text()) | |
| 40 .then(response_text => { | |
| 41 assert_equals(response_text, 'Foreign Fetch'); | |
| 42 }); | |
| 43 }, 'Service Worker intercepts fetches in scope with wildcard origin.'); | |
| 44 | |
| 45 promise_test(t => { | |
| 46 var scope = 'foreign-fetch/scope/match-origin'; | |
| 47 return install_cross_origin_worker( | |
| 48 t, worker_for_origins([location.origin]), scope) | |
| 49 .then(() => fetch(intercepted_url(scope))) | |
| 50 .then(response => response.text()) | |
| 51 .then(response_text => { | |
| 52 assert_equals(response_text, 'Foreign Fetch'); | |
| 53 }); | |
| 54 }, 'Service Worker intercepts fetches in scope with explicit origin.'); | |
| 55 | |
| 56 promise_test(t => { | |
| 57 var scope = 'foreign-fetch/scope/nomatch-origin'; | |
| 58 return install_cross_origin_worker( | |
| 59 t, worker_for_origins(['https://example.com']), scope) | |
| 60 .then(() => promise_rejects(t, new TypeError(), | |
| 61 fetch(non_intercepted_url(scope)))); | |
| 62 }, 'Service Worker doesn\'t intercept fetches with non matching origin.'); | |
| 63 | |
| 64 promise_test(t => { | |
| 65 var scope = 'foreign-fetch/scope/origin-list'; | |
| 66 return install_cross_origin_worker( | |
| 67 t, worker_for_origins([location.origin, 'https://example.com']), scope) | |
| 68 .then(() => fetch(intercepted_url(scope))) | |
| 69 .then(response => response.text()) | |
| 70 .then(response_text => { | |
| 71 assert_equals(response_text, 'Foreign Fetch'); | |
| 72 }); | |
| 73 }, 'Service Worker intercepts fetches in scope with explicit origin list.'); | |
| 74 | |
| 75 promise_test(t => { | |
| 76 var scope = 'resources/foreign-fetch/same-origin'; | |
| 77 return service_worker_unregister_and_register( | |
| 78 t, 'resources/' + worker_for_origins(['*']), scope) | |
| 79 .then(r => { | |
| 80 add_completion_callback(() => r.unregister()); | |
| 81 return wait_for_state(t, r.installing, 'activated'); | |
| 82 }) | |
| 83 .then(() => fetch(scope + '/intercept/foo?basic')) | |
| 84 .then(response => { | |
| 85 assert_equals(response.status, 404); | |
| 86 }); | |
| 87 }, 'Service Worker does not intercept same origin fetches.'); | |
| 88 | |
| 89 promise_test(t => { | |
| 90 var scope = 'reply-to-message.html?onmessage'; | |
| 91 var remote_url = | |
| 92 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + scope; | |
| 93 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) | |
| 94 .then(() => with_iframe(remote_url)) | |
| 95 .then(frame => new Promise(resolve => { | |
| 96 var channel = new MessageChannel(); | |
| 97 frame.contentWindow.postMessage('ping', '*', [channel.port1]); | |
| 98 channel.port2.onmessage = reply => resolve(reply.data); | |
| 99 })) | |
| 100 .then(reply => { | |
| 101 assert_equals(reply, 'ping'); | |
| 102 }); | |
| 103 }, 'Service Worker does not intercept navigations.'); | |
| 104 | |
| 105 promise_test(t => { | |
| 106 var scope = 'fetch-access-control.php?fallback&ACAOrigin=*'; | |
| 107 var remote_url = | |
| 108 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + scope; | |
| 109 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) | |
| 110 .then(() => fetch(remote_url)) | |
| 111 .then(response => response.text()) | |
| 112 .then(response_text => assert_true(response_text.startsWith('report('))); | |
| 113 }, 'Service Worker that fallback to network should fallback to network.'); | |
| 114 | |
| 115 promise_test(t => { | |
| 116 var scope = 'fetch-access-control.php?fetch&ACAOrigin=*'; | |
| 117 var remote_url = | |
| 118 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + scope; | |
| 119 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) | |
| 120 .then(() => fetch(remote_url)) | |
| 121 .then(response => response.text()) | |
| 122 .then(response_text => assert_true(response_text.startsWith('report('))); | |
| 123 }, 'Service Worker that fetch from the network should fallback to network.'); | |
| 124 | |
| 125 promise_test(t => { | |
| 126 var scope = 'simple.txt?fallback'; | |
| 127 var remote_url = | |
| 128 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + scope; | |
| 129 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) | |
| 130 .then(() => fetch(remote_url, {mode: 'no-cors'})) | |
| 131 .then(response => assert_equals(response.type, 'opaque')) | |
| 132 .then(() => promise_rejects(t, new TypeError(), fetch(remote_url))); | |
| 133 }, 'Falling back to network should still respect CORS.'); | |
| 134 | |
| 135 promise_test(t => { | |
| 136 var ff_scope = 'foreign-fetch/scope/controlled?basic'; | |
| 137 var remote_url = | |
| 138 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + ff_scope; | |
| 139 var scope = 'resources/simple.html?fetch'; | |
| 140 var worker = 'resources/empty-worker.js'; | |
| 141 return install_cross_origin_worker(t, worker_for_scopes(['']), ff_scope) | |
| 142 .then(() => service_worker_unregister_and_register(t, worker, scope)) | |
| 143 .then(r => { | |
| 144 add_completion_callback(() => r.unregister()); | |
| 145 return wait_for_state(t, r.installing, 'activated'); | |
| 146 }) | |
| 147 .then(() => with_iframe(scope)) | |
| 148 .then(frame => frame.contentWindow.fetch(remote_url)) | |
| 149 .then(response => response.text()) | |
| 150 .then(response_text => { | |
| 151 assert_equals(response_text, 'Foreign Fetch'); | |
| 152 }); | |
| 153 }, 'Foreign fetch can intercept fetch requests from SW controlled pages.'); | |
| 154 | |
| 155 promise_test(t => { | |
| 156 var ff_scope = 'foreign-fetch/scope/controlled?script'; | |
| 157 var remote_url = | |
| 158 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + ff_scope; | |
| 159 var scope = 'resources/simple.html?script'; | |
| 160 var worker = 'resources/empty-worker.js'; | |
| 161 return install_cross_origin_worker(t, worker_for_scopes(['']), ff_scope) | |
| 162 .then(() => service_worker_unregister_and_register(t, worker, scope)) | |
| 163 .then(r => { | |
| 164 add_completion_callback(() => r.unregister()); | |
| 165 return wait_for_state(t, r.installing, 'activated'); | |
| 166 }) | |
| 167 .then(() => with_iframe(scope)) | |
| 168 .then(frame => new Promise(resolve => { | |
| 169 frame.contentWindow.DidLoad = resolve; | |
| 170 let script = frame.contentWindow.document.createElement('script'); | |
| 171 script.setAttribute('src', remote_url); | |
| 172 script.setAttribute('crossorigin', 'use-credentials'); | |
| 173 frame.contentWindow.document.head.appendChild(script); | |
| 174 })) | |
| 175 .then(response_text => { | |
| 176 assert_equals(response_text, 'Foreign Fetch'); | |
| 177 }); | |
| 178 }, 'Foreign fetch can intercept resource requests from SW controlled pages.'); | |
| 179 | |
| 180 promise_test(t => { | |
| 181 var scope = 'simple.txt?meta'; | |
| 182 var remote_url = | |
| 183 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + scope; | |
| 184 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) | |
| 185 .then(() => fetch(remote_url, {mode: 'no-cors'})) | |
| 186 .then(response => response.json()) | |
| 187 .then(response_data => { | |
| 188 assert_equals(self.location.href, response_data.referrer); | |
| 189 assert_equals(self.location.origin, response_data.origin); | |
| 190 }) | |
| 191 .then(() => with_iframe('resources/blank.html')) | |
| 192 .then(frame => { | |
| 193 var meta = frame.contentDocument.createElement('meta'); | |
| 194 meta.setAttribute('name', 'referrer'); | |
| 195 meta.setAttribute('content', 'no-referrer'); | |
| 196 frame.contentDocument.head.appendChild(meta); | |
| 197 return frame.contentWindow.fetch(remote_url, {mode: 'no-cors'}); | |
| 198 }) | |
| 199 .then(response => response.json()) | |
| 200 .then(response_data => { | |
| 201 assert_equals('', response_data.referrer); | |
| 202 assert_equals('null', response_data.origin); | |
| 203 }); | |
| 204 }, 'Referrer and origin are set correctly in ForeignFetchEvent.'); | |
| 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 => { | |
| 219 var scope = 'simple.txt?basic_insecure'; | |
| 220 var remote_url = | |
| 221 host_info.AUTHENTICATED_ORIGIN + '/serviceworker/resources/' + scope; | |
| 222 return install_cross_origin_worker(t, worker_for_scopes(['']), scope, | |
| 223 host_info.AUTHENTICATED_ORIGIN) | |
| 224 .then(() => fetch_from_iframe(host_info.HTTPS_REMOTE_ORIGIN, remote_url)) | |
| 225 .then(response => assert_equals(response, 'Success: Foreign Fetch')) | |
| 226 .then(() => fetch_from_iframe(host_info.UNAUTHENTICATED_ORIGIN, | |
| 227 remote_url)) | |
| 228 .then(response => assert_equals(response, | |
| 229 'Error: TypeError: Failed to fetch')); | |
| 230 }, 'Service Worker does not intercept fetches from an insecure context.'); | |
| 231 | |
| 232 promise_test(t => { | |
| 233 var scope = 'fetch-access-control.php?basic&ACAOrigin=*&ACAMethods=SPECIAL'; | |
| 234 var remote_url = | |
| 235 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + scope; | |
| 236 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) | |
| 237 .then(() => fetch(remote_url, {method: 'SPECIAL'})) | |
| 238 .then(response => response.text()) | |
| 239 .then(response_text => assert_true(response_text.startsWith('report('))) | |
| 240 // Do the whole thing twice to test CORS preflight cache behavior. | |
| 241 .then(() => fetch(remote_url, {method: 'SPECIAL'})) | |
| 242 .then(response => response.text()) | |
| 243 .then(response_text => assert_true(response_text.startsWith('report('))); | |
| 244 }, 'Service Worker does not intercept fetches with CORS preflight'); | |
| 245 | |
| 246 promise_test(t => { | |
| 247 var scope = 'simple.txt?null'; | |
| 248 var remote_url = | |
| 249 host_info.HTTPS_REMOTE_ORIGIN + '/serviceworker/resources/' + scope; | |
| 250 return install_cross_origin_worker(t, worker_for_scopes(['']), scope) | |
| 251 .then(() => promise_rejects(t, new TypeError(), fetch(remote_url))); | |
| 252 }, 'Foreign fetch rejects if resolved with a null response.'); | |
| 253 </script> | |
| 254 </body> | |
| OLD | NEW |