cross-partition.https.html (19612B)
1 <!DOCTYPE html> 2 <meta charset=utf-8> 3 <meta name="timeout" content="long"> 4 <script src="/resources/testharness.js"></script> 5 <script src="/resources/testharnessreport.js"></script> 6 <script src="/common/get-host-info.sub.js"></script> 7 <script src="/common/utils.js"></script> 8 <script src="/common/dispatcher/dispatcher.js"></script> 9 <!-- Pull in executor_path needed by newPopup / newIframe --> 10 <script src="/html/cross-origin-embedder-policy/credentialless/resources/common.js"></script> 11 <!-- Pull in importScript / newPopup / newIframe --> 12 <script src="/html/anonymous-iframe/resources/common.js"></script> 13 <script src="resources/common.js"></script> 14 <body> 15 <script> 16 17 const fetch_unsuccessful_response = "Fetch failed"; 18 const fetch_successful_response = "Fetch succeeded"; 19 const js_finished = "revoking blob_url js finished"; 20 21 // Fetches a previously revoked blob_url to see if the revoking was successful. 22 async function fetch_contents_check(blob_url) { 23 try { 24 const blob = await fetch(blob_url).then(response => response.blob()); 25 await blob.text(); 26 } catch(e) { 27 return fetch_unsuccessful_response; 28 } 29 return fetch_successful_response; 30 } 31 32 const can_blob_url_be_revoked_js = (blob_url, response_queue_name) => ` 33 async function test() { 34 if (!('revokeObjectURL' in URL)) { 35 return send("${response_queue_name}", "URL.revokeObjectURL is not exposed"); 36 } 37 try { 38 URL.revokeObjectURL("${blob_url}"); 39 } catch(e) { 40 return send("${response_queue_name}", e.toString()); 41 } 42 43 // Create, fetch, and revoke a separate blob URL to better ensure that the 44 // revoke call above has had time to take effect before we return. 45 const blob_1 = new Blob(["blob data"], {type : "text/plain"}); 46 const blob_url_1 = URL.createObjectURL(blob_1); 47 await fetch(blob_url_1).then(response => response.blob()); 48 URL.revokeObjectURL(blob_url_1); 49 50 return send("${response_queue_name}", "${js_finished}"); 51 } 52 await test(); 53 `; 54 55 const can_blob_url_be_fetched_js = (blob_url, response_queue_name) => ` 56 async function test() { 57 try { 58 const blob = await fetch("${blob_url}").then(response => response.blob()); 59 await blob.text(); 60 } catch(e) { 61 return send("${response_queue_name}", "${fetch_unsuccessful_response}"); 62 } 63 64 return send("${response_queue_name}", "${fetch_successful_response}"); 65 } 66 await test(); 67 `; 68 69 const same_site_origin = get_host_info().HTTPS_ORIGIN; 70 71 // Tests revoking blob URL for same and cross partition iframes. 72 promise_test(t => { 73 return new Promise(async (resolve, reject) => { 74 try { 75 // Creates blob URL. 76 const blob = new Blob(["blob data"], {type : "text/plain"}); 77 const blob_url = window.URL.createObjectURL(blob); 78 79 // Fetches blob URL to ensure that it's valid. 80 const blob_fetch = await fetch_contents_check(blob_url); 81 if (blob_fetch !== fetch_successful_response) { 82 reject("Blob URL invalid"); 83 } 84 85 // Creates same and cross partition iframes. 86 const response_queue_uuid = token(); 87 88 const [cross_site_iframe_uuid, same_site_iframe_uuid] = 89 await create_test_iframes(t, response_queue_uuid); 90 91 // Attempt to revoke blob URL in cross partition iframe. 92 await send(cross_site_iframe_uuid, can_blob_url_be_revoked_js(blob_url, response_queue_uuid)); 93 var response_1 = await receive(response_queue_uuid); 94 if (response_1 !== js_finished) { 95 reject(response_1); 96 } 97 response_1 = await fetch_contents_check(blob_url); 98 if (response_1 !== fetch_successful_response) { 99 reject(`Blob URL was revoked in not-same-top-level-site iframe: ${response_1}`); 100 } 101 102 // Attempt to revoke blob URL in same partition iframe. 103 await send(same_site_iframe_uuid, can_blob_url_be_revoked_js(blob_url, response_queue_uuid)); 104 var response_2 = await receive(response_queue_uuid); 105 if (response_2 !== js_finished) { 106 reject(response_2); 107 } 108 response_2 = await fetch_contents_check(blob_url); 109 if (response_2 !== fetch_unsuccessful_response) { 110 t.add_cleanup(() => window.URL.revokeObjectURL(blob_url)); 111 reject(`Blob URL wasn't revoked in same-top-level-site iframe: ${response_2}`); 112 } 113 114 resolve(); 115 } catch (e) { 116 reject(e); 117 } 118 }); 119 }, "Blob URL shouldn't be revocable from a cross-partition iframe"); 120 121 const newWorker = (origin) => { 122 const worker_token = token(); 123 const worker_url = origin + executor_worker_path + `&uuid=${worker_token}`; 124 const worker = new Worker(worker_url); 125 return worker_token; 126 } 127 128 const create_dedicated_worker_js = (origin, response_queue_uuid) => ` 129 const importScript = ${importScript}; 130 await importScript("/html/cross-origin-embedder-policy/credentialless" + 131 "/resources/common.js"); 132 await importScript("/html/anonymous-iframe/resources/common.js"); 133 await importScript("/common/utils.js"); 134 135 // dispatcher.js has already been loaded by the popup this is running in. 136 const newWorker = ${newWorker}; 137 await send("${response_queue_uuid}", newWorker("${origin}")); 138 `; 139 140 // Tests revoking blob URL from same and cross partition dedicated worker. 141 promise_test(t => { 142 return new Promise(async (resolve, reject) => { 143 try { 144 const response_queue_uuid = token(); 145 146 const [cross_site_iframe_uuid, same_site_iframe_uuid] = 147 await create_test_iframes(t, response_queue_uuid); 148 149 await send(cross_site_iframe_uuid, create_dedicated_worker_js(same_site_origin, response_queue_uuid)); 150 const worker_1_uuid = await receive(response_queue_uuid); 151 152 await send(same_site_iframe_uuid, create_dedicated_worker_js(same_site_origin, response_queue_uuid)); 153 const worker_2_uuid = await receive(response_queue_uuid); 154 155 const blob = new Blob(["blob data"], {type : "text/plain"}); 156 const blob_url = window.URL.createObjectURL(blob); 157 158 await send(worker_1_uuid, can_blob_url_be_revoked_js(blob_url, response_queue_uuid)); 159 var response_1 = await receive(response_queue_uuid); 160 if (response_1 !== js_finished) { 161 reject(response_1); 162 } 163 response_1 = await fetch_contents_check(blob_url); 164 if (response_1 !== fetch_successful_response) { 165 reject(`Blob URL was revoked in not-same-top-level-site dedicated worker: ${response_1}`); 166 } 167 168 await send(worker_2_uuid, can_blob_url_be_revoked_js(blob_url, response_queue_uuid)); 169 var response_2 = await receive(response_queue_uuid); 170 if (response_2 !== js_finished) { 171 reject(response_2); 172 } 173 response_2 = await fetch_contents_check(blob_url); 174 if (response_2 !== fetch_unsuccessful_response) { 175 t.add_cleanup(() => window.URL.revokeObjectURL(blob_url)); 176 reject(`Blob URL wasn't revoked in same-top-level-site dedicated worker: ${response_2}`); 177 } 178 179 resolve(); 180 } catch (e) { 181 reject(e); 182 } 183 }); 184 }, "Blob URL shouldn't be revocable from a cross-partition dedicated worker"); 185 186 const newSharedWorker = (origin) => { 187 const worker_token = token(); 188 const worker_url = origin + executor_worker_path + `&uuid=${worker_token}`; 189 const worker = new SharedWorker(worker_url, worker_token); 190 return worker_token; 191 } 192 193 const create_shared_worker_js = (origin, response_queue_uuid) => ` 194 const importScript = ${importScript}; 195 await importScript("/html/cross-origin-embedder-policy/credentialless" + 196 "/resources/common.js"); 197 await importScript("/html/anonymous-iframe/resources/common.js"); 198 await importScript("/common/utils.js"); 199 200 // dispatcher.js has already been loaded by the popup this is running in. 201 const newSharedWorker = ${newSharedWorker}; 202 await send("${response_queue_uuid}", newSharedWorker("${origin}")); 203 `; 204 205 // Tests revoking blob URL from same and cross partition shared worker. 206 promise_test(t => { 207 return new Promise(async (resolve, reject) => { 208 try { 209 const response_queue_uuid = token(); 210 211 const [cross_site_iframe_uuid, same_site_iframe_uuid] = 212 await create_test_iframes(t, response_queue_uuid); 213 214 // Create a shared worker in the cross-top-level-site iframe. 215 await send(cross_site_iframe_uuid, create_shared_worker_js(same_site_origin, response_queue_uuid)); 216 const worker_1_uuid = await receive(response_queue_uuid); 217 218 // Create a shared worker in the same-top-level-site iframe. 219 await send(same_site_iframe_uuid, create_shared_worker_js(same_site_origin, response_queue_uuid)); 220 const worker_2_uuid = await receive(response_queue_uuid); 221 222 const blob = new Blob(["blob data"], {type : "text/plain"}); 223 const blob_url = window.URL.createObjectURL(blob); 224 225 await send(worker_1_uuid, can_blob_url_be_revoked_js(blob_url, response_queue_uuid)); 226 var response_1 = await receive(response_queue_uuid); 227 if (response_1 !== js_finished) { 228 reject(response_1); 229 } 230 response_1 = await fetch_contents_check(blob_url); 231 if (response_1 !== fetch_successful_response) { 232 reject(`Blob URL was revoked in not-same-top-level-site shared worker: ${response_1}`); 233 } 234 235 await send(worker_2_uuid, can_blob_url_be_revoked_js(blob_url, response_queue_uuid)); 236 var response_2 = await receive(response_queue_uuid); 237 if (response_2 !== js_finished) { 238 reject(response_2); 239 } 240 response_2 = await fetch_contents_check(blob_url); 241 if (response_2 !== fetch_unsuccessful_response) { 242 t.add_cleanup(() => window.URL.revokeObjectURL(blob_url)); 243 reject(`Blob URL wasn't revoked in same-top-level-site shared worker: ${response_2}`); 244 } 245 246 resolve(); 247 } catch (e) { 248 reject(e); 249 } 250 }); 251 }, "Blob URL shouldn't be revocable from a cross-partition shared worker"); 252 253 const newServiceWorker = async (origin) => { 254 const worker_token = token(); 255 const worker_url = origin + executor_service_worker_path + 256 `&uuid=${worker_token}`; 257 const worker_url_path = executor_service_worker_path.substring(0, 258 executor_service_worker_path.lastIndexOf('/')); 259 const scope = worker_url_path + "/not-used/"; 260 const reg = await navigator.serviceWorker.register(worker_url, 261 {'scope': scope}); 262 return worker_token; 263 } 264 265 const create_service_worker_js = (origin, response_queue_uuid) => ` 266 const importScript = ${importScript}; 267 await importScript("/html/cross-origin-embedder-policy/credentialless" + 268 "/resources/common.js"); 269 await importScript("/html/anonymous-iframe/resources/common.js"); 270 await importScript("/common/utils.js"); 271 272 // dispatcher.js has already been loaded by the popup this is running in. 273 const newServiceWorker = ${newServiceWorker}; 274 await send("${response_queue_uuid}", await newServiceWorker("${origin}")); 275 `; 276 277 // Tests revoking blob URL from a service worker. 278 promise_test(t => { 279 return new Promise(async (resolve, reject) => { 280 try { 281 const response_queue_uuid = token(); 282 283 const [cross_site_iframe_uuid, same_site_iframe_uuid] = 284 await create_test_iframes(t, response_queue_uuid); 285 286 // Create a service worker in either iframe. 287 await send(cross_site_iframe_uuid, create_service_worker_js(same_site_origin, response_queue_uuid)); 288 var worker_1_uuid = await receive(response_queue_uuid); 289 t.add_cleanup(() => 290 send(worker_1_uuid, "self.registration.unregister();")); 291 292 const blob = new Blob(["blob data"], {type : "text/plain"}); 293 const blob_url = window.URL.createObjectURL(blob); 294 t.add_cleanup(() => window.URL.revokeObjectURL(blob_url)); 295 296 await send(worker_1_uuid, 297 can_blob_url_be_revoked_js(blob_url, response_queue_uuid)); 298 const response = await receive(response_queue_uuid); 299 if (response !== "URL.revokeObjectURL is not exposed") { 300 reject(`URL.revokeObjectURL is exposed in a Service Worker context: ${response}`); 301 } 302 resolve(); 303 } catch (e) { 304 reject(e); 305 } 306 }); 307 }, "Blob URL shouldn't be revocable from a service worker"); 308 309 // Tests fetching blob URL for same and cross partition iframes. 310 promise_test(t => { 311 return new Promise(async (resolve, reject) => { 312 try { 313 // Creates blob URL. 314 const blob = new Blob(["blob data"], {type : "text/plain"}); 315 const blob_url = window.URL.createObjectURL(blob); 316 t.add_cleanup(() => window.URL.revokeObjectURL(blob_url)); 317 318 // Fetches blob URL to ensure that it's valid. 319 const blob_fetch = await fetch_contents_check(blob_url); 320 if (blob_fetch !== fetch_successful_response) { 321 reject("Blob URL invalid"); 322 } 323 324 // Creates same and cross partition iframes. 325 const response_queue_uuid = token(); 326 327 const [cross_site_iframe_uuid, same_site_iframe_uuid] = 328 await create_test_iframes(t, response_queue_uuid); 329 330 // Attempt to fetch blob URL in cross partition iframe. 331 await send(cross_site_iframe_uuid, can_blob_url_be_fetched_js(blob_url, response_queue_uuid)); 332 var response_1 = await receive(response_queue_uuid); 333 if (response_1 !== fetch_unsuccessful_response) { 334 reject(`Blob URL was fetched in not-same-top-level-site iframe: ${response_1}`); 335 } 336 337 // Attempt to fetch blob URL in same partition iframe. 338 await send(same_site_iframe_uuid, can_blob_url_be_fetched_js(blob_url, response_queue_uuid)); 339 var response_2 = await receive(response_queue_uuid); 340 if (response_2 !== fetch_successful_response) { 341 reject(`Blob URL wasn't fetched in same-top-level-site iframe: ${response_2}`); 342 } 343 344 resolve(); 345 } catch (e) { 346 reject(e); 347 } 348 }); 349 }, "Blob URL shouldn't be fetched from a cross-partition iframe"); 350 351 // Tests fetching blob URL from same and cross partition dedicated worker. 352 promise_test(t => { 353 return new Promise(async (resolve, reject) => { 354 try { 355 const response_queue_uuid = token(); 356 357 // Creates same and cross partition iframes. 358 const [cross_site_iframe_uuid, same_site_iframe_uuid] = 359 await create_test_iframes(t, response_queue_uuid); 360 361 // Creates a dedicated worker in the cross-top-level-site iframe. 362 await send(cross_site_iframe_uuid, create_dedicated_worker_js(same_site_origin, response_queue_uuid)); 363 const worker_1_uuid = await receive(response_queue_uuid); 364 365 // Creates a dedicated worker in the same-top-level-site iframe. 366 await send(same_site_iframe_uuid, create_dedicated_worker_js(same_site_origin, response_queue_uuid)); 367 const worker_2_uuid = await receive(response_queue_uuid); 368 369 const blob = new Blob(["blob data"], {type : "text/plain"}); 370 const blob_url = window.URL.createObjectURL(blob); 371 t.add_cleanup(() => window.URL.revokeObjectURL(blob_url)); 372 373 // Attempts to fetch in the cross-top-level-site dedicated worker. 374 await send(worker_1_uuid, can_blob_url_be_fetched_js(blob_url, response_queue_uuid)); 375 var response_1 = await receive(response_queue_uuid); 376 if (response_1 !== fetch_unsuccessful_response) { 377 reject(`Blob URL was fetched in not-same-top-level-site dedicated worker: ${response_1}`); 378 } 379 380 // Attempts to fetch in the same-top-level-site dedicated worker. 381 await send(worker_2_uuid, can_blob_url_be_fetched_js(blob_url, response_queue_uuid)); 382 var response_2 = await receive(response_queue_uuid); 383 if (response_2 !== fetch_successful_response) { 384 reject(`Blob URL wasn't fetched in same-top-level-site dedicated worker: ${response_2}`); 385 } 386 387 resolve(); 388 } catch (e) { 389 reject(e); 390 } 391 }); 392 }, "Blob URL shouldn't be fetched from a cross-partition dedicated worker"); 393 394 // Tests fetching blob URL from same and cross partition shared worker. 395 promise_test(t => { 396 return new Promise(async (resolve, reject) => { 397 try { 398 const response_queue_uuid = token(); 399 400 const [cross_site_iframe_uuid, same_site_iframe_uuid] = 401 await create_test_iframes(t, response_queue_uuid); 402 403 // Create a shared worker in the cross-top-level-site iframe. 404 await send(cross_site_iframe_uuid, create_shared_worker_js(same_site_origin, response_queue_uuid)); 405 const worker_1_uuid = await receive(response_queue_uuid); 406 407 // Create a shared worker in the same-top-level-site iframe. 408 await send(same_site_iframe_uuid, create_shared_worker_js(same_site_origin, response_queue_uuid)); 409 const worker_2_uuid = await receive(response_queue_uuid); 410 411 const blob = new Blob(["blob data"], {type : "text/plain"}); 412 const blob_url = window.URL.createObjectURL(blob); 413 t.add_cleanup(() => window.URL.revokeObjectURL(blob_url)); 414 415 // Attempts to fetch in the cross-top-level-site shared worker. 416 await send(worker_1_uuid, can_blob_url_be_fetched_js(blob_url, response_queue_uuid)); 417 var response_1 = await receive(response_queue_uuid); 418 if (response_1 !== fetch_unsuccessful_response) { 419 reject(`Blob URL was fetched in not-same-top-level-site shared worker: ${response_1}`); 420 } 421 422 // Attempts to fetch in the same-top-level-site shared worker. 423 await send(worker_2_uuid, can_blob_url_be_fetched_js(blob_url, response_queue_uuid)); 424 var response_2 = await receive(response_queue_uuid); 425 if (response_2 !== fetch_successful_response) { 426 reject(`Blob URL wasn't fetched in same-top-level-site shared worker: ${response_2}`); 427 } 428 429 resolve(); 430 } catch (e) { 431 reject(e); 432 } 433 }); 434 }, "Blob URL shouldn't be fetched from a cross-partition shared worker"); 435 436 // Tests fetching blob URL from a cross partition service worker. 437 promise_test(t => { 438 return new Promise(async (resolve, reject) => { 439 try { 440 const response_queue_uuid = token(); 441 442 const [cross_site_iframe_uuid, same_site_iframe_uuid] = 443 await create_test_iframes(t, response_queue_uuid); 444 445 const blob = new Blob(["blob data"], {type : "text/plain"}); 446 const blob_url = window.URL.createObjectURL(blob); 447 t.add_cleanup(() => window.URL.revokeObjectURL(blob_url)); 448 449 // Create a service worker in cross-top-level-site iframe. 450 await send(cross_site_iframe_uuid, create_service_worker_js(same_site_origin, response_queue_uuid)); 451 var worker_1_uuid = await receive(response_queue_uuid); 452 t.add_cleanup(() => 453 send(worker_1_uuid, "self.registration.unregister();")); 454 455 await send(worker_1_uuid, 456 can_blob_url_be_fetched_js(blob_url, response_queue_uuid)); 457 const response_1 = await receive(response_queue_uuid); 458 if (response_1 !== fetch_unsuccessful_response) { 459 reject(`Blob URL was fetched in not-same-top-level-site service worker: ${response_1}`); 460 } 461 462 // Create a service worker in same-top-level-site iframe. 463 await send(same_site_iframe_uuid, create_service_worker_js(same_site_origin, response_queue_uuid)); 464 var worker_2_uuid = await receive(response_queue_uuid); 465 t.add_cleanup(() => 466 send(worker_2_uuid, "self.registration.unregister();")); 467 468 await send(worker_2_uuid, 469 can_blob_url_be_fetched_js(blob_url, response_queue_uuid)); 470 const response_2 = await receive(response_queue_uuid); 471 if (response_2 !== fetch_successful_response) { 472 reject(`Blob URL wasn't fetched in same-top-level-site service worker: ${response_2}`); 473 } 474 resolve(); 475 } catch (e) { 476 reject(e); 477 } 478 }); 479 }, "Blob URL shouldn't be fetched from a cross-partition service worker"); 480 481 </script> 482 </body>