Skip to content

Commit

Permalink
Add WPT for COOP behavior in navigations to about:blank (#27548)
Browse files Browse the repository at this point in the history
This CL adds a WPT test that checks the interaction of COOP
same-origin-allow-popups with about:blank navigations.
As discussed in whatwg/html#5198.

Change-Id: Iabe461416c36468f73a41af0f69c46c545744e14
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2678150
Auto-Submit: Pâris Meuleman <pmeuleman@chromium.org>
Commit-Queue: Pâris Meuleman <pmeuleman@chromium.org>
Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#860665}

Co-authored-by: Pâris MEULEMAN <pmeuleman@chromium.org>
  • Loading branch information
chromium-wpt-export-bot and ParisMeuleman authored Mar 8, 2021
1 parent 2ed850a commit c4f759f
Show file tree
Hide file tree
Showing 3 changed files with 344 additions and 0 deletions.
176 changes: 176 additions & 0 deletions html/cross-origin-opener-policy/navigate-to-aboutblank.https.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
<title>
This tests the inheritance of COOP for navigations to about:blank.
</title>
<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="reporting/resources/dispatcher.js"></script>
<script src="reporting/resources/try-access.js"></script>


<p>Non-initial empty documents (about:blank) should inherit their
cross-origin-opener-policy from the navigation's initiator top level document,
if the initiator and its top level document are same-origin, or default
(unsafe-none) otherwise.
</p>

<ol>
<li>Create the opener popup with a given COOP <code>openerCOOP</code>.</li>
<li>Add iframe to the opener popup that is either same-origin or
cross-origin.
</li>
<li>Opener's iframe opens a new window, to a network document with <code>openeeCOOP</code>.</li>
<li>Opener's iframe navigates the openee popup to about:blank.</li>
</ol>

<script>
const directory = "/html/cross-origin-opener-policy";
const executor_path = directory + "/reporting/resources/executor.html?pipe=";
const same_origin = get_host_info().HTTPS_ORIGIN;
const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN;
const coop_same_origin_header =
'|header(Cross-Origin-Opener-Policy,same-origin)';
const coop_same_origin_allow_popups_header =
'|header(Cross-Origin-Opener-Policy,same-origin-allow-popups)';
const coop_unsafe_none_header =
'|header(Cross-Origin-Opener-Policy,unsafe-none)';

function navigateToAboutBlankTest(
opener_COOP_header,
iframe_origin,
openee_COOP_header,
openee_origin,
expect_openee_closed
){
return promise_test(async t => {
const this_window_token = token();
const opener_token = token();
const openee_token = token();
const iframe_token = token();

const opener_url = same_origin + executor_path + opener_COOP_header +
`&uuid=${opener_token}`;
const openee_url = openee_origin + executor_path + openee_COOP_header +
`&uuid=${openee_token}`;
const iframe_url = iframe_origin + executor_path + `&uuid=${iframe_token}`;

t.add_cleanup(() => {
send(openee_token, "window.close()");
send(opener_token, "window.close()");
});

// 1. Create the opener window.
let opener_window_proxy = window.open(opener_url, opener_token);

// 2. Create the iframe.
send(opener_token, `
iframe = document.createElement('iframe');
iframe.src = "${iframe_url}";
document.body.appendChild(iframe);
`);

// 3. The iframe opens its openee window.
send(iframe_token, `
window.openee = window.open(
'${openee_url.replace(/,/g, '\\,')}',
"${openee_token}"
);
`);

// 4. Ensure the popup is fully loaded.
send(openee_token, `send("${this_window_token}", "Ack");`);
assert_equals(await receive(this_window_token), "Ack");

// 5. The iframe navigates openee to about:blank.
send(iframe_token, `
window.openee_blank = window.open('about:blank', "${openee_token}");
(async function() {
const timeout = 2000;
const retry_delay = 100;
for(let i = 0; i * retry_delay < timeout; ++i) {
// A try-catch block is used, because of same-origin policy,
// preventing access to the document before committing about:blank.
try {
if (window.openee_blank.closed ||
window.openee_blank.document.location.href == "about:blank") {
send("${this_window_token}", "about:blank loaded");
return;
}
} catch(e) {}
await new Promise(resolve => setTimeout(resolve, retry_delay));
}
send("${this_window_token}", "about:blank not loaded");
})()
`);
assert_equals(await receive(this_window_token), "about:blank loaded");


// 6. Retrieve and check the results.
send(iframe_token, `
send("${this_window_token}", window.openee.closed);
`);
assert_equals(await receive(this_window_token), `${expect_openee_closed}`);
}, `Navigate to about:blank from iframe with opener.top \
COOP: ${opener_COOP_header}, iframe origin: ${iframe_origin}, \
openee COOP: ${openee_COOP_header}, openee origin: ${openee_origin}.`);
};

// iframe same-origin with its top-level embedder:
// initial empty document and about:blank navigations initiated from the
// same-origin iframe will inherit the COOP from the iframe's top-level embedder.

// Since all navigations of openee are within same-origin pages with the
// same COOP value, there are no browsing context group switches.
navigateToAboutBlankTest(
coop_same_origin_header,
same_origin,
coop_same_origin_header,
same_origin,
false
);

// Since all navigations of openee are within same-origin pages with the
// same COOP value, there are no browsing context group switches.
navigateToAboutBlankTest(
coop_same_origin_allow_popups_header,
same_origin,
coop_same_origin_allow_popups_header,
same_origin,
false
);

// The first openee navigation, from initial empty document to
// cross-origin will not switch the browsing context group, thanks to the
// same-origin-allow-popups behavior.
// The second openee navigation, to about:blank, will inherit from the
// iniatiator's, the iframe, top. Navigating from a COOP: unsafe-none page to
// a COOP: same-origin-allow-popups page causes a browsing context group
// switch.
navigateToAboutBlankTest(
coop_same_origin_allow_popups_header,
same_origin,
coop_unsafe_none_header,
cross_origin,
true
);

// iframe cross-origin with its top-level embedder:
// initial empty document and about:blank navigations initiated from the
// cross-origin iframe will default COOP to unsafe-none.

// The navigation from the initial empty document and the cross_origin url
// does not cause a browsing context group switch
// (both have COOP: unsafe-none).
// The navigation from the cross-origin url to about:blank does not cause a
// browsing context group swich, about:blank defaulted its COOP value to
// unsafe-none.
navigateToAboutBlankTest(
coop_same_origin_allow_popups_header,
cross_origin,
coop_unsafe_none_header,
cross_origin,
false
);
</script>
166 changes: 166 additions & 0 deletions html/cross-origin-opener-policy/navigate-top-to-aboutblank.https.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
<title>
This tests the inheritance of COOP for navigations of the top document to about:blank.
</title>
<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="reporting/resources/dispatcher.js"></script>
<script src="reporting/resources/try-access.js"></script>


<p>Non-initial empty documents (about:blank) should inherit their
cross-origin-opener-policy from the navigation's initiator top level document,
if the initiator and its top level document are same-origin, or default (to
unsafe-none) otherwise.
</p>

<ol>
<li>Create the opener popup with a given COOP <code>openerCOOP</code>.</li>
<li>Add iframe to the opener popup that is either same-origin or
cross-origin.
</li>
<li>Opener opens a new window, to a network document with the same origin and
COOP value as opener.</li>
<li>Opener's iframe navigates its parent frame (opener) to about:blank.</li>
<li>Verify the openee still has access to its opener.</li>
</ol>

<script>
const directory = "/html/cross-origin-opener-policy";
const executor_path = directory + "/reporting/resources/executor.html?pipe=";
const same_origin = get_host_info().HTTPS_ORIGIN;
const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN;
const coop_same_origin_header =
'|header(Cross-Origin-Opener-Policy,same-origin)';
const coop_same_origin_allow_popups_header =
'|header(Cross-Origin-Opener-Policy,same-origin-allow-popups)';
const coop_unsafe_none_header =
'|header(Cross-Origin-Opener-Policy,unsafe-none)';

function navigateToAboutBlankTest(
COOP_header,
iframe_origin,
expect_opener_closed
){
return promise_test(async t => {
const this_window_token = token();
const opener_token = token();
const openee_token = token();
const iframe_token = token();

const opener_url = same_origin + executor_path + COOP_header +
`&uuid=${opener_token}`;
const openee_url = same_origin + executor_path + COOP_header +
`&uuid=${openee_token}`;
const iframe_url = iframe_origin + executor_path + `&uuid=${iframe_token}`;

t.add_cleanup(() => {
send(opener_token, "window.close()");
send(openee_token, "window.close()");
});

// 1. Create the opener window.
let opener_window_proxy = window.open(opener_url, opener_token);

// 2. Create the iframe.
// The allow-top-navigation sandbox flags disables the intervention
// requiring a user gesture to navigate top.
send(opener_token, `
iframe = document.createElement('iframe');
iframe.src = "${iframe_url}";
iframe.sandbox = "allow-top-navigation allow-scripts";
document.body.appendChild(iframe);
`);

// 3. The opener opens openee window.
send(opener_token, `
window.openee = window.open(
'${openee_url.replace(/,/g, '\\,')}'
);
`);

// 4. Ensure the popup is fully loaded.
send(openee_token, `send("${this_window_token}", "Ack");`);
assert_equals(await receive(this_window_token), "Ack");

// 5. The iframe navigates its top-level document to about:blank.
send(iframe_token, `
top.location.href = "about:blank";
`);

// 6. Ensure opener is fully loaded and then retrieve the results.
send(openee_token, `
(async function() {
const timeout = 2000;
const retry_delay = 100;
for(let i = 0; i * retry_delay < timeout; ++i) {
// A try-catch block is used, because of same-origin policy,
// which may prevent the access to the opener if its origin changed,
// after a navigation to about:blank from the cross origin iframe.
try {
if (
window.opener === null ||
window.opener.closed ||
window.opener.document.location.href == "about:blank") {
send("${this_window_token}", "about:blank loaded");
return;
}
} catch(e) {
// The exception is thrown when about:blank is loaded and is
// cross-origin with openee.
send("${this_window_token}", "about:blank loaded");
return;
}
await new Promise(resolve => setTimeout(resolve, retry_delay));
}
send("${this_window_token}", "about:blank NOT loaded");
})()
`);
assert_equals(await receive(this_window_token), "about:blank loaded");

// 7. Retrieve and check the results.
send(openee_token, `
send(
"${this_window_token}",
window.opener === null || window.opener.closed);
`);

assert_equals(await receive(this_window_token), `${expect_opener_closed}`);
}, `Navigate top to about:blank from iframe with \
opener COOP: ${COOP_header}, iframe origin: ${iframe_origin}`);
};

// iframe same-origin with its top-level embedder:
// initial empty document and about:blank navigations initiated from the
// same-origin iframe will inherit COOP from the iframe's top-level embedder.

// Opener's navigation to about:blank stays in the same browsing context group.
navigateToAboutBlankTest(
coop_same_origin_header,
same_origin,
false
);

// iframe cross-origin with its top-level embedder:
// initial empty document and about:blank navigations initiated from the
// cross-origin iframe will default COOP to unsafe-none.

// Opener's navigation to about:blank doesn't inherit COOP, leading to a
// browsing context group switch.
navigateToAboutBlankTest(
coop_same_origin_header,
cross_origin,
true
);

// Same origin allow popups allows the navigation of top to the cross-origin
// about:blank (origin inherited from the iframe) page, which does not have COOP
// (initiator is a cross origin iframe).
navigateToAboutBlankTest(
coop_same_origin_allow_popups_header,
cross_origin,
false
);
</script>
2 changes: 2 additions & 0 deletions lint.ignore
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,8 @@ SET TIMEOUT: feature-policy/experimental-features/resources/focus-without-user-a
SET TIMEOUT: permissions-policy/experimental-features/resources/focus-without-user-activation-iframe-tentative.html
SET TIMEOUT: html/browsers/windows/auxiliary-browsing-contexts/resources/close-opener.html
SET TIMEOUT: html/cross-origin-embedder-policy/resources/reporting-worker.js
SET TIMEOUT: html/cross-origin-opener-policy/navigate-to-aboutblank.https.html
SET TIMEOUT: html/cross-origin-opener-policy/navigate-top-to-aboutblank.https.html
SET TIMEOUT: html/cross-origin-opener-policy/reporting/resources/dispatcher.js
SET TIMEOUT: html/dom/documents/dom-tree-accessors/Document.currentScript.html
SET TIMEOUT: html/webappapis/timers/*
Expand Down

0 comments on commit c4f759f

Please sign in to comment.