diff options
Diffstat (limited to 'browser/base/content/test/general/browser_tabfocus.js')
-rw-r--r-- | browser/base/content/test/general/browser_tabfocus.js | 565 |
1 files changed, 0 insertions, 565 deletions
diff --git a/browser/base/content/test/general/browser_tabfocus.js b/browser/base/content/test/general/browser_tabfocus.js deleted file mode 100644 index 4042421e8..000000000 --- a/browser/base/content/test/general/browser_tabfocus.js +++ /dev/null @@ -1,565 +0,0 @@ -/* - * This test checks that focus is adjusted properly when switching tabs. - */ - -var testPage1 = "<html id='html1'><body id='body1'><button id='button1'>Tab 1</button></body></html>"; -var testPage2 = "<html id='html2'><body id='body2'><button id='button2'>Tab 2</button></body></html>"; -var testPage3 = "<html id='html3'><body id='body3'><button id='button3'>Tab 3</button></body></html>"; - -const fm = Services.focus; - -function EventStore() { - this["main-window"] = []; - this["window1"] = []; - this["window2"] = []; -} - -EventStore.prototype = { - "push": function (event) { - if (event.indexOf("1") > -1) { - this["window1"].push(event); - } else if (event.indexOf("2") > -1) { - this["window2"].push(event); - } else { - this["main-window"].push(event); - } - } -} - -var tab1 = null; -var tab2 = null; -var browser1 = null; -var browser2 = null; -var _lastfocus; -var _lastfocuswindow = null; -var actualEvents = new EventStore(); -var expectedEvents = new EventStore(); -var currentTestName = ""; -var _expectedElement = null; -var _expectedWindow = null; - -var currentPromiseResolver = null; - -function* getFocusedElementForBrowser(browser, dontCheckExtraFocus = false) -{ - if (gMultiProcessBrowser) { - return new Promise((resolve, reject) => { - messageManager.addMessageListener("Browser:GetCurrentFocus", function getCurrentFocus(message) { - messageManager.removeMessageListener("Browser:GetCurrentFocus", getCurrentFocus); - resolve(message.data.details); - }); - - // The dontCheckExtraFocus flag is used to indicate not to check some - // additional focus related properties. This is needed as both URLs are - // loaded using the same child process and share focus managers. - browser.messageManager.sendAsyncMessage("Browser:GetFocusedElement", - { dontCheckExtraFocus : dontCheckExtraFocus }); - }); - } - var focusedWindow = {}; - var node = fm.getFocusedElementForWindow(browser.contentWindow, false, focusedWindow); - return "Focus is " + (node ? node.id : "<none>"); -} - -function focusInChild() -{ - var contentFM = Components.classes["@mozilla.org/focus-manager;1"]. - getService(Components.interfaces.nsIFocusManager); - - function getWindowDocId(target) - { - return (String(target.location).indexOf("1") >= 0) ? "window1" : "window2"; - } - - function eventListener(event) { - var id; - if (event.target instanceof Components.interfaces.nsIDOMWindow) - id = getWindowDocId(event.originalTarget) + "-window"; - else if (event.target instanceof Components.interfaces.nsIDOMDocument) - id = getWindowDocId(event.originalTarget) + "-document"; - else - id = event.originalTarget.id; - sendSyncMessage("Browser:FocusChanged", { details : event.type + ": " + id }); - } - - addEventListener("focus", eventListener, true); - addEventListener("blur", eventListener, true); - - addMessageListener("Browser:ChangeFocus", function changeFocus(message) { - content.document.getElementById(message.data.id)[message.data.type](); - }); - - addMessageListener("Browser:GetFocusedElement", function getFocusedElement(message) { - var focusedWindow = {}; - var node = contentFM.getFocusedElementForWindow(content, false, focusedWindow); - var details = "Focus is " + (node ? node.id : "<none>"); - - /* Check focus manager properties. Add an error onto the string if they are - not what is expected which will cause matching to fail in the parent process. */ - let doc = content.document; - if (!message.data.dontCheckExtraFocus) { - if (contentFM.focusedElement != node) { - details += "<ERROR: focusedElement doesn't match>"; - } - if (contentFM.focusedWindow && contentFM.focusedWindow != content) { - details += "<ERROR: focusedWindow doesn't match>"; - } - if ((contentFM.focusedWindow == content) != doc.hasFocus()) { - details += "<ERROR: child hasFocus() is not correct>"; - } - if ((contentFM.focusedElement && doc.activeElement != contentFM.focusedElement) || - (!contentFM.focusedElement && doc.activeElement != doc.body)) { - details += "<ERROR: child activeElement is not correct>"; - } - } - - sendSyncMessage("Browser:GetCurrentFocus", { details : details }); - }); -} - -function focusElementInChild(elementid, type) -{ - let browser = (elementid.indexOf("1") >= 0) ? browser1 : browser2; - if (gMultiProcessBrowser) { - browser.messageManager.sendAsyncMessage("Browser:ChangeFocus", - { id: elementid, type: type }); - } - else { - browser.contentDocument.getElementById(elementid)[type](); - } -} - -add_task(function*() { - tab1 = gBrowser.addTab(); - browser1 = gBrowser.getBrowserForTab(tab1); - - tab2 = gBrowser.addTab(); - browser2 = gBrowser.getBrowserForTab(tab2); - - yield promiseTabLoadEvent(tab1, "data:text/html," + escape(testPage1)); - yield promiseTabLoadEvent(tab2, "data:text/html," + escape(testPage2)); - - var childFocusScript = "data:,(" + focusInChild.toString() + ")();"; - browser1.messageManager.loadFrameScript(childFocusScript, true); - browser2.messageManager.loadFrameScript(childFocusScript, true); - - gURLBar.focus(); - yield SimpleTest.promiseFocus(); - - if (gMultiProcessBrowser) { - messageManager.addMessageListener("Browser:FocusChanged", message => { - actualEvents.push(message.data.details); - compareFocusResults(); - }); - } - - _lastfocus = "urlbar"; - _lastfocuswindow = "main-window"; - - window.addEventListener("focus", _browser_tabfocus_test_eventOccured, true); - window.addEventListener("blur", _browser_tabfocus_test_eventOccured, true); - - // make sure that the focus initially starts out blank - var focusedWindow = {}; - - let focused = yield getFocusedElementForBrowser(browser1); - is(focused, "Focus is <none>", "initial focus in tab 1"); - - focused = yield getFocusedElementForBrowser(browser2); - is(focused, "Focus is <none>", "initial focus in tab 2"); - - is(document.activeElement, gURLBar.inputField, "focus after loading two tabs"); - - yield* expectFocusShiftAfterTabSwitch(tab2, "window2", null, true, - "after tab change, focus in new tab"); - - focused = yield getFocusedElementForBrowser(browser2); - is(focused, "Focus is <none>", "focusedElement after tab change, focus in new tab"); - - // switching tabs when nothing in the new tab is focused - // should focus the browser - yield* expectFocusShiftAfterTabSwitch(tab1, "window1", null, true, - "after tab change, focus in original tab"); - - focused = yield getFocusedElementForBrowser(browser1); - is(focused, "Focus is <none>", "focusedElement after tab change, focus in original tab"); - - // focusing a button in the current tab should focus it - yield expectFocusShift(() => focusElementInChild("button1", "focus"), - "window1", "button1", true, - "after button focused"); - - focused = yield getFocusedElementForBrowser(browser1); - is(focused, "Focus is button1", "focusedElement in first browser after button focused"); - - // focusing a button in a background tab should not change the actual - // focus, but should set the focus that would be in that background tab to - // that button. - yield expectFocusShift(() => focusElementInChild("button2", "focus"), - "window1", "button1", false, - "after button focus in unfocused tab"); - - focused = yield getFocusedElementForBrowser(browser1, false); - is(focused, "Focus is button1", "focusedElement in first browser after button focus in unfocused tab"); - focused = yield getFocusedElementForBrowser(browser2, true); - is(focused, "Focus is button2", "focusedElement in second browser after button focus in unfocused tab"); - - // switching tabs should now make the button in the other tab focused - yield* expectFocusShiftAfterTabSwitch(tab2, "window2", "button2", true, - "after tab change with button focused"); - - // blurring an element in a background tab should not change the active - // focus, but should clear the focus in that tab. - yield expectFocusShift(() => focusElementInChild("button1", "blur"), - "window2", "button2", false, - "focusedWindow after blur in unfocused tab"); - - focused = yield getFocusedElementForBrowser(browser1, true); - is(focused, "Focus is <none>", "focusedElement in first browser after focus in unfocused tab"); - focused = yield getFocusedElementForBrowser(browser2, false); - is(focused, "Focus is button2", "focusedElement in second browser after focus in unfocused tab"); - - // When focus is in the tab bar, it should be retained there - yield expectFocusShift(() => gBrowser.selectedTab.focus(), - "main-window", "tab2", true, - "focusing tab element"); - yield* expectFocusShiftAfterTabSwitch(tab1, "main-window", "tab1", true, - "tab change when selected tab element was focused"); - - let switchWaiter; - if (gMultiProcessBrowser) { - switchWaiter = new Promise((resolve, reject) => { - gBrowser.addEventListener("TabSwitchDone", function listener() { - gBrowser.removeEventListener("TabSwitchDone", listener); - executeSoon(resolve); - }); - }); - } - - yield* expectFocusShiftAfterTabSwitch(tab2, "main-window", "tab2", true, - "another tab change when selected tab element was focused"); - - // When this a remote browser, wait for the paint on the second browser so that - // any post tab-switching stuff has time to complete before blurring the tab. - // Otherwise, the _adjustFocusAfterTabSwitch in tabbrowser gets confused and - // isn't sure what tab is really focused. - if (gMultiProcessBrowser) { - yield switchWaiter; - } - - yield expectFocusShift(() => gBrowser.selectedTab.blur(), - "main-window", null, true, - "blurring tab element"); - - // focusing the url field should switch active focus away from the browser but - // not clear what would be the focus in the browser - focusElementInChild("button1", "focus"); - - yield expectFocusShift(() => gURLBar.focus(), - "main-window", "urlbar", true, - "focusedWindow after url field focused"); - focused = yield getFocusedElementForBrowser(browser1, true); - is(focused, "Focus is button1", "focusedElement after url field focused, first browser"); - focused = yield getFocusedElementForBrowser(browser2, true); - is(focused, "Focus is button2", "focusedElement after url field focused, second browser"); - - yield expectFocusShift(() => gURLBar.blur(), - "main-window", null, true, - "blurring url field"); - - // when a chrome element is focused, switching tabs to a tab with a button - // with the current focus should focus the button - yield* expectFocusShiftAfterTabSwitch(tab1, "window1", "button1", true, - "after tab change, focus in url field, button focused in new tab"); - - focused = yield getFocusedElementForBrowser(browser1, false); - is(focused, "Focus is button1", "after switch tab, focus in unfocused tab, first browser"); - focused = yield getFocusedElementForBrowser(browser2, true); - is(focused, "Focus is button2", "after switch tab, focus in unfocused tab, second browser"); - - // blurring an element in the current tab should clear the active focus - yield expectFocusShift(() => focusElementInChild("button1", "blur"), - "window1", null, true, - "after blur in focused tab"); - - focused = yield getFocusedElementForBrowser(browser1, false); - is(focused, "Focus is <none>", "focusedWindow after blur in focused tab, child"); - focusedWindow = {}; - is(fm.getFocusedElementForWindow(window, false, focusedWindow), browser1, "focusedElement after blur in focused tab, parent"); - - // blurring an non-focused url field should have no effect - yield expectFocusShift(() => gURLBar.blur(), - "window1", null, false, - "after blur in unfocused url field"); - - focusedWindow = {}; - is(fm.getFocusedElementForWindow(window, false, focusedWindow), browser1, "focusedElement after blur in unfocused url field"); - - // switch focus to a tab with a currently focused element - yield* expectFocusShiftAfterTabSwitch(tab2, "window2", "button2", true, - "after switch from unfocused to focused tab"); - focused = yield getFocusedElementForBrowser(browser2, true); - is(focused, "Focus is button2", "focusedElement after switch from unfocused to focused tab"); - - // clearing focus on the chrome window should switch the focus to the - // chrome window - yield expectFocusShift(() => fm.clearFocus(window), - "main-window", null, true, - "after switch to chrome with no focused element"); - - focusedWindow = {}; - is(fm.getFocusedElementForWindow(window, false, focusedWindow), null, "focusedElement after switch to chrome with no focused element"); - - // switch focus to another tab when neither have an active focus - yield* expectFocusShiftAfterTabSwitch(tab1, "window1", null, true, - "focusedWindow after tab switch from no focus to no focus"); - - focused = yield getFocusedElementForBrowser(browser1, false); - is(focused, "Focus is <none>", "after tab switch from no focus to no focus, first browser"); - focused = yield getFocusedElementForBrowser(browser2, true); - is(focused, "Focus is button2", "after tab switch from no focus to no focus, second browser"); - - // next, check whether navigating forward, focusing the urlbar and then - // navigating back maintains the focus in the urlbar. - yield expectFocusShift(() => focusElementInChild("button1", "focus"), - "window1", "button1", true, - "focus button"); - - yield promiseTabLoadEvent(tab1, "data:text/html," + escape(testPage3)); - - // now go back again - gURLBar.focus(); - - yield new Promise((resolve, reject) => { - window.addEventListener("pageshow", function navigationOccured(event) { - window.removeEventListener("pageshow", navigationOccured, true); - resolve(); - }, true); - document.getElementById('Browser:Back').doCommand(); - }); - - is(window.document.activeElement, gURLBar.inputField, "urlbar still focused after navigating back"); - - // Document navigation with F6 does not yet work in mutli-process browsers. - if (!gMultiProcessBrowser) { - gURLBar.focus(); - actualEvents = new EventStore(); - _lastfocus = "urlbar"; - _lastfocuswindow = "main-window"; - - yield expectFocusShift(() => EventUtils.synthesizeKey("VK_F6", { }), - "window1", "html1", - true, "switch document forward with f6"); - - EventUtils.synthesizeKey("VK_F6", { }); - is(fm.focusedWindow, window, "switch document forward again with f6"); - - browser1.style.MozUserFocus = "ignore"; - browser1.clientWidth; - EventUtils.synthesizeKey("VK_F6", { }); - is(fm.focusedWindow, window, "switch document forward again with f6 when browser non-focusable"); - - browser1.style.MozUserFocus = "normal"; - browser1.clientWidth; - } - - window.removeEventListener("focus", _browser_tabfocus_test_eventOccured, true); - window.removeEventListener("blur", _browser_tabfocus_test_eventOccured, true); - - gBrowser.removeCurrentTab(); - gBrowser.removeCurrentTab(); - - finish(); -}); - -function _browser_tabfocus_test_eventOccured(event) -{ - function getWindowDocId(target) - { - if (target == browser1.contentWindow || target == browser1.contentDocument) { - return "window1"; - } - if (target == browser2.contentWindow || target == browser2.contentDocument) { - return "window2"; - } - return "main-window"; - } - - var id; - - // Some focus events from the child bubble up? Ignore them. - if (Cu.isCrossProcessWrapper(event.originalTarget)) - return; - - if (event.target instanceof Window) - id = getWindowDocId(event.originalTarget) + "-window"; - else if (event.target instanceof Document) - id = getWindowDocId(event.originalTarget) + "-document"; - else if (event.target.id == "urlbar" && event.originalTarget.localName == "input") - id = "urlbar"; - else if (event.originalTarget.localName == "browser") - id = (event.originalTarget == browser1) ? "browser1" : "browser2"; - else if (event.originalTarget.localName == "tab") - id = (event.originalTarget == tab1) ? "tab1" : "tab2"; - else - id = event.originalTarget.id; - - actualEvents.push(event.type + ": " + id); - compareFocusResults(); -} - -function getId(element) -{ - if (!element) { - return null; - } - - if (element.localName == "browser") { - return element == browser1 ? "browser1" : "browser2"; - } - - if (element.localName == "tab") { - return element == tab1 ? "tab1" : "tab2"; - } - - return (element.localName == "input") ? "urlbar" : element.id; -} - -function compareFocusResults() -{ - if (!currentPromiseResolver) - return; - - let winIds = ["main-window", "window1", "window2"]; - - for (let winId of winIds) { - if (actualEvents[winId].length < expectedEvents[winId].length) - return; - } - - for (let winId of winIds) { - for (let e = 0; e < expectedEvents.length; e++) { - is(actualEvents[winId][e], expectedEvents[winId][e], currentTestName + " events [event " + e + "]"); - } - actualEvents[winId] = []; - } - - // Use executeSoon as this will be called during a focus/blur event handler - executeSoon(() => { - let matchWindow = window; - if (gMultiProcessBrowser) { - is(_expectedWindow, "main-window", "main-window is always expected"); - } - else if (_expectedWindow != "main-window") { - matchWindow = (_expectedWindow == "window1" ? browser1.contentWindow : browser2.contentWindow); - } - - var focusedElement = fm.focusedElement; - is(getId(focusedElement), _expectedElement, currentTestName + " focusedElement"); - is(fm.focusedWindow, matchWindow, currentTestName + " focusedWindow"); - var focusedWindow = {}; - is(getId(fm.getFocusedElementForWindow(matchWindow, false, focusedWindow)), - _expectedElement, currentTestName + " getFocusedElementForWindow"); - is(focusedWindow.value, matchWindow, currentTestName + " getFocusedElementForWindow frame"); - is(matchWindow.document.hasFocus(), true, currentTestName + " hasFocus"); - var expectedActive = _expectedElement; - if (!expectedActive) { - expectedActive = matchWindow.document instanceof XULDocument ? - "main-window" : getId(matchWindow.document.body); - } - is(getId(matchWindow.document.activeElement), expectedActive, currentTestName + " activeElement"); - - currentPromiseResolver(); - currentPromiseResolver = null; - }); -} - -function* expectFocusShiftAfterTabSwitch(tab, expectedWindow, expectedElement, focusChanged, testid) -{ - let tabSwitchPromise = null; - yield expectFocusShift(() => { tabSwitchPromise = BrowserTestUtils.switchTab(gBrowser, tab) }, - expectedWindow, expectedElement, focusChanged, testid) - yield tabSwitchPromise; -} - -function* expectFocusShift(callback, expectedWindow, expectedElement, focusChanged, testid) -{ - currentPromiseResolver = null; - currentTestName = testid; - - expectedEvents = new EventStore(); - - if (focusChanged) { - _expectedElement = expectedElement; - _expectedWindow = expectedWindow; - - // When the content is in a child process, the expected element in the chrome window - // will always be the urlbar or a browser element. - if (gMultiProcessBrowser) { - if (_expectedWindow == "window1") { - _expectedElement = "browser1"; - } - else if (_expectedWindow == "window2") { - _expectedElement = "browser2"; - } - _expectedWindow = "main-window"; - } - - if (gMultiProcessBrowser && _lastfocuswindow != "main-window" && - _lastfocuswindow != expectedWindow) { - let browserid = _lastfocuswindow == "window1" ? "browser1" : "browser2"; - expectedEvents.push("blur: " + browserid); - } - - var newElementIsFocused = (expectedElement && !expectedElement.startsWith("html")); - if (newElementIsFocused && gMultiProcessBrowser && - _lastfocuswindow != "main-window" && - expectedWindow == "main-window") { - // When switching from a child to a chrome element, the focus on the element will arrive first. - expectedEvents.push("focus: " + expectedElement); - newElementIsFocused = false; - } - - if (_lastfocus && _lastfocus != _expectedElement) - expectedEvents.push("blur: " + _lastfocus); - - if (_lastfocuswindow && - _lastfocuswindow != expectedWindow) { - - if (!gMultiProcessBrowser || _lastfocuswindow != "main-window") { - expectedEvents.push("blur: " + _lastfocuswindow + "-document"); - expectedEvents.push("blur: " + _lastfocuswindow + "-window"); - } - } - - if (expectedWindow && _lastfocuswindow != expectedWindow) { - if (gMultiProcessBrowser && expectedWindow != "main-window") { - let browserid = expectedWindow == "window1" ? "browser1" : "browser2"; - expectedEvents.push("focus: " + browserid); - } - - if (!gMultiProcessBrowser || expectedWindow != "main-window") { - expectedEvents.push("focus: " + expectedWindow + "-document"); - expectedEvents.push("focus: " + expectedWindow + "-window"); - } - } - - if (newElementIsFocused) { - expectedEvents.push("focus: " + expectedElement); - } - - _lastfocus = expectedElement; - _lastfocuswindow = expectedWindow; - } - - return new Promise((resolve, reject) => { - currentPromiseResolver = resolve; - callback(); - - // No events are expected, so resolve the promise immediately. - if (expectedEvents["main-window"].length + expectedEvents["window1"].length + expectedEvents["window2"].length == 0) { - currentPromiseResolver(); - currentPromiseResolver = null; - } - }); -} |