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;