Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test gets skipped with pattern: verify && !debug && os == 'linux'
- Manifest: browser/base/content/test/general/browser.toml
/*
* This test checks that focus is adjusted properly in a browser when pressing F6 and Shift+F6.
* There are additional tests in dom/tests/mochitest/chrome/test_focus_docnav.xul which test
* non-browser cases.
*/
var testPage1 =
"data:text/html,<html id='html1'><body id='body1'><button id='button1'>Tab 1</button></body></html>";
var testPage2 =
"data:text/html,<html id='html2'><body id='body2'><button id='button2'>Tab 2</button></body></html>";
var testPage3 =
"data:text/html,<html id='html3'><body id='body3' contenteditable='true'><button id='button3'>Tab 3</button></body></html>";
var fm = Services.focus;
async function expectFocusOnF6(
backward,
expectedDocument,
expectedElement,
onContent,
desc
) {
if (onContent) {
let success = await SpecialPowers.spawn(
gBrowser.selectedBrowser,
[expectedElement],
async function (expectedElementId) {
content.lastResult = "";
let contentExpectedElement =
content.document.getElementById(expectedElementId);
if (!contentExpectedElement) {
// Element not found, so look in the child frames.
for (let f = 0; f < content.frames.length; f++) {
if (content.frames[f].document.getElementById(expectedElementId)) {
contentExpectedElement = content.frames[f].document;
break;
}
}
} else if (contentExpectedElement.localName == "html") {
contentExpectedElement = contentExpectedElement.ownerDocument;
}
if (!contentExpectedElement) {
return null;
}
contentExpectedElement.addEventListener(
"focus",
function () {
let details =
Services.focus.focusedWindow.document.documentElement.id;
if (Services.focus.focusedElement) {
details += "," + Services.focus.focusedElement.id;
}
// Assign the result to a temporary place, to be used
// by the next spawn call.
content.lastResult = details;
},
{ capture: true, once: true }
);
return !!contentExpectedElement;
}
);
ok(success, "expected element " + expectedElement + " was found");
EventUtils.synthesizeKey("VK_F6", { shiftKey: backward });
let expected = expectedDocument;
if (!expectedElement.startsWith("html")) {
expected += "," + expectedElement;
}
let result = await SpecialPowers.spawn(
gBrowser.selectedBrowser,
[],
async () => {
await ContentTaskUtils.waitForCondition(() => content.lastResult);
return content.lastResult;
}
);
is(result, expected, desc + " child focus matches");
} else {
let focusPromise = BrowserTestUtils.waitForEvent(window, "focus", true);
EventUtils.synthesizeKey("VK_F6", { shiftKey: backward });
await focusPromise;
}
if (typeof expectedElement == "string") {
expectedElement = fm.focusedWindow.document.getElementById(expectedElement);
}
if (gMultiProcessBrowser && onContent) {
expectedDocument = "main-window";
expectedElement = gBrowser.selectedBrowser;
}
is(
fm.focusedWindow.document.documentElement.id,
expectedDocument,
desc + " document matches"
);
is(
fm.focusedElement,
expectedElement,
desc +
" element matches (wanted: " +
expectedElement.id +
" got: " +
fm.focusedElement.id +
")"
);
}
// Load a page and navigate between it and the chrome window.
add_task(async function () {
let page1Promise = BrowserTestUtils.browserLoaded(
gBrowser.selectedBrowser,
false,
testPage1
);
BrowserTestUtils.startLoadingURIString(gBrowser.selectedBrowser, testPage1);
await page1Promise;
// When the urlbar is focused, pressing F6 should focus the root of the content page.
gURLBar.focus();
await expectFocusOnF6(
false,
"html1",
"html1",
true,
"basic focus content page"
);
// When the content is focused, pressing F6 should focus the urlbar.
await expectFocusOnF6(
false,
"main-window",
gURLBar.inputField,
false,
"basic focus content page urlbar"
);
// When a button in content is focused, pressing F6 should focus the urlbar.
await expectFocusOnF6(
false,
"html1",
"html1",
true,
"basic focus content page with button focused"
);
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
return content.document.getElementById("button1").focus();
});
await expectFocusOnF6(
false,
"main-window",
gURLBar.inputField,
false,
"basic focus content page with button focused urlbar"
);
// The document root should be focused, not the button
await expectFocusOnF6(
false,
"html1",
"html1",
true,
"basic focus again content page with button focused"
);
// Check to ensure that the root element is focused
await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
Assert.ok(
content.document.activeElement == content.document.documentElement,
"basic focus again content page with button focused child root is focused"
);
});
});
// Open a second tab. Document focus should skip the background tab.
add_task(async function () {
await BrowserTestUtils.openNewForegroundTab(gBrowser, testPage2);
await expectFocusOnF6(
false,
"main-window",
gURLBar.inputField,
false,
"basic focus content page and second tab urlbar"
);
await expectFocusOnF6(
false,
"html2",
"html2",
true,
"basic focus content page with second tab"
);
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
// Shift+F6 should navigate backwards. There's only one document here so the effect
// is the same.
add_task(async function () {
gURLBar.focus();
await expectFocusOnF6(
true,
"html1",
"html1",
true,
"back focus content page"
);
await expectFocusOnF6(
true,
"main-window",
gURLBar.inputField,
false,
"back focus content page urlbar"
);
});
// Open the sidebar and navigate between the sidebar, content and top-level window
add_task(async function () {
let sidebar = document.getElementById("sidebar");
let loadPromise = BrowserTestUtils.waitForEvent(sidebar, "load", true);
SidebarController.toggle("viewBookmarksSidebar");
await loadPromise;
gURLBar.focus();
await expectFocusOnF6(
false,
"bookmarksPanel",
sidebar.contentDocument.getElementById("search-box").inputField,
false,
"focus with sidebar open sidebar"
);
await expectFocusOnF6(
false,
"html1",
"html1",
true,
"focus with sidebar open content"
);
await expectFocusOnF6(
false,
"main-window",
gURLBar.inputField,
false,
"focus with sidebar urlbar"
);
// Now go backwards
await expectFocusOnF6(
true,
"html1",
"html1",
true,
"back focus with sidebar open content"
);
await expectFocusOnF6(
true,
"bookmarksPanel",
sidebar.contentDocument.getElementById("search-box").inputField,
false,
"back focus with sidebar open sidebar"
);
await expectFocusOnF6(
true,
"main-window",
gURLBar.inputField,
false,
"back focus with sidebar urlbar"
);
SidebarController.toggle("viewBookmarksSidebar");
});
// Navigate when the downloads panel is open
add_task(async function test_download_focus() {
await pushPrefs(
["accessibility.tabfocus", 7],
["browser.download.autohideButton", false],
["security.dialog_enable_delay", 0]
);
await promiseButtonShown("downloads-button");
let popupShownPromise = BrowserTestUtils.waitForEvent(
document,
"popupshown",
true
);
EventUtils.synthesizeMouseAtCenter(
document.getElementById("downloads-button"),
{}
);
await popupShownPromise;
gURLBar.focus();
await expectFocusOnF6(
false,
"main-window",
document.getElementById("downloadsHistory"),
false,
"focus with downloads panel open panel"
);
await expectFocusOnF6(
false,
"html1",
"html1",
true,
"focus with downloads panel open"
);
await expectFocusOnF6(
false,
"main-window",
gURLBar.inputField,
false,
"focus downloads panel open urlbar"
);
// Now go backwards
await expectFocusOnF6(
true,
"html1",
"html1",
true,
"back focus with downloads panel open"
);
await expectFocusOnF6(
true,
"main-window",
document.getElementById("downloadsHistory"),
false,
"back focus with downloads panel open"
);
await expectFocusOnF6(
true,
"main-window",
gURLBar.inputField,
false,
"back focus downloads panel open urlbar"
);
let downloadsPopup = document.getElementById("downloadsPanel");
let popupHiddenPromise = BrowserTestUtils.waitForEvent(
downloadsPopup,
"popuphidden",
true
);
downloadsPopup.hidePopup();
await popupHiddenPromise;
});
// Navigation with a contenteditable body
add_task(async function () {
await BrowserTestUtils.openNewForegroundTab(gBrowser, testPage3);
// The body should be focused when it is editable, not the root.
gURLBar.focus();
await expectFocusOnF6(
false,
"html3",
"body3",
true,
"focus with contenteditable body"
);
await expectFocusOnF6(
false,
"main-window",
gURLBar.inputField,
false,
"focus with contenteditable body urlbar"
);
// Now go backwards
await expectFocusOnF6(
false,
"html3",
"body3",
true,
"back focus with contenteditable body"
);
await expectFocusOnF6(
false,
"main-window",
gURLBar.inputField,
false,
"back focus with contenteditable body urlbar"
);
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
// Navigation with a frameset loaded
add_task(async function () {
await BrowserTestUtils.openNewForegroundTab(
gBrowser,
);
gURLBar.focus();
await expectFocusOnF6(
false,
"htmlframe1",
"htmlframe1",
true,
"focus on frameset frame 0"
);
await expectFocusOnF6(
false,
"htmlframe2",
"htmlframe2",
true,
"focus on frameset frame 1"
);
await expectFocusOnF6(
false,
"htmlframe3",
"htmlframe3",
true,
"focus on frameset frame 2"
);
await expectFocusOnF6(
false,
"htmlframe4",
"htmlframe4",
true,
"focus on frameset frame 3"
);
await expectFocusOnF6(
false,
"main-window",
gURLBar.inputField,
false,
"focus on frameset frame urlbar"
);
await expectFocusOnF6(
true,
"htmlframe4",
"htmlframe4",
true,
"back focus on frameset frame 3"
);
await expectFocusOnF6(
true,
"htmlframe3",
"htmlframe3",
true,
"back focus on frameset frame 2"
);
await expectFocusOnF6(
true,
"htmlframe2",
"htmlframe2",
true,
"back focus on frameset frame 1"
);
await expectFocusOnF6(
true,
"htmlframe1",
"htmlframe1",
true,
"back focus on frameset frame 0"
);
await expectFocusOnF6(
true,
"main-window",
gURLBar.inputField,
false,
"back focus on frameset frame urlbar"
);
BrowserTestUtils.removeTab(gBrowser.selectedTab);
});
// XXXndeakin add tests for browsers inside of panels
function promiseButtonShown(id) {
let dwu = window.windowUtils;
return TestUtils.waitForCondition(() => {
let target = document.getElementById(id);
let bounds = dwu.getBoundsWithoutFlushing(target);
return bounds.width > 0 && bounds.height > 0;
}, `Waiting for button ${id} to have non-0 size`);
}