diff options
Diffstat (limited to 'browser/base/content/test/outOfProcess/browser_promisefocus.js')
-rw-r--r-- | browser/base/content/test/outOfProcess/browser_promisefocus.js | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/browser/base/content/test/outOfProcess/browser_promisefocus.js b/browser/base/content/test/outOfProcess/browser_promisefocus.js new file mode 100644 index 0000000000..9018c0f0ae --- /dev/null +++ b/browser/base/content/test/outOfProcess/browser_promisefocus.js @@ -0,0 +1,262 @@ +// 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,<input>" + ); + + let tab2 = await BrowserTestUtils.openNewForegroundTab( + gBrowser, + "data:text/html,<input>" + ); + + 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 = "<input>"; + + 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); +}); |