fetch-response-taint.https.html (8920B)
1 <!DOCTYPE html> 2 <title>Service Worker: Tainting of responses fetched via SW.</title> 3 <!-- This test makes a large number of requests sequentially. --> 4 <meta name="timeout" content="long"> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="/common/get-host-info.sub.js"></script> 8 <script src="resources/test-helpers.sub.js"></script> 9 <body> 10 <script> 11 var host_info = get_host_info(); 12 var BASE_ORIGIN = host_info.HTTPS_ORIGIN; 13 var OTHER_ORIGIN = host_info.HTTPS_REMOTE_ORIGIN; 14 var BASE_URL = BASE_ORIGIN + base_path() + 15 'resources/fetch-access-control.py?'; 16 var OTHER_BASE_URL = OTHER_ORIGIN + base_path() + 17 'resources/fetch-access-control.py?'; 18 19 function frame_fetch(frame, url, mode, credentials) { 20 var foreignPromise = frame.contentWindow.fetch( 21 new Request(url, {mode: mode, credentials: credentials})) 22 23 // Event loops should be shared between contexts of similar origin, not all 24 // browsers adhere to this expectation at the time of this writing. Incorrect 25 // behavior in this regard can interfere with test execution when the 26 // provided iframe is removed from the document. 27 // 28 // WPT maintains a test dedicated the expected treatment of event loops, so 29 // the following workaround is acceptable in this context. 30 return Promise.resolve(foreignPromise); 31 } 32 33 var login_and_register; 34 promise_test(function(t) { 35 var SCOPE = 'resources/fetch-response-taint-iframe.html'; 36 var SCRIPT = 'resources/fetch-rewrite-worker.js'; 37 var registration; 38 39 login_and_register = login_https(t, host_info.HTTPS_ORIGIN, host_info.HTTPS_REMOTE_ORIGIN) 40 .then(function() { 41 return service_worker_unregister_and_register(t, SCRIPT, SCOPE); 42 }) 43 .then(function(r) { 44 registration = r; 45 return wait_for_state(t, registration.installing, 'activated'); 46 }) 47 .then(function() { return with_iframe(SCOPE); }) 48 .then(function(f) { 49 // This test should not be considered complete until after the 50 // service worker has been unregistered. Currently, `testharness.js` 51 // does not support asynchronous global "tear down" logic, so this 52 // must be expressed using a dedicated `promise_test`. Because the 53 // other sub-tests in this file are declared synchronously, this 54 // test will be the final test executed. 55 promise_test(function(t) { 56 f.remove(); 57 return registration.unregister(); 58 }, 'restore global state'); 59 60 return f; 61 }); 62 return login_and_register; 63 }, 'initialize global state'); 64 65 function ng_test(url, mode, credentials) { 66 promise_test(function(t) { 67 return login_and_register 68 .then(function(frame) { 69 var fetchRequest = frame_fetch(frame, url, mode, credentials); 70 return promise_rejects_js(t, frame.contentWindow.TypeError, fetchRequest); 71 }); 72 }, 'url:\"' + url + '\" mode:\"' + mode + 73 '\" credentials:\"' + credentials + '\" should fail.'); 74 } 75 76 function ok_test(url, mode, credentials, expected_type, expected_username) { 77 promise_test(function() { 78 return login_and_register.then(function(frame) { 79 return frame_fetch(frame, url, mode, credentials) 80 }) 81 .then(function(res) { 82 assert_equals(res.type, expected_type, 'response type'); 83 return res.text(); 84 }) 85 .then(function(text) { 86 if (expected_type == 'opaque') { 87 assert_equals(text, ''); 88 } else { 89 return new Promise(function(resolve) { 90 var report = resolve; 91 // text must contain report() call. 92 eval(text); 93 }) 94 .then(function(result) { 95 assert_equals(result.username, expected_username); 96 }); 97 } 98 }); 99 }, 'fetching url:\"' + url + '\" mode:\"' + mode + 100 '\" credentials:\"' + credentials + '\" should ' + 101 'succeed.'); 102 } 103 104 function build_rewrite_url(origin, url, mode, credentials) { 105 return origin + '/?url=' + encodeURIComponent(url) + '&mode=' + mode + 106 '&credentials=' + credentials + '&'; 107 } 108 109 function for_each_origin_mode_credentials(callback) { 110 [BASE_ORIGIN, OTHER_ORIGIN].forEach(function(origin) { 111 ['same-origin', 'no-cors', 'cors'].forEach(function(mode) { 112 ['omit', 'same-origin', 'include'].forEach(function(credentials) { 113 callback(origin, mode, credentials); 114 }); 115 }); 116 }); 117 } 118 119 ok_test(BASE_URL, 'same-origin', 'omit', 'basic', 'undefined'); 120 ok_test(BASE_URL, 'same-origin', 'same-origin', 'basic', 'username2s'); 121 ok_test(BASE_URL, 'same-origin', 'include', 'basic', 'username2s'); 122 ok_test(BASE_URL, 'no-cors', 'omit', 'basic', 'undefined'); 123 ok_test(BASE_URL, 'no-cors', 'same-origin', 'basic', 'username2s'); 124 ok_test(BASE_URL, 'no-cors', 'include', 'basic', 'username2s'); 125 ok_test(BASE_URL, 'cors', 'omit', 'basic', 'undefined'); 126 ok_test(BASE_URL, 'cors', 'same-origin', 'basic', 'username2s'); 127 ok_test(BASE_URL, 'cors', 'include', 'basic', 'username2s'); 128 ng_test(OTHER_BASE_URL, 'same-origin', 'omit'); 129 ng_test(OTHER_BASE_URL, 'same-origin', 'same-origin'); 130 ng_test(OTHER_BASE_URL, 'same-origin', 'include'); 131 ok_test(OTHER_BASE_URL, 'no-cors', 'omit', 'opaque'); 132 ok_test(OTHER_BASE_URL, 'no-cors', 'same-origin', 'opaque'); 133 ok_test(OTHER_BASE_URL, 'no-cors', 'include', 'opaque'); 134 ng_test(OTHER_BASE_URL, 'cors', 'omit'); 135 ng_test(OTHER_BASE_URL, 'cors', 'same-origin'); 136 ng_test(OTHER_BASE_URL, 'cors', 'include'); 137 ok_test(OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'omit', 'cors', 'undefined'); 138 ok_test(OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'same-origin', 'cors', 139 'undefined'); 140 ng_test(OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'include'); 141 ok_test(OTHER_BASE_URL + 'ACAOrigin=' + BASE_ORIGIN + '&ACACredentials=true', 142 'cors', 'include', 'cors', 'username1s') 143 144 for_each_origin_mode_credentials(function(origin, mode, credentials) { 145 var url = build_rewrite_url( 146 origin, BASE_URL, 'same-origin', 'omit'); 147 // Fetch to the other origin with same-origin mode should fail. 148 if (origin == OTHER_ORIGIN && mode == 'same-origin') { 149 ng_test(url, mode, credentials); 150 } else { 151 // The response type from the SW should be basic 152 ok_test(url, mode, credentials, 'basic', 'undefined'); 153 } 154 }); 155 156 for_each_origin_mode_credentials(function(origin, mode, credentials) { 157 var url = build_rewrite_url( 158 origin, BASE_URL, 'same-origin', 'same-origin'); 159 160 // Fetch to the other origin with same-origin mode should fail. 161 if (origin == OTHER_ORIGIN && mode == 'same-origin') { 162 ng_test(url, mode, credentials); 163 } else { 164 // The response type from the SW should be basic. 165 ok_test(url, mode, credentials, 'basic', 'username2s'); 166 } 167 }); 168 169 for_each_origin_mode_credentials(function(origin, mode, credentials) { 170 var url = build_rewrite_url( 171 origin, OTHER_BASE_URL, 'same-origin', 'omit'); 172 // The response from the SW should be an error. 173 ng_test(url, mode, credentials); 174 }); 175 176 for_each_origin_mode_credentials(function(origin, mode, credentials) { 177 var url = build_rewrite_url( 178 origin, OTHER_BASE_URL, 'no-cors', 'omit'); 179 180 // SW can respond only to no-cors requests. 181 if (mode != 'no-cors') { 182 ng_test(url, mode, credentials); 183 } else { 184 // The response type from the SW should be opaque. 185 ok_test(url, mode, credentials, 'opaque'); 186 } 187 }); 188 189 for_each_origin_mode_credentials(function(origin, mode, credentials) { 190 var url = build_rewrite_url( 191 origin, OTHER_BASE_URL + 'ACAOrigin=*', 'cors', 'omit'); 192 193 // Fetch to the other origin with same-origin mode should fail. 194 if (origin == OTHER_ORIGIN && mode == 'same-origin') { 195 ng_test(url, mode, credentials); 196 } else if (origin == BASE_ORIGIN && mode == 'same-origin') { 197 // Cors type response to a same-origin mode request should fail 198 ng_test(url, mode, credentials); 199 } else { 200 // The response from the SW should be cors. 201 ok_test(url, mode, credentials, 'cors', 'undefined'); 202 } 203 }); 204 205 for_each_origin_mode_credentials(function(origin, mode, credentials) { 206 var url = build_rewrite_url( 207 origin, 208 OTHER_BASE_URL + 'ACAOrigin=' + BASE_ORIGIN + 209 '&ACACredentials=true', 210 'cors', 'include'); 211 // Fetch to the other origin with same-origin mode should fail. 212 if (origin == OTHER_ORIGIN && mode == 'same-origin') { 213 ng_test(url, mode, credentials); 214 } else if (origin == BASE_ORIGIN && mode == 'same-origin') { 215 // Cors type response to a same-origin mode request should fail 216 ng_test(url, mode, credentials); 217 } else { 218 // The response from the SW should be cors. 219 ok_test(url, mode, credentials, 'cors', 'username1s'); 220 } 221 }); 222 </script> 223 </body>