206 lines
6.7 KiB
HTML
206 lines
6.7 KiB
HTML
<!DOCTYPE html>
|
|
<title>Test Script-Based Focus for Fenced Frames</title>
|
|
<script src="/resources/testharness.js"></script>
|
|
<script src="/resources/testharnessreport.js"></script>
|
|
<script src="/resources/testdriver.js"></script>
|
|
<script src="/resources/testdriver-actions.js"></script>
|
|
<script src="/resources/testdriver-vendor.js"></script>
|
|
<script src="/common/utils.js"></script>
|
|
<script src="resources/utils.js"></script>
|
|
<script src="/common/dispatcher/dispatcher.js"></script>
|
|
|
|
<script src="/common/get-host-info.sub.js"></script>
|
|
|
|
<body>
|
|
<script>
|
|
async function AttemptButtonFocus(frame, expecting_focus) {
|
|
await frame.execute(async (expecting_focus) => {
|
|
const button = document.createElement("button");
|
|
document.body.append(button);
|
|
button.focus();
|
|
assert_equals(document.activeElement == button, expecting_focus,
|
|
"Button's focus should match expected focus");
|
|
}, [expecting_focus]);
|
|
}
|
|
|
|
async function ClickOn(element, actions) {
|
|
// Wait until the window size is initialized.
|
|
while (window.innerWidth == 0) {
|
|
await new Promise(resolve => requestAnimationFrame(resolve));
|
|
}
|
|
await actions.pointerMove(0, 0, {origin: element})
|
|
.pointerDown()
|
|
.pointerUp()
|
|
.send();
|
|
}
|
|
|
|
async function SetupTest(click=true) {
|
|
// Clean up any leftover frames from prior tests.
|
|
document.querySelectorAll("fencedframe").forEach(e => {
|
|
e.remove();
|
|
})
|
|
|
|
const actions = new test_driver.Actions();
|
|
|
|
const frame = attachFencedFrameContext();
|
|
const fencedframe_element = frame.element;
|
|
|
|
if (click)
|
|
await ClickOn(document.body, actions);
|
|
|
|
return [actions, frame, fencedframe_element];
|
|
}
|
|
|
|
promise_test(async () => {
|
|
const [actions, ff1, ff1_element] = await SetupTest(false);
|
|
|
|
await ClickOn(ff1_element, actions);
|
|
await AttemptButtonFocus(ff1, true);
|
|
|
|
const button = document.createElement("button");
|
|
document.body.append(button);
|
|
button.focus();
|
|
assert_true(document.activeElement == button,
|
|
"The button should have focus");
|
|
assert_false(navigator.userActivation.isActive,
|
|
"Window should not have user activation");
|
|
}, "An embedder can focus out of a fenced frame");
|
|
|
|
promise_test(async () => {
|
|
const [actions, frame, fencedframe_element] = await SetupTest();
|
|
|
|
await AttemptButtonFocus(frame, false);
|
|
await ClickOn(fencedframe_element, actions);
|
|
await AttemptButtonFocus(frame, true);
|
|
}, "Fenced frames can't pull script focus until getting user activation");
|
|
|
|
promise_test(async t => {
|
|
const [actions, frame, fencedframe_element] = await SetupTest();
|
|
|
|
await ClickOn(fencedframe_element, actions);
|
|
await ClickOn(document.body, actions);
|
|
|
|
await AttemptButtonFocus(frame, true);
|
|
|
|
// Give the browser time to receive the focus event before attempting
|
|
// another focus.
|
|
await t.step_timeout(async () => {await AttemptButtonFocus(frame, true);},
|
|
500);
|
|
}, "Focused fenced frames can move programmatic focus within frame");
|
|
|
|
promise_test(async () => {
|
|
const [actions, frame, fencedframe_element] = await SetupTest();
|
|
|
|
await ClickOn(fencedframe_element, actions);
|
|
await ClickOn(document.body, actions);
|
|
|
|
// This will pull focus across a frame boundary and consume user activation.
|
|
await AttemptButtonFocus(frame, true);
|
|
|
|
await ClickOn(document.body, actions);
|
|
await AttemptButtonFocus(frame, false);
|
|
}, "Script focus into a fenced frame consumes user activation");
|
|
|
|
promise_test(async () => {
|
|
const [actions, ff1, ff1_element] = await SetupTest();
|
|
|
|
const ff2 = attachFencedFrameContext();
|
|
const ff2_element = ff2.element;
|
|
|
|
await ClickOn(ff1_element, actions);
|
|
|
|
await AttemptButtonFocus(ff1, true);
|
|
await AttemptButtonFocus(ff2, false);
|
|
}, "Another fenced frame cannot pull focus out of a focused fenced frame");
|
|
|
|
promise_test(async () => {
|
|
const [actions, ff1, ff1_element] = await SetupTest();
|
|
|
|
await ClickOn(ff1_element, actions);
|
|
await AttemptButtonFocus(ff1, true);
|
|
|
|
await ff1.execute(async () => {
|
|
const ff2 = attachFencedFrameContext();
|
|
|
|
await ff2.execute(async () => {
|
|
const button = document.createElement("button");
|
|
document.body.append(button);
|
|
button.focus();
|
|
assert_false(document.activeElement == button,
|
|
"The button should not have focus");
|
|
assert_false(navigator.userActivation.isActive,
|
|
"The fenced frame should not have user activation");
|
|
});
|
|
});
|
|
}, "A fenced frame nested in another fenced frame cannot pull focus");
|
|
|
|
promise_test(async () => {
|
|
const [actions, ff1, ff1_element] = await SetupTest();
|
|
|
|
await ClickOn(document.body, actions);
|
|
|
|
const button = document.createElement("button");
|
|
document.body.append(button);
|
|
button.focus();
|
|
assert_equals(document.activeElement, button,
|
|
"The button in the main page should have focus.");
|
|
|
|
await ff1.execute(async () => {
|
|
assert_false(navigator.userActivation.isActive,
|
|
"The fenced frame should not have user activation.");
|
|
window.focus();
|
|
});
|
|
|
|
assert_equals(document.activeElement, button,
|
|
"The button in the main page should still have focus.");
|
|
}, "A fenced frame cannot pull window.focus() without user activation");
|
|
|
|
promise_test(async () => {
|
|
const [actions, ff1, ff1_element] = await SetupTest();
|
|
|
|
await ClickOn(ff1_element, actions);
|
|
await ClickOn(document.body, actions);
|
|
|
|
const button = document.createElement("button");
|
|
document.body.append(button);
|
|
button.focus();
|
|
assert_equals(document.activeElement, button,
|
|
"The button should have focus.");
|
|
|
|
await ff1.execute(async () => {
|
|
assert_true(navigator.userActivation.isActive,
|
|
"The fenced frame should have user activation.");
|
|
window.focus();
|
|
assert_false(navigator.userActivation.isActive,
|
|
"The fenced frame's user activation should be consumed by the focus");
|
|
});
|
|
|
|
assert_equals(document.activeElement, document.body,
|
|
"The main page's focus should be pulled away from the button.");
|
|
}, "A fenced frame can pull window.focus() after user activation");
|
|
|
|
promise_test(async () => {
|
|
var actions = new test_driver.Actions();
|
|
|
|
const frame = attachIFrameContext(
|
|
{origin: get_host_info().HTTPS_REMOTE_ORIGIN});
|
|
const iframe_element =
|
|
document.body.getElementsByTagName('iframe')[0];
|
|
|
|
await frame.execute(async () => {
|
|
const button = document.createElement("button");
|
|
document.body.append(button);
|
|
button.focus();
|
|
assert_equals(document.activeElement, button,
|
|
"The button in the iframe should have focus.");
|
|
}, [true]);
|
|
|
|
const button = document.createElement("button");
|
|
document.body.append(button);
|
|
button.focus();
|
|
assert_equals(document.activeElement, button,
|
|
"The button in the main page should have focus.");
|
|
}, "An cross-origin iframe can pull focus back and forth without activation");
|
|
|
|
</script>
|
|
</body>
|