| <!DOCTYPE html> |
| <meta charset=utf-8> |
| <meta name="timeout" content="long"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/common/get-host-info.sub.js"></script> |
| <script src="/common/utils.js"></script> |
| <script src="/common/dispatcher/dispatcher.js"></script> |
| <!-- Pull in executor_path needed by newPopup / newIframe --> |
| <script src="/html/cross-origin-embedder-policy/credentialless/resources/common.js"></script> |
| <!-- Pull in importScript / newPopup / newIframe --> |
| <script src="/html/anonymous-iframe/resources/common.js"></script> |
| <body> |
| <script> |
| |
| const navigation_handle_null = "Navigation handle returns null"; |
| const navigation_handle_not_null = "Navigation handle returns not null"; |
| const opener_null_response = "Window.opener is null"; |
| const opener_not_null_response = "Window.opener isn't null"; |
| |
| const does_blob_url_open_return_handle = (blob_url, response_queue_name) => ` |
| async function test() { |
| const handle = window.open("${blob_url}") |
| if (!handle) { |
| return send("${response_queue_name}", "${navigation_handle_null}"); |
| } |
| |
| return send("${response_queue_name}", "${navigation_handle_not_null}"); |
| } |
| await test(); |
| `; |
| |
| const add_iframe_js = (iframe_origin, response_queue_uuid) => ` |
| const importScript = ${importScript}; |
| await importScript("/html/cross-origin-embedder-policy/credentialless" + |
| "/resources/common.js"); |
| await importScript("/html/anonymous-iframe/resources/common.js"); |
| await importScript("/common/utils.js"); |
| |
| // dispatcher.js has already been loaded by the popup this is running in. |
| await send("${response_queue_uuid}", newIframe("${iframe_origin}")); |
| `; |
| |
| const same_site_origin = get_host_info().HTTPS_ORIGIN; |
| const cross_site_origin = get_host_info().HTTPS_NOTSAMESITE_ORIGIN; |
| |
| async function create_test_iframes(t, response_queue_uuid) { |
| assert_equals("https://" + window.location.host, same_site_origin, |
| "this test assumes that the page's window.location.host corresponds to " + |
| "get_host_info().HTTPS_ORIGIN"); |
| |
| // Create a same-origin iframe in a cross-site popup. |
| const not_same_site_popup_uuid = newPopup(t, cross_site_origin); |
| await send(not_same_site_popup_uuid, |
| add_iframe_js(same_site_origin, response_queue_uuid)); |
| const cross_site_iframe_uuid = await receive(response_queue_uuid); |
| |
| // Create a same-origin iframe in a same-site popup. |
| const same_origin_popup_uuid = newPopup(t, same_site_origin); |
| await send(same_origin_popup_uuid, |
| add_iframe_js(same_site_origin, response_queue_uuid)); |
| const same_site_iframe_uuid = await receive(response_queue_uuid); |
| |
| return [cross_site_iframe_uuid, same_site_iframe_uuid]; |
| } |
| |
| const opener_check_frame_html = (noopener_response_queue) => ` |
| <!doctype html> |
| <!-- dispatcher.js requires the baseURI to be set in order to compute |
| the server path correctly in the blob URL page. --> |
| <base href="${window.location.href}"> |
| <script src="/html/cross-origin-embedder-policy/credentialless/resources/common.js"><\/script> |
| <script src="/html/anonymous-iframe/resources/common.js"><\/script> |
| <script src="/common/utils.js"><\/script> |
| <script src="/common/dispatcher/dispatcher.js"><\/script> |
| <script> |
| if (window.opener === null) { |
| send("${noopener_response_queue}", "${opener_null_response}") |
| } else { |
| send("${noopener_response_queue}", "${opener_not_null_response}") |
| } |
| <\/script> |
| `; |
| |
| // Tests blob URL window.open for same and cross partition iframes. |
| promise_test(t => { |
| return new Promise(async (resolve, reject) => { |
| try { |
| // Creates same and cross partition iframes. |
| const response_queue_uuid = token(); |
| const noopener_response_queue = token(); |
| |
| const [cross_site_iframe_uuid, same_site_iframe_uuid] = |
| await create_test_iframes(t, response_queue_uuid); |
| |
| const blob = new Blob([opener_check_frame_html(noopener_response_queue)], {type : "text/html"}); |
| const blob_url = URL.createObjectURL(blob); |
| |
| // Attempt to open blob URL in cross partition iframe. |
| await send(cross_site_iframe_uuid, does_blob_url_open_return_handle(blob_url, response_queue_uuid)); |
| const response_1 = await receive(response_queue_uuid); |
| if (response_1 !== navigation_handle_null) { |
| reject(`Blob URL handle wasn't null in not-same-top-level-site iframe: ${response_1}`); |
| } |
| const noopener_response_1 = await receive(noopener_response_queue); |
| if (noopener_response_1 !== opener_null_response) { |
| reject(`Blob URL page opener wasn't null in not-same-top-level-site iframe.`); |
| } |
| |
| // Attempt to open blob URL in same partition iframe. |
| await send(same_site_iframe_uuid, does_blob_url_open_return_handle(blob_url, response_queue_uuid)); |
| const response_2 = await receive(response_queue_uuid); |
| if (response_2 !== navigation_handle_not_null) { |
| reject(`Blob URL wasn't opened in same-top-level-site iframe: ${response_2}`); |
| } |
| const noopener_response_2 = await receive(noopener_response_queue); |
| if (noopener_response_2 !== opener_not_null_response) { |
| reject(`Blob URL page opener was null in same-top-level-site iframe`); |
| } |
| resolve(); |
| } catch (e) { |
| reject(e); |
| } |
| }); |
| }, "Blob URL window.open should enforce noopener for a cross-top-level-site navigation"); |
| |
| const blob_url_iframe_html = (response_queue_uuid, message) => ` |
| <!doctype html> |
| <!-- dispatcher.js requires the baseURI to be set in order to compute |
| the server path correctly in the blob URL page. --> |
| <base href="${window.location.href}"> |
| <script src="/html/cross-origin-embedder-policy/credentialless/resources/common.js"><\/script> |
| <script src="/html/anonymous-iframe/resources/common.js"><\/script> |
| <script src="/common/utils.js"><\/script> |
| <script src="/common/dispatcher/dispatcher.js"><\/script> |
| <script> |
| send("${response_queue_uuid}", "${message}"); |
| <\/script> |
| `; |
| |
| const create_iframe_with_blob_url = (blob_url, response_queue_uuid) => ` |
| const iframe = document.createElement('iframe'); |
| iframe.src = "${blob_url}"; |
| iframe.onload = () => { |
| const same_site_message = "same_partition_loaded"; |
| const blob_url_iframe_html = ${blob_url_iframe_html}; |
| const same_top_level_site_blob = new Blob([blob_url_iframe_html("${response_queue_uuid}", same_site_message)], {type : "text/html"}); |
| const same_top_level_site_blob_url = URL.createObjectURL(same_top_level_site_blob); |
| const iframe2 = document.createElement('iframe'); |
| iframe2.src = same_top_level_site_blob_url; |
| document.body.appendChild(iframe2); |
| }; |
| document.body.appendChild(iframe); |
| `; |
| |
| // Tests blob URL subframe navigations for same and cross partition iframes. |
| promise_test(t => { |
| return new Promise(async (resolve, reject) => { |
| try { |
| // Creates same and cross partition iframes. |
| const response_queue_uuid = token(); |
| const cross_site_message = "cross_partition_loaded"; |
| |
| const [cross_site_iframe_uuid, same_site_iframe_uuid] = |
| await create_test_iframes(t, response_queue_uuid); |
| |
| // Create blob URL for the cross-site test. |
| const cross_site_blob = new Blob([blob_url_iframe_html(response_queue_uuid, cross_site_message)], {type: "text/html"}); |
| const cross_site_blob_url = URL.createObjectURL(cross_site_blob); |
| |
| // Attempt to open blob URL in cross partition iframe. |
| await send(cross_site_iframe_uuid, create_iframe_with_blob_url(cross_site_blob_url, response_queue_uuid)); |
| |
| const response = await receive(response_queue_uuid); |
| if (response === cross_site_message) { |
| reject(`Blob URL subframe navigation succeeded in not-same-top-level-site iframe.`); |
| } |
| resolve(); |
| } catch (e) { |
| reject(e); |
| } |
| }); |
| }, "Blob URL should partition subframe navigation."); |
| |
| const open_blob_url_window_via_a_click = (blob_url) => ` |
| const link = document.createElement("a"); |
| link.href = "${blob_url}"; |
| link.target = "_blank"; |
| link.rel = "opener"; |
| document.body.appendChild(link); |
| link.click(); |
| `; |
| |
| // Tests blob URL `<a target="_blank" rel="opener">` click for same and cross partition iframes. |
| promise_test(t => { |
| return new Promise(async (resolve, reject) => { |
| try { |
| // Creates same and cross partition iframes. |
| const noopener_response_queue = token(); |
| |
| const [cross_site_iframe_uuid, same_site_iframe_uuid] = await create_test_iframes(t, token()); |
| |
| const blob = new Blob([opener_check_frame_html(noopener_response_queue)], {type : "text/html"}); |
| const blob_url = URL.createObjectURL(blob); |
| |
| // Attempt to click blob URL in cross partition iframe. |
| await send(cross_site_iframe_uuid, open_blob_url_window_via_a_click(blob_url)); |
| const noopener_response_1 = await receive(noopener_response_queue); |
| if (noopener_response_1 !== opener_null_response) { |
| reject(`Blob URL page opener wasn't null in not-same-top-level-site iframe.`); |
| } |
| |
| // Attempt to click blob URL in same partition iframe. |
| await send(same_site_iframe_uuid, open_blob_url_window_via_a_click(blob_url)); |
| const noopener_response_2 = await receive(noopener_response_queue); |
| if (noopener_response_2 !== opener_not_null_response) { |
| reject(`Blob URL page opener was null in same-top-level-site iframe`); |
| } |
| resolve(); |
| } catch (e) { |
| reject(e); |
| } |
| }); |
| }, "Blob URL link click should enforce noopener for a cross-top-level-site navigation"); |
| |
| const open_blob_url_window_via_area_click = (blob_url) => ` |
| const canvas = document.createElement("canvas"); |
| canvas.height = 1; |
| canvas.width = 1; |
| const dataURL = canvas.toDataURL(); |
| |
| const image = document.createElement("img"); |
| image.src = dataURL; |
| document.body.appendChild(image); |
| |
| const map = document.createElement("map"); |
| map.name = "map"; |
| image.useMap = "#map"; |
| document.body.appendChild(map); |
| |
| const area = document.createElement("area"); |
| area.shape = "rect"; |
| area.coords = "0,0,1,1"; |
| area.href = "${blob_url}"; |
| area.target = "_blank"; |
| area.rel = "opener"; |
| map.appendChild(area); |
| area.click(); |
| `; |
| |
| // Tests blob URL `<area target="_blank" rel="opener">` click for same and cross partition iframes. |
| promise_test(t => { |
| return new Promise(async (resolve, reject) => { |
| try { |
| // Creates same and cross partition iframes. |
| const noopener_response_queue = token(); |
| |
| const [cross_site_iframe_uuid, same_site_iframe_uuid] = await create_test_iframes(t, token()); |
| |
| const blob = new Blob([opener_check_frame_html(noopener_response_queue)], {type : "text/html"}); |
| const blob_url = URL.createObjectURL(blob); |
| |
| // Attempt to click blob URL in cross partition iframe. |
| await send(cross_site_iframe_uuid, open_blob_url_window_via_area_click(blob_url)); |
| const noopener_response_1 = await receive(noopener_response_queue); |
| if (noopener_response_1 !== opener_null_response) { |
| reject(`Blob URL page opener wasn't null in not-same-top-level-site iframe.`); |
| } |
| |
| // Attempt to click blob URL in same partition iframe. |
| await send(same_site_iframe_uuid, open_blob_url_window_via_area_click(blob_url)); |
| const noopener_response_2 = await receive(noopener_response_queue); |
| if (noopener_response_2 !== opener_not_null_response) { |
| reject(`Blob URL page opener was null in same-top-level-site iframe`); |
| } |
| resolve(); |
| } catch (e) { |
| reject(e); |
| } |
| }); |
| }, "Blob URL area element click should enforce noopener for a cross-top-level-site navigation"); |
| |
| </script> |
| </body> |