Skip to content

Commit 3ad44da

Browse files
vinhillmoz-wptsync-bot
authored andcommitted
Align CloseOuter with #script-closable session history check.
Since whatwg/html#6315, script-closable checks for a history length of one, instead of the session history containing only one document. This commit also adds a wpt to test that windows opened by links and forms count as `created by a script`. Differential Revision: https://phabricator.services.mozilla.com/D245035 bugzilla-url: https://bugzilla.mozilla.org/show_bug.cgi?id=1959610 gecko-commit: e0390012bdc423f35439ff7c3709ba26982b8883 gecko-reviewers: smaug
1 parent cdec662 commit 3ad44da

File tree

5 files changed

+133
-26
lines changed

5 files changed

+133
-26
lines changed

html/browsers/the-window-object/open-close/close_noopener_beforeunload-1.html

Lines changed: 0 additions & 8 deletions
This file was deleted.

html/browsers/the-window-object/open-close/close_noopener_beforeunload-2.html

Lines changed: 0 additions & 6 deletions
This file was deleted.

html/browsers/the-window-object/open-close/close_noopener_beforeunload.html

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,31 @@
44
<script src="/resources/testharnessreport.js"></script>
55
<div id="log"></div>
66
<script>
7-
async_test(t => {
8-
window.open("close_noopener_beforeunload-2.html?2", "", "noopener");
9-
let chan = new BroadcastChannel("close_noopener_beforeunload?2");
10-
chan.onmessage = t.step_func_done(function(event) {
11-
assert_equals(event.data.name, "beforeunload", "correct message received");
12-
assert_equals(event.data.history, 2, "session history has multiple entries");
7+
function waitForMessage(channel, name) {
8+
return new Promise(resolve => {
9+
function listener({ data }) {
10+
if (data.name === name) {
11+
channel.removeEventListener("message", listener);
12+
resolve(data);
13+
}
14+
};
15+
channel.addEventListener("message", listener);
1316
});
17+
}
18+
19+
async_test(t => {
20+
let chan = new BroadcastChannel("close_noopener_beforeunload2");
21+
waitForMessage(chan, "beforeunload").then(t.step_func_done(data => {
22+
assert_equals(data.history, 2, "session history has multiple entries");
23+
}));
24+
window.open("self-close.html?navs=1&channel=close_noopener_beforeunload2", "", "noopener");
1425
}, "closing noopener window with 2 entries");
1526

1627
async_test(t => {
17-
window.open("close_noopener_beforeunload-1.html?1", "", "noopener");
18-
let chan = new BroadcastChannel("close_noopener_beforeunload?1");
19-
chan.onmessage = t.step_func_done(function(event) {
20-
assert_equals(event.data.name, "beforeunload", "correct message received");
21-
assert_equals(event.data.history, 1, "session history has a single entry");
22-
});
28+
let chan = new BroadcastChannel("close_noopener_beforeunload1");
29+
waitForMessage(chan, "beforeunload").then(t.step_func_done(data => {
30+
assert_equals(data.history, 1, "session history has a single entry");
31+
}));
32+
window.open("self-close.html?navs=0&channel=close_noopener_beforeunload1", "", "noopener");
2333
}, "closing noopener window with 1 entry");
2434
</script>
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<!doctype html>
2+
<title>Test whether a window is script-closable</title>
3+
<link rel="help" href="https://html.spec.whatwg.org/#script-closable"/>
4+
<script src="/resources/testharness.js"></script>
5+
<script src="/resources/testharnessreport.js"></script>
6+
<div id="log"></div>
7+
8+
<script>
9+
let uid = 0;
10+
11+
async function withChannel(createWindow) {
12+
const channel_name = `channel_${++uid}`;
13+
const channel = new BroadcastChannel(channel_name);
14+
15+
const closedPromise = new Promise(resolve => {
16+
channel.addEventListener("message", ({data}) => {
17+
if (data.name === 'load') {
18+
assert_true(true, 'window was loaded');
19+
} else {
20+
assert_not_equals(data.history, 1, "If script-closable, then not due to history length");
21+
resolve(data.closed);
22+
}
23+
});
24+
});
25+
26+
await createWindow(channel_name);
27+
return closedPromise;
28+
}
29+
30+
const Actions = {
31+
async form(noopener) {
32+
return withChannel((channel_name) => {
33+
const form = document.createElement("form");
34+
form.action = "self-close.html";
35+
form.target = '_blank';
36+
if (noopener) {
37+
form.rel = "noopener";
38+
}
39+
// ?navs=1
40+
const inp1 = document.createElement("input");
41+
inp1.name = "navs";
42+
inp1.value = "1";
43+
form.appendChild(inp1);
44+
// ?channel=channel_name
45+
const inp2 = document.createElement("input");
46+
inp2.name = "channel";
47+
inp2.value = channel_name;
48+
form.appendChild(inp2);
49+
document.body.appendChild(form);
50+
51+
form.submit();
52+
form.remove();
53+
});
54+
},
55+
async link(noopener) {
56+
return withChannel((channel_name) => {
57+
const anchor = document.createElement("a");
58+
anchor.href = `self-close.html?navs=1&channel=${channel_name}`;
59+
anchor.target = '_blank';
60+
if (noopener) {
61+
anchor.rel = "noopener";
62+
}
63+
document.body.appendChild(anchor);
64+
65+
anchor.click();
66+
67+
anchor.remove();
68+
});
69+
},
70+
async script(noopener) {
71+
return withChannel((channel_name) => {
72+
const url = `self-close.html?navs=1&channel=${channel_name}`;
73+
window.open(url, "_blank", noopener ? 'noopener' : '');
74+
});
75+
}
76+
}
77+
78+
for (const action of [Actions.form, Actions.link, Actions.script]) {
79+
for (const noopener of [false, true])
80+
promise_test(async () => {
81+
const closed = await action(noopener);
82+
assert_true(closed, "window closed");
83+
}, `Window created by ${action.name} with ${noopener ? 'noopener' : 'opener'} is script-closable`);
84+
}
85+
</script>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<!doctype html>
2+
<p>self-close.html?navs=n&channel=name will navigate n times, then close and notify the channel.</p>
3+
4+
<script>
5+
window.onload = setTimeout(() => {
6+
const urlParams = new URLSearchParams(window.location.search);
7+
let n = parseInt(urlParams.get('navs')) || 0;
8+
9+
const channel = new BroadcastChannel(urlParams.get('channel'));
10+
11+
channel.postMessage({ name: 'load', href: window.location.href });
12+
13+
if (n > 0) {
14+
urlParams.set('navs', n-1);
15+
window.location.href = `${window.location.pathname}?${urlParams.toString()}#${n}`;
16+
} else {
17+
window.onbeforeunload = () => {
18+
channel.postMessage({ name: 'beforeunload', history: history.length, closed: true });
19+
}
20+
window.close();
21+
if (!window.closed) {
22+
channel.postMessage({ name: 'close failed', history: history.length, closed: false });
23+
}
24+
}
25+
}, 0);
26+
</script>

0 commit comments

Comments
 (0)