Skip to content

Commit

Permalink
Do not forward focus to child frame when calling window.focus() on pa…
Browse files Browse the repository at this point in the history
…rent frame

Differential Revision: https://phabricator.services.mozilla.com/D146446

bugzilla-url: https://bugzilla.mozilla.org/show_bug.cgi?id=1757531
gecko-commit: c424ce3bbdf1f959575ad753feeceb97b97dd31b
gecko-reviewers: hsivonen
  • Loading branch information
EdgarChen authored and moz-wptsync-bot committed Jun 1, 2022
1 parent 08955b5 commit 53b704d
Show file tree
Hide file tree
Showing 5 changed files with 218 additions and 0 deletions.
88 changes: 88 additions & 0 deletions focus/activeelement-after-calling-window-focus.sub.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<!doctype html>
<meta charset=utf-8>
<title>activeElement after calling window.focus()</title>
<meta name="timeout" content="long">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<script>
function waitForEvent(target, event, checkFn) {
return new Promise(resolve => {
target.addEventListener(event, e => {
if (checkFn && !checkFn(e)) {
return;
}
resolve();
}, { once: true });
});
}

function focusInnerInput(w) {
w.postMessage("focusinnerinput", "*");
}

function focusInnerFrame(w) {
w.postMessage("focusinner", "*");
}

function focusMiddleFrame(w) {
w.postMessage("focusmiddle", "*");
}

function focusOuterFrame(w) {
w.postMessage("focusouter", "*");
}

// This will send message to outer frame and also inner frame to ask them
// send the log they collect back, the logs of outer and inner will be
// concatenated.
async function getLog(w) {
let log = "";
step_timeout(function() {
w.postMessage("getlog", "*");
}, 0);
await waitForEvent(window, "message", (e) => {
log = e.data;
return true;
});
return log;
}

async function runTest(t, url) {
let w = window.open(url);
t.add_cleanup(() => { w.close(); });
await waitForEvent(window, "message", e => e.data === "ready");
// Calling input.focus() on inner iframe should move its document.activeElement to INPUT.
focusInnerInput(w);
assert_equals(await getLog(w), 'outerlog:windowblur,middlelog:innerlog:windowfocus,INPUT,');
// Calling window.focus() on inner iframe should NOT reset its document.activeElement to BODY
// because it's focused element is not an iframe.
focusInnerFrame(w);
assert_equals(await getLog(w), 'outerlog:windowblur,middlelog:innerlog:windowfocus,INPUT,INPUT,');
// Calling window.focus() on middle iframe should reset its document.activeElement to BODY.
focusMiddleFrame(w);
assert_equals(await getLog(w), 'outerlog:windowblur,middlelog:windowfocus,BODY,innerlog:windowfocus,INPUT,INPUT,windowblur,');
// Calling window.focus() on top-level frame should reset its document.activeElement to BODY.
focusOuterFrame(w);
assert_equals(await getLog(w), 'outerlog:windowblur,windowfocus,BODY,middlelog:windowfocus,BODY,windowblur,innerlog:windowfocus,INPUT,INPUT,windowblur,');
}

promise_test(async t => {
await runTest(t, "https://{{hosts[][www]}}:{{ports[https][0]}}/focus/support/activeelement-after-calling-window-focus-outer-same.sub.html");
}, "Tests for all frames are in same origin");

promise_test(async t => {
await runTest(t, "https://{{hosts[alt][www]}}:{{ports[https][0]}}/focus/support/activeelement-after-calling-window-focus-outer-same.sub.html");
}, "Tests for middle frame and inner frame are in same origin and outer frame is in different origin");

promise_test(async t => {
await runTest(t, "https://{{hosts[alt][www]}}:{{ports[https][0]}}/focus/support/activeelement-after-calling-window-focus-outer-different.sub.html");
}, "Tests for outer frame and middle frame are in same origin and inner frame is in different origin");

promise_test(async t => {
await runTest(t, "https://{{hosts[][www]}}:{{ports[https][0]}}/focus/support/activeelement-after-calling-window-focus-outer-different.sub.html");
}, "Tests for outer frame and inner frame are in same origin and middle frame is in different origin");

promise_test(async t => {
await runTest(t, "support/activeelement-after-calling-window-focus-outer-different.sub.html");
}, "Tests for all frames are in different origin");
</script>
38 changes: 38 additions & 0 deletions focus/support/activeelement-after-calling-window-focus-inner.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Focus test inner document</title>
</head>
<body>
<h1>Inner</h1>
<input>
<script>
let innerlog = "innerlog:";

window.onmessage = function(e) {
if (e.data == "focusinnerinput") {
document.querySelector("input").focus();
innerlog += document.activeElement.tagName + ",";
} else if (e.data == "focusinner") {
window.focus();
innerlog += document.activeElement.tagName + ",";
} else if (e.data == "getlog") {
parent.postMessage(innerlog, "*");
}
};

window.onfocus = function() {
innerlog += "windowfocus,";
};

window.onblur = function() {
innerlog += "windowblur,";
};

window.onload = function() {
parent.postMessage("ready", "*");
}
</script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!doctype html>
<meta charset="utf-8">
<title>Focus test middle document</title>
<h1>Middle</h1><br>
<iframe src="https://{{hosts[][www]}}:{{ports[https][0]}}/focus/support/activeelement-after-calling-window-focus-inner.html"></iframe>
<script>
let middlelog = "middlelog:";

let iframe = document.querySelector("iframe");
window.onmessage = function(e) {
if (e.data == "ready") {
parent.postMessage(e.data, "*");
} else if (e.data == "focusinnerinput" || e.data == "focusinner" || e.data == "getlog") {
iframe.contentWindow.postMessage(e.data, "*");
} else if (e.data == "focusmiddle") {
window.focus();
middlelog += document.activeElement.tagName + ",";
} else {
parent.postMessage(middlelog + e.data, "*");
}
};

window.onfocus = function() {
middlelog += "windowfocus,";
};

window.onblur = function() {
middlelog += "windowblur,";
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!doctype html>
<meta charset="utf-8">
<title>Focus test outer document</title>
<iframe src="https://{{hosts[alt][www]}}:{{ports[https][0]}}/focus/support/activeelement-after-calling-window-focus-middle.sub.html"></iframe>
<script>
let outerlog = "outerlog:";

let iframe = document.querySelector("iframe");
window.onmessage = function(e) {
if (e.data == "ready") {
opener.postMessage(e.data, "*");
} else if (e.data == "focusinnerinput" || e.data == "focusinner" || e.data == "focusmiddle" || e.data == "getlog") {
iframe.contentWindow.postMessage(e.data, "*");
} else if (e.data == "focusouter") {
window.focus();
outerlog += document.activeElement.tagName + ",";
} else {
opener.postMessage(outerlog + e.data, "*");
}
};

window.onload = function() {
window.onfocus = function() {
outerlog += "windowfocus,";
};
};

window.onblur = function() {
outerlog += "windowblur,";
};
</script>
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!doctype html>
<meta charset="utf-8">
<title>Focus test outer document</title>
<iframe src="https://{{hosts[][www]}}:{{ports[https][0]}}/focus/support/activeelement-after-calling-window-focus-middle.sub.html"></iframe>
<script>
let outerlog = "outerlog:";

let iframe = document.querySelector("iframe");
window.onmessage = function(e) {
if (e.data == "ready") {
opener.postMessage(e.data, "*");
} else if (e.data == "focusinnerinput" || e.data == "focusinner" || e.data == "focusmiddle" || e.data == "getlog") {
iframe.contentWindow.postMessage(e.data, "*");
} else if (e.data == "focusouter") {
window.focus();
outerlog += document.activeElement.tagName + ",";
} else {
opener.postMessage(outerlog + e.data, "*");
}
};

window.onload = function() {
window.onfocus = function() {
outerlog += "windowfocus,";
};
};

window.onblur = function() {
outerlog += "windowblur,";
};
</script>

1 comment on commit 53b704d

@community-tc-integration
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Uh oh! Looks like an error! Details

invalid json response body at https://api.github.com/repos/web-platform-tests/wpt/check-runs reason: Unexpected end of JSON input

Please sign in to comment.