// Opens another window and switches focus between them.
add_task(async function test_window_focus() {
let window2 = await BrowserTestUtils.openNewBrowserWindow();
ok(!document.hasFocus(), "hasFocus after open second window");
ok(window2.document.hasFocus(), "hasFocus after open second window");
is(
Services.focus.activeWindow,
window2,
"activeWindow after open second window"
);
is(
Services.focus.focusedWindow,
window2,
"focusedWindow after open second window"
);
await SimpleTest.promiseFocus(window);
ok(document.hasFocus(), "hasFocus after promiseFocus on window");
ok(!window2.document.hasFocus(), "hasFocus after promiseFocus on window");
is(
Services.focus.activeWindow,
window,
"activeWindow after promiseFocus on window"
);
is(
Services.focus.focusedWindow,
window,
"focusedWindow after promiseFocus on window"
);
await SimpleTest.promiseFocus(window2);
ok(!document.hasFocus(), "hasFocus after promiseFocus on second window");
ok(
window2.document.hasFocus(),
"hasFocus after promiseFocus on second window"
);
is(
Services.focus.activeWindow,
window2,
"activeWindow after promiseFocus on second window"
);
is(
Services.focus.focusedWindow,
window2,
"focusedWindow after promiseFocus on second window"
);
await BrowserTestUtils.closeWindow(window2);
// If the window is already focused, this should just return.
await SimpleTest.promiseFocus(window);
await SimpleTest.promiseFocus(window);
});
// Opens two tabs and ensures that focus can be switched to the browser.
add_task(async function test_tab_focus() {
let tab1 = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"data:text/html,"
);
let tab2 = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"data:text/html,"
);
gURLBar.focus();
await SimpleTest.promiseFocus(tab2.linkedBrowser);
is(
document.activeElement,
tab2.linkedBrowser,
"Browser is focused after promiseFocus"
);
await SpecialPowers.spawn(tab1.linkedBrowser, [], () => {
Assert.equal(
Services.focus.activeBrowsingContext,
null,
"activeBrowsingContext in child process in hidden tab"
);
Assert.equal(
Services.focus.focusedWindow,
null,
"focusedWindow in child process in hidden tab"
);
Assert.ok(
!content.document.hasFocus(),
"hasFocus in child process in hidden tab"
);
});
await SpecialPowers.spawn(tab2.linkedBrowser, [], () => {
Assert.equal(
Services.focus.activeBrowsingContext,
content.browsingContext,
"activeBrowsingContext in child process in visible tab"
);
Assert.equal(
Services.focus.focusedWindow,
content.window,
"focusedWindow in child process in visible tab"
);
Assert.ok(
content.document.hasFocus(),
"hasFocus in child process in visible tab"
);
});
BrowserTestUtils.removeTab(tab1);
BrowserTestUtils.removeTab(tab2);
});
// Opens a document with a nested hierarchy of frames using initChildFrames and
// focuses each child iframe in turn.
add_task(async function test_subframes_focus() {
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
OOP_BASE_PAGE_URI
);
const markup = "";
let browser = tab.linkedBrowser;
let browsingContexts = await initChildFrames(browser, markup);
for (let blurSubframe of [true, false]) {
for (let index = browsingContexts.length - 1; index >= 0; index--) {
let bc = browsingContexts[index];
// Focus each browsing context in turn. Do this twice, once when the window
// is not already focused, and once when it is already focused.
for (let step = 0; step < 2; step++) {
let desc =
"within child frame " +
index +
" step " +
step +
" blur subframe " +
blurSubframe +
" ";
info(desc + "start");
await SimpleTest.promiseFocus(bc, false, blurSubframe);
let expectedFocusedBC = bc;
// Becuase we are iterating backwards through the iframes, when we get to a frame
// that contains the iframe we just tested, focusing it will keep the child
// iframe focused as well, so we need to account for this when verifying which
// child iframe is focused. For the root frame (index 0), the iframe nested
// two items down will actually be focused.
// If blurSubframe is true however, the iframe focus in the parent will be cleared,
// so the focused window should be the parent instead.
if (!blurSubframe) {
if (index == 0) {
expectedFocusedBC = browsingContexts[index + 2];
} else if (index == 3 || index == 1) {
expectedFocusedBC = browsingContexts[index + 1];
}
}
is(
Services.focus.focusedContentBrowsingContext,
expectedFocusedBC,
desc +
" focusedContentBrowsingContext" +
":: " +
Services.focus.focusedContentBrowsingContext?.id +
"," +
expectedFocusedBC?.id
);
// If the processes don't match, then the child iframe is an out-of-process iframe.
let oop =
expectedFocusedBC.currentWindowGlobal.osPid !=
bc.currentWindowGlobal.osPid;
await SpecialPowers.spawn(
bc,
[
index,
desc,
expectedFocusedBC != bc ? expectedFocusedBC : null,
oop,
],
(num, descChild, childBC, isOop) => {
Assert.equal(
Services.focus.activeBrowsingContext,
content.browsingContext.top,
descChild + "activeBrowsingContext"
);
Assert.ok(
content.document.hasFocus(),
descChild + "hasFocus: " + content.browsingContext.id
);
// If a child browsing context is expected to be focused, the focusedWindow
// should be set to that instead and the active element should be an iframe.
// Otherwise, the focused window should be this window, and the active
// element should be the document's body element.
if (childBC) {
// The frame structure is:
// A1
// -> B
// -> A2
// where A and B are two processes. The frame A2 starts out focused. When B is
// focused, A1's focus is updated correctly.
// In Fission mode, childBC.window returns a non-null proxy even if OOP
if (isOop) {
Assert.equal(
Services.focus.focusedWindow,
null,
descChild + "focusedWindow"
);
Assert.ok(!childBC.docShell, descChild + "childBC.docShell");
} else {
Assert.equal(
Services.focus.focusedWindow,
childBC.window,
descChild + "focusedWindow"
);
}
Assert.equal(
content.document.activeElement.localName,
"iframe",
descChild + "activeElement"
);
} else {
Assert.equal(
Services.focus.focusedWindow,
content.window,
descChild + "focusedWindow"
);
Assert.equal(
content.document.activeElement,
content.document.body,
descChild + "activeElement"
);
}
}
);
}
}
}
// Focus the top window without blurring the browser.
await SimpleTest.promiseFocus(window, false, false);
is(
document.activeElement.localName,
"browser",
"focus after blurring browser blur subframe false"
);
// Now, focus the top window, blurring the browser.
await SimpleTest.promiseFocus(window, false, true);
is(
document.activeElement,
document.body,
"focus after blurring browser blur subframe true"
);
BrowserTestUtils.removeTab(tab);
});