Skip to content

Commit

Permalink
[Blob URL] Add tests for enforcing noopener on a / area clicks
Browse files Browse the repository at this point in the history
For cross-top-level-site navigations via clicking "a" and "area"
links that use `target="_blank" rel="opener"`, we should enforce
noopener as part of Blob URL partitioning.

"window.opener" can also get set on form submissions, but from testing
in Chrome, Firefox, and Safari, we can't successfully perform a form
submission to a Blob URL (if the method is GET, it seems that the
appended '?' breaks the Blob URL lookup, and POST doesn't work either
because it is an unsupported method for Blob URLs).

For more information, see:
https://docs.google.com/document/d/1Xk73RLlLgfVw1p2tYBGqlP7ROQxaMh6kxfusSMm9exM/edit?usp=sharing

Bug: 361751872
Change-Id: I723a0cf0df73ebb2f81f3fced496248d5c7a9798
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5979376
Reviewed-by: Steven Bingler <[email protected]>
Commit-Queue: Andrew Williams <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1377218}
  • Loading branch information
recvfrom authored and chromium-wpt-export-bot committed Nov 2, 2024
1 parent b4899d9 commit d7f9bb1
Showing 1 changed file with 120 additions and 22 deletions.
142 changes: 120 additions & 22 deletions FileAPI/BlobURL/cross-partition-navigation.tentative.https.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,25 @@
return [cross_site_iframe_uuid, same_site_iframe_uuid];
}

// Tests navigating blob URL for same and cross partition iframes.
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 {
Expand All @@ -75,25 +93,7 @@
const [cross_site_iframe_uuid, same_site_iframe_uuid] =
await create_test_iframes(t, response_queue_uuid);

const frame_html = `
<!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>
`;

const blob = new Blob([frame_html], {type : "text/html"});
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.
Expand Down Expand Up @@ -122,7 +122,105 @@
reject(e);
}
});
}, "Blob URL navigation should enforce noopener for a cross-top-level-site navigation");
}, "Blob URL window.open should enforce noopener for a cross-top-level-site 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>
</body>

0 comments on commit d7f9bb1

Please sign in to comment.