зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1483828 - [Part 1] Disallow <tab> to move focus to root element r=smaug
Brings us on-par with Chrome and Safari Differential Revision: https://phabricator.services.mozilla.com/D198436
This commit is contained in:
Родитель
4b63bf2834
Коммит
8f46bf2a0c
|
@ -246,7 +246,10 @@ window.onload = function() {
|
|||
synthesizeKey("KEY_Tab", { shiftKey: true });
|
||||
},
|
||||
state: { current: 0, active: null },
|
||||
activeElement: listEl.ownerDocument.documentElement,
|
||||
activeElement:
|
||||
!SpecialPowers.getBoolPref("dom.disable_tab_focus_to_root_element.enabled")
|
||||
? listEl.ownerDocument.documentElement
|
||||
: defaultFocus,
|
||||
}];
|
||||
|
||||
for (const test of tests) {
|
||||
|
|
|
@ -4522,7 +4522,7 @@ nsresult nsFocusManager::GetNextTabbableContent(
|
|||
if (aCurrentTabIndex == (aForward ? 0 : 1)) {
|
||||
// if going backwards, the canvas should be focused once the beginning
|
||||
// has been reached, so get the root element.
|
||||
if (!aForward) {
|
||||
if (!aForward && !StaticPrefs::dom_disable_tab_focus_to_root_element()) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window = GetCurrentWindow(aRootContent);
|
||||
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
|
||||
|
||||
|
@ -4576,7 +4576,7 @@ bool nsFocusManager::TryToMoveFocusToSubDocument(
|
|||
NS_ASSERTION(doc, "content not in document");
|
||||
Document* subdoc = doc->GetSubDocumentFor(aCurrentContent);
|
||||
if (subdoc && !subdoc->EventHandlingSuppressed()) {
|
||||
if (aForward) {
|
||||
if (aForward && !StaticPrefs::dom_disable_tab_focus_to_root_element()) {
|
||||
// When tabbing forward into a frame, return the root
|
||||
// frame so that the canvas becomes focused.
|
||||
if (nsCOMPtr<nsPIDOMWindowOuter> subframe = subdoc->GetWindow()) {
|
||||
|
@ -4597,6 +4597,13 @@ bool nsFocusManager::TryToMoveFocusToSubDocument(
|
|||
if (*aResultContent) {
|
||||
return true;
|
||||
}
|
||||
if (rootElement->IsEditable() &&
|
||||
StaticPrefs::dom_disable_tab_focus_to_root_element()) {
|
||||
// Only move to the root element with a valid reason
|
||||
*aResultContent = rootElement;
|
||||
NS_ADDREF(*aResultContent);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,10 +79,16 @@
|
|||
opener.is(lastFocusTarget, shadowDate, "Should have focused date element in shadow DOM. (3)");
|
||||
synthesizeKey("KEY_Tab");
|
||||
opener.is(lastFocusTarget, shadowDate, "Should have focused date element with a calendar button in shadow DOM. (3)");
|
||||
synthesizeKey("KEY_Tab");
|
||||
opener.is(shadowIframe.contentDocument.activeElement,
|
||||
shadowIframe.contentDocument.documentElement,
|
||||
"Should have focused document element in shadow iframe. (3)");
|
||||
|
||||
let canTabMoveFocusToRootElement =
|
||||
!SpecialPowers.getBoolPref("dom.disable_tab_focus_to_root_element");
|
||||
if (canTabMoveFocusToRootElement) {
|
||||
synthesizeKey("KEY_Tab");
|
||||
opener.is(shadowIframe.contentDocument.activeElement,
|
||||
shadowIframe.contentDocument.documentElement,
|
||||
"Should have focused document element in shadow iframe. (3)");
|
||||
}
|
||||
|
||||
synthesizeKey("KEY_Tab");
|
||||
opener.is(shadowIframe.contentDocument.activeElement,
|
||||
shadowIframe.contentDocument.body.firstChild,
|
||||
|
@ -99,10 +105,12 @@
|
|||
opener.is(shadowIframe.contentDocument.activeElement,
|
||||
shadowIframe.contentDocument.body.firstChild,
|
||||
"Should have focused input element in shadow iframe. (4)");
|
||||
synthesizeKey("KEY_Tab", {shiftKey: true});
|
||||
opener.is(shadowIframe.contentDocument.activeElement,
|
||||
shadowIframe.contentDocument.documentElement,
|
||||
"Should have focused document element in shadow iframe. (4)");
|
||||
if (canTabMoveFocusToRootElement) {
|
||||
synthesizeKey("KEY_Tab", {shiftKey: true});
|
||||
opener.is(shadowIframe.contentDocument.activeElement,
|
||||
shadowIframe.contentDocument.documentElement,
|
||||
"Should have focused document element in shadow iframe. (4)");
|
||||
}
|
||||
synthesizeKey("KEY_Tab", {shiftKey: true});
|
||||
opener.is(lastFocusTarget, shadowDate, "Should have focused date element with a calendar button in shadow DOM. (4)");
|
||||
synthesizeKey("KEY_Tab", {shiftKey: true});
|
||||
|
|
|
@ -20,7 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=226361
|
|||
|
||||
</p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
@ -43,8 +43,11 @@ function tab_to(id) {
|
|||
}
|
||||
|
||||
function tab_iframe() {
|
||||
doc = document;
|
||||
tab_to('iframe');
|
||||
let canTabMoveFocusToRootElement = !SpecialPowers.getBoolPref("dom.disable_tab_focus_to_root_element");
|
||||
if (canTabMoveFocusToRootElement) {
|
||||
doc = document;
|
||||
tab_to('iframe');
|
||||
}
|
||||
|
||||
// inside iframe
|
||||
doc = document.getElementById('iframe').contentDocument
|
||||
|
|
|
@ -56,10 +56,12 @@ function runTest(aObjectOrEmbed)
|
|||
const pbutton = document.getElementById("pbutton");
|
||||
pbutton.focus();
|
||||
|
||||
synthesizeKey("KEY_Tab");
|
||||
is(document.activeElement, aObjectOrEmbed, `${desc}: focus in parent after tab`);
|
||||
is(childDoc.activeElement, childDoc.documentElement, `${desc}: focus in child after tab`);
|
||||
|
||||
let canTabMoveFocusToRootElement = !SpecialPowers.getBoolPref("dom.disable_tab_focus_to_root_element");
|
||||
if (canTabMoveFocusToRootElement) {
|
||||
synthesizeKey("KEY_Tab");
|
||||
is(document.activeElement, aObjectOrEmbed, `${desc}: focus in parent after tab`);
|
||||
is(childDoc.activeElement, childDoc.documentElement, `${desc}: focus in child after tab`);
|
||||
}
|
||||
synthesizeKey("KEY_Tab");
|
||||
is(document.activeElement, aObjectOrEmbed, `${desc}: focus in parent after tab 2`);
|
||||
is(childDoc.activeElement, button, `${desc}: focus in child after tab 2`);
|
||||
|
|
|
@ -2530,6 +2530,8 @@ mozilla::ipc::IPCResult BrowserChild::RecvNavigateByKey(
|
|||
aForward
|
||||
? (aForDocumentNavigation
|
||||
? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_FIRSTDOC)
|
||||
: StaticPrefs::dom_disable_tab_focus_to_root_element()
|
||||
? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_FIRST)
|
||||
: static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_ROOT))
|
||||
: (aForDocumentNavigation
|
||||
? static_cast<uint32_t>(nsIFocusManager::MOVEFOCUS_LASTDOC)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Tests for for-of loops</title>
|
||||
<title>Test for using TAB to move focus and scroll into view</title>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
|
||||
|
@ -11,10 +11,18 @@
|
|||
<div id="content" style="display: none"></div>
|
||||
<script>
|
||||
function doTest() {
|
||||
var canTabMoveFocusToRootElement =
|
||||
!SpecialPowers.getBoolPref("dom.disable_tab_focus_to_root_element");
|
||||
document.getElementById("button").focus();
|
||||
const iframe = document.querySelector("iframe");
|
||||
is(window.scrollY, 0, "Scrolled position initially 0");
|
||||
synthesizeKey("KEY_Tab");
|
||||
ok(window.scrollY > 200, "Scrolled child frame into view");
|
||||
is(document.activeElement, iframe, "Focus moved to the iframe");
|
||||
if (canTabMoveFocusToRootElement) {
|
||||
ok(window.scrollY > 200, "Scrolled child frame into view");
|
||||
} else {
|
||||
is(window.scrollY, 0, "Scrolled position remained the same");
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
|
|
@ -4817,6 +4817,12 @@
|
|||
value: true
|
||||
mirror: always
|
||||
|
||||
# Whether allowing using <tab> to move focus to root elements
|
||||
- name: dom.disable_tab_focus_to_root_element
|
||||
type: bool
|
||||
value: @IS_NIGHTLY_BUILD@
|
||||
mirror: always
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Prefs starting with "editor"
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
|
@ -49,6 +49,8 @@ function onUnload() {
|
|||
|
||||
var gFocusObservingElement = null;
|
||||
var gBlurObservingElement = null;
|
||||
var canTabMoveFocusToRootElement =
|
||||
!SpecialPowers.getBoolPref("dom.disable_tab_focus_to_root_element");
|
||||
|
||||
function onFocus(aEvent) {
|
||||
if (aEvent.target != gFocusObservingElement) {
|
||||
|
@ -201,18 +203,30 @@ function runTests() {
|
|||
root = iframe.contentDocument.documentElement;
|
||||
resetFocusToInput("initializing for iframe_not_editable");
|
||||
|
||||
testTabKey(true, root, false, prev, true,
|
||||
false, "input#prev[readonly] -> html");
|
||||
testTabKey(true, editor, true, root, false,
|
||||
true, "html -> input in the subdoc");
|
||||
if (canTabMoveFocusToRootElement) {
|
||||
testTabKey(true, root, false, prev, true,
|
||||
false, "input#prev[readonly] -> html");
|
||||
testTabKey(true, editor, true, root, false,
|
||||
true, "html -> input in the subdoc");
|
||||
} else {
|
||||
testTabKey(true, editor, true, prev, true,
|
||||
true, "input#prev[readonly] -> input in the subdoc");
|
||||
}
|
||||
testTabKey(true, next, true, editor, true,
|
||||
false, "input in the subdoc -> input#next[readonly]");
|
||||
testTabKey(false, editor, true, next, true,
|
||||
true, "input#next[readonly] -> input in the subdoc");
|
||||
testTabKey(false, root, false, editor, true,
|
||||
false, "input in the subdoc -> html");
|
||||
testTabKey(false, prev, true, root, false,
|
||||
false, "html -> input#next[readonly]");
|
||||
if (canTabMoveFocusToRootElement) {
|
||||
testTabKey(false, root, false, editor, true,
|
||||
false, "input in the subdoc -> html");
|
||||
testTabKey(false, prev, true, root, false,
|
||||
false, "html -> input#next[readonly]");
|
||||
} else {
|
||||
testTabKey(false, prev, true, editor, true,
|
||||
false, "input in the subdoc -> input#prev[readonly]");
|
||||
testTabKey(false, next, true, prev, true,
|
||||
false, "input#prev[readonly] -> input#next[readonly]");
|
||||
}
|
||||
|
||||
iframe.style.display = "none";
|
||||
|
||||
|
@ -236,8 +250,13 @@ function runTests() {
|
|||
resetFocusToParentHTML("testing iframe_html");
|
||||
testTabKey(true, editor, true, html, false,
|
||||
true, "html of parent -> html[contentediable=true]");
|
||||
testTabKey(false, html, false, editor, true,
|
||||
false, "html[contenteditable=true] -> html of parent");
|
||||
if (canTabMoveFocusToRootElement) {
|
||||
testTabKey(false, html, false, editor, true,
|
||||
false, "html[contenteditable=true] -> html of parent");
|
||||
} else {
|
||||
testTabKey(false, next, true, editor, true,
|
||||
false, "html[contenteditable=true] -> input#next[readonly]");
|
||||
}
|
||||
prev.style.display = "inline";
|
||||
resetFocusToInput("after parent html <-> html[contenteditable=true]");
|
||||
|
||||
|
@ -270,8 +289,13 @@ function runTests() {
|
|||
resetFocusToParentHTML("testing iframe_designMode");
|
||||
testTabKey(true, root, false, html, false,
|
||||
true, "html of parent -> html in designMode");
|
||||
testTabKey(false, html, false, root, false,
|
||||
false, "html in designMode -> html of parent");
|
||||
if (canTabMoveFocusToRootElement) {
|
||||
testTabKey(false, html, false, root, false,
|
||||
false, "html[contenteditable=true] -> html of parent");
|
||||
} else {
|
||||
testTabKey(false, next, true, root, false,
|
||||
false, "html in designMode -> html of parent");
|
||||
}
|
||||
prev.style.display = "inline";
|
||||
resetFocusToInput("after parent html <-> html in designMode");
|
||||
|
||||
|
@ -302,8 +326,13 @@ function runTests() {
|
|||
resetFocusToParentHTML("testing iframe_body");
|
||||
testTabKey(true, editor, true, html, false,
|
||||
true, "html of parent -> body[contentediable=true]");
|
||||
testTabKey(false, html, false, editor, true,
|
||||
false, "body[contenteditable=true] -> html of parent");
|
||||
if (canTabMoveFocusToRootElement) {
|
||||
testTabKey(false, html, false, editor, true,
|
||||
false, "body[contenteditable=true] -> html of parent");
|
||||
} else {
|
||||
testTabKey(false, next, true, editor, true,
|
||||
false, "body[contenteditable=true] -> input#next[readonly]");
|
||||
}
|
||||
prev.style.display = "inline";
|
||||
resetFocusToInput("after parent html <-> body[contenteditable=true]");
|
||||
|
||||
|
@ -321,25 +350,44 @@ function runTests() {
|
|||
root = iframe.contentDocument.documentElement;
|
||||
resetFocusToInput("initializing for iframe_p");
|
||||
|
||||
testTabKey(true, root, false, prev, true,
|
||||
false, "input#prev[readonly] -> html (has p[contenteditable=true])");
|
||||
testTabKey(true, editor, true, root, false,
|
||||
true, "html (has p[contenteditable=true]) -> p[contentediable=true]");
|
||||
if (canTabMoveFocusToRootElement) {
|
||||
testTabKey(true, root, false, prev, true,
|
||||
false, "input#prev[readonly] -> html (has p[contenteditable=true])");
|
||||
testTabKey(true, editor, true, root, false,
|
||||
true, "html (has p[contenteditable=true]) -> p[contentediable=true]");
|
||||
} else {
|
||||
testTabKey(true, editor, true, prev, true,
|
||||
true, "input#prev[readonly] -> p[contenteditable=true]");
|
||||
}
|
||||
testTabKey(true, next, true, editor, true,
|
||||
false, "p[contentediable=true] -> input#next[readonly]");
|
||||
testTabKey(false, editor, true, next, true,
|
||||
true, "input#next[readonly] -> p[contentediable=true]");
|
||||
testTabKey(false, root, false, editor, true,
|
||||
false, "p[contenteditable=true] -> html (has p[contenteditable=true])");
|
||||
testTabKey(false, prev, true, root, false,
|
||||
false, "html (has p[contenteditable=true]) -> input#prev[readonly]");
|
||||
if (canTabMoveFocusToRootElement) {
|
||||
testTabKey(false, root, false, editor, true,
|
||||
false, "p[contenteditable=true] -> html (has p[contenteditable=true])");
|
||||
testTabKey(false, prev, true, root, false,
|
||||
false, "html (has p[contenteditable=true]) -> input#prev[readonly]");
|
||||
} else {
|
||||
testTabKey(false, prev, true, editor, true,
|
||||
false, "p[contenteditable=true] -> html (has p[contenteditable=true])");
|
||||
testTabKey(false, next, true, prev, true,
|
||||
false, "html (has p[contenteditable=true]) -> input#next[readonly]");
|
||||
}
|
||||
prev.style.display = "none";
|
||||
|
||||
resetFocusToParentHTML("testing iframe_p");
|
||||
testTabKey(true, root, false, html, false,
|
||||
false, "html of parent -> html (has p[contentediable=true])");
|
||||
testTabKey(false, html, false, root, false,
|
||||
false, "html (has p[contentediable=true]) -> html of parent");
|
||||
if (canTabMoveFocusToRootElement) {
|
||||
testTabKey(true, root, false, html, false,
|
||||
false, "html of parent -> html (has p[contentediable=true])");
|
||||
testTabKey(false, html, false, root, false,
|
||||
false, "html (has p[contentediable=true]) -> html of parent");
|
||||
} else {
|
||||
testTabKey(true, editor, true, html, false,
|
||||
true, "html of parent -> p[contentediable=true]");
|
||||
testTabKey(false, next, true, editor, true,
|
||||
false, "p[contentediable=true] -> input#next[readonly]");
|
||||
}
|
||||
prev.style.display = "inline";
|
||||
resetFocusToInput("after parent html <-> html (has p[contentediable=true])");
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче