AnonymousIframe: Check FencedFrameInteraction (2/3) (#32533)
With the following nested tree:
1. A popup enforcing COEP.
2. An AnonymousFrame, omitting COEP.
3. A FencedFrame, enforcing/omitting COEP/CORP
Check whether (3) loads depending on its origin and headers.
Bug: 1287458
Change-Id: If71284825ae6eeb86dec6413eff6bc50bdd9963d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3392375
Reviewed-by: Camille Lamy <clamy@chromium.org>
Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org>
Cr-Commit-Position: refs/heads/main@{#963501}
Co-authored-by: Arthur Sonzogni <arthursonzogni@chromium.org>
diff --git a/html/cross-origin-embedder-policy/anonymous-iframe/fenced-frame-coep.tentative.https.window.js b/html/cross-origin-embedder-policy/anonymous-iframe/fenced-frame-coep.tentative.https.window.js
new file mode 100644
index 0000000..fd91c95
--- /dev/null
+++ b/html/cross-origin-embedder-policy/anonymous-iframe/fenced-frame-coep.tentative.https.window.js
@@ -0,0 +1,102 @@
+// META: script=/common/get-host-info.sub.js
+// META: script=/common/utils.js
+// META: script=/common/dispatcher/dispatcher.js
+// META: script=../credentialless/resources/common.js
+// META: script=./resources/common.js
+// META: timeout=long
+
+setup(() => {
+ assert_implements(window.HTMLFencedFrameElement,
+ "HTMLFencedFrameElement is not supported.");
+})
+
+const import_common = `
+ const importScript = ${importScript};
+ await importScript("/common/utils.js");
+ await importScript("/html/cross-origin-embedder-policy/credentialless" +
+ "/resources/common.js");
+ await importScript("/html/cross-origin-embedder-policy/anonymous-iframe" +
+ "/resources/common.js");
+`;
+
+// 3 actors:
+// - A popup, enforcing COEP.
+// - An AnonymousFrame, omitting COEP, inside the popup.
+// - A FencedFrame, inside the anonymous frame.
+//
+// This answers the question: Does the FencedFrame require COEP/CORP?
+promise_test_parallel(async test => {
+ const same_origin = get_host_info().HTTPS_ORIGIN;
+ const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN;
+ const msg_queue = token();
+
+ // 1. Create a popup, enforcing COEP:
+ const popup = newPopup(same_origin, coep_require_corp);
+
+ // 2. Inside, create an AnonymousFrame.
+ send(popup, `
+ ${import_common}
+ const iframe_anonymous = newAnonymousIframe("${same_origin}");
+ send("${msg_queue}", iframe_anonymous);
+ `);
+ const iframe_anonymous = await receive(msg_queue);
+ send(iframe_anonymous, `
+ ${import_common}
+ send("${msg_queue}", "Script imported");
+ `);
+ assert_equals(await receive(msg_queue), "Script imported");
+
+ // 3. Inside, create a FencedFrame. Does it load?
+ // Several variations depending on its origin and headers.
+ const test_cases = [
+ {
+ description: "same-origin => blocked.",
+ origin: same_origin, headers: "",
+ expectation: "FencedFrame blocked",
+ }, {
+ description: "cross-origin => blocked.",
+ origin: cross_origin, headers: "",
+ expectation: "FencedFrame blocked",
+ }, {
+ description: "same-origin + coep => blocked.",
+ origin: same_origin, headers: coep_require_corp,
+ expectation: "FencedFrame blocked",
+ }, {
+ description: "cross-origin + coep => blocked.",
+ origin: cross_origin, headers: coep_require_corp,
+ expectation: "FencedFrame blocked",
+ }, {
+ description: "same-origin + coep + corp => allowed.",
+ origin: same_origin, headers: coep_require_corp + corp_cross_origin,
+ expectation: "FencedFrame loaded",
+ }, {
+ description: "cross-origin + coep + corp => allowed.",
+ origin: cross_origin, headers: coep_require_corp + corp_cross_origin,
+ expectation: "FencedFrame loaded",
+ },
+ ];
+
+ for(const test_case of test_cases) {
+ promise_test_parallel(async test => {
+ const msg_queue = token();
+ send(iframe_anonymous, `
+ const iframe_fenced = newFencedFrame("${test_case.origin}",
+ "${test_case.headers}");
+ send("${msg_queue}", iframe_fenced);
+ `);
+ const iframe_fenced = await receive(msg_queue);
+
+ // Test depends on what comes first, a reply from the FencedFrame or a
+ // timeout.
+ send(iframe_fenced, `
+ send("${msg_queue}", "FencedFrame loaded")
+ `);
+ test.step_timeout(() => {
+ send(msg_queue, "FencedFrame blocked")
+ }, 5000);
+
+ assert_equals(await receive(msg_queue), test_case.expectation);
+ }, test_case.description);
+ }
+
+}, "Check FencedFrame check adherence to COEP within an anonymous frame");
diff --git a/html/cross-origin-embedder-policy/anonymous-iframe/resources/common.js b/html/cross-origin-embedder-policy/anonymous-iframe/resources/common.js
index 1378f3e..25d2ac8 100644
--- a/html/cross-origin-embedder-policy/anonymous-iframe/resources/common.js
+++ b/html/cross-origin-embedder-policy/anonymous-iframe/resources/common.js
@@ -22,22 +22,25 @@
// Create a popup. The new document will execute any scripts sent toward the
// token it returns.
-const newPopup = (test, origin) => {
+const newPopup = (origin, opt_headers) => {
+ opt_headers ||= "";
const popup_token = token();
- const popup = window.open(origin + executor_path + `&uuid=${popup_token}`);
- test.add_cleanup(() => popup.close());
+ const popup = window.open(origin + executor_path + opt_headers +
+ `&uuid=${popup_token}`);
+ add_completion_callback(() => popup.close());
return popup_token;
}
// Create a fenced frame. The new document will execute any scripts sent
// toward the token it returns.
-const newFencedFrame = (child_origin) => {
+const newFencedFrame = (child_origin, opt_headers) => {
+ opt_headers ||= "";
const support_loading_mode_fenced_frame =
"|header(Supports-Loading-Mode,fenced-frame)";
const sub_document_token = token();
const fencedframe = document.createElement('fencedframe');
fencedframe.src = child_origin + executor_path +
- support_loading_mode_fenced_frame +
+ support_loading_mode_fenced_frame + opt_headers +
`&uuid=${sub_document_token}`;
document.body.appendChild(fencedframe);
return sub_document_token;