/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Tests that the suppress-focus-border attribute is applied to the Urlbar * correctly. Its purpose is to hide the focus border after the panel is closed. * It also ensures we don't flash the border at the user after they click the * Urlbar but before we decide we're opening the view. */ let TEST_RESULT = new UrlbarResult( UrlbarUtils.RESULT_TYPE.URL, UrlbarUtils.RESULT_SOURCE.HISTORY, { url: "http://mozilla.org/" } ); /** * A test provider that awaits a promise before returning results. */ class AwaitPromiseProvider extends UrlbarTestUtils.TestProvider { /** * @param {object} args * The constructor arguments for UrlbarTestUtils.TestProvider. * @param {Promise} promise * The promise that will be awaited before returning results. */ constructor(args, promise) { super(args); this._promise = promise; } async startQuery(context, add) { await this._promise; for (let result of this._results) { add(this, result); } } } add_setup(async function () { await SearchTestUtils.installSearchExtension({}, { setAsDefault: true }); registerCleanupFunction(function () { SpecialPowers.clipboardCopyString(""); }); }); add_task(async function afterMousedown_topSites() { const win = await BrowserTestUtils.openNewBrowserWindow(); win.gURLBar.blur(); await withAwaitProvider( { results: [TEST_RESULT], priority: Infinity }, getSuppressFocusPromise(win), async () => { Assert.ok( !win.gURLBar.hasAttribute("suppress-focus-border"), "Sanity check: the Urlbar does not have the supress-focus-border attribute." ); await UrlbarTestUtils.promisePopupOpen(win, () => { if (win.gURLBar.getAttribute("pageproxystate") == "invalid") { gURLBar.handleRevert(); } EventUtils.synthesizeMouseAtCenter(win.gURLBar.inputField, {}, win); }); let result = await UrlbarTestUtils.waitForAutocompleteResultAt(win, 0); Assert.ok( result, "The provider returned a result after waiting for the suppress-focus-border attribute." ); await UrlbarTestUtils.promisePopupClose(win); Assert.ok( !gURLBar.hasAttribute("suppress-focus-border"), "The Urlbar no longer has the supress-focus-border attribute after close." ); } ); await BrowserTestUtils.closeWindow(win); }); add_task(async function openLocation_topSites() { const win = await BrowserTestUtils.openNewBrowserWindow(); await withAwaitProvider( { results: [TEST_RESULT], priority: Infinity }, getSuppressFocusPromise(win), async () => { Assert.ok( !win.gURLBar.hasAttribute("suppress-focus-border"), "Sanity check: the Urlbar does not have the supress-focus-border attribute." ); await UrlbarTestUtils.promisePopupOpen(win, () => { EventUtils.synthesizeKey("l", { accelKey: true }, win); }); let result = await UrlbarTestUtils.waitForAutocompleteResultAt(win, 0); Assert.ok( result, "The provider returned a result after waiting for the suppress-focus-border attribute." ); await UrlbarTestUtils.promisePopupClose(win); Assert.ok( !win.gURLBar.hasAttribute("suppress-focus-border"), "The Urlbar no longer has the supress-focus-border attribute after close." ); } ); await BrowserTestUtils.closeWindow(win); }); // Tests that the address bar loses the suppress-focus-border attribute if no // results are returned by a query. This simulates the user disabling Top Sites // then clicking the address bar. add_task(async function afterMousedown_noTopSites() { const win = await BrowserTestUtils.openNewBrowserWindow(); await withAwaitProvider( // Note that the provider returns no results. { results: [], priority: Infinity }, getSuppressFocusPromise(win), async () => { Assert.ok( !win.gURLBar.hasAttribute("suppress-focus-border"), "Sanity check: the Urlbar does not have the supress-focus-border attribute." ); EventUtils.synthesizeMouseAtCenter(win.gURLBar.inputField, {}, win); // Because the panel opening may not be immediate, we must wait a bit. // eslint-disable-next-line mozilla/no-arbitrary-setTimeout await new Promise(resolve => setTimeout(resolve, 500)); Assert.ok(!UrlbarTestUtils.isPopupOpen(win), "The popup is not open."); Assert.ok( !win.gURLBar.hasAttribute("suppress-focus-border"), "The Urlbar no longer has the supress-focus-border attribute." ); } ); await BrowserTestUtils.closeWindow(win); }); // Tests that we show the focus border when new tabs are opened. add_task(async function newTab() { const win = await BrowserTestUtils.openNewBrowserWindow(); // Tabs opened with withNewTab don't focus the Urlbar, so we have to open one // manually. let tab = await openAboutNewTab(win); await BrowserTestUtils.waitForCondition( () => win.gURLBar.hasAttribute("focused"), "Waiting for the Urlbar to become focused." ); Assert.ok( !win.gURLBar.hasAttribute( "suppress-focus-border", "The Urlbar does not have the suppress-focus-border attribute." ) ); BrowserTestUtils.removeTab(tab); await BrowserTestUtils.closeWindow(win); }); // Tests that we show the focus border when a new tab is opened and the address // bar panel is already open. add_task(async function newTab_alreadyOpen() { const win = await BrowserTestUtils.openNewBrowserWindow(); await withAwaitProvider( { results: [TEST_RESULT], priority: Infinity }, getSuppressFocusPromise(win), async () => { await UrlbarTestUtils.promisePopupOpen(win, () => { EventUtils.synthesizeKey("l", { accelKey: true }, win); }); let tab = await openAboutNewTab(win); await BrowserTestUtils.waitForCondition( () => !UrlbarTestUtils.isPopupOpen(win), "Waiting for the Urlbar panel to close." ); Assert.ok( !win.gURLBar.hasAttribute( "suppress-focus-border", "The Urlbar does not have the suppress-focus-border attribute." ) ); BrowserTestUtils.removeTab(tab); } ); await BrowserTestUtils.closeWindow(win); }); add_task(async function searchTip() { const win = await BrowserTestUtils.openNewBrowserWindow(); info("Set a pref to show a search tip button."); await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.searchTips.test.ignoreShowLimits", true]], }); info("Open new tab."); const tab = await openAboutNewTab(win); info("Click the tip button."); const result = await UrlbarTestUtils.getDetailsOfResultAt(win, 0); const button = result.element.row._buttons.get("0"); await UrlbarTestUtils.promisePopupClose(win, () => { EventUtils.synthesizeMouseAtCenter(button, {}, win); }); Assert.ok( !win.gURLBar.hasAttribute( "suppress-focus-border", "The Urlbar does not have the suppress-focus-border attribute." ) ); BrowserTestUtils.removeTab(tab); await BrowserTestUtils.closeWindow(win); await SpecialPowers.popPrefEnv(); }); add_task(async function interactionOnNewTab() { const win = await BrowserTestUtils.openNewBrowserWindow(); info("Open about:newtab in new tab"); const tab = await openAboutNewTab(win); await BrowserTestUtils.waitForCondition( () => win.gBrowser.selectedTab === tab ); await testInteractionsOnAboutNewTab(win); BrowserTestUtils.removeTab(tab); await BrowserTestUtils.closeWindow(win); }); add_task(async function interactionOnNewTabInPrivateWindow() { const win = await BrowserTestUtils.openNewBrowserWindow({ private: true, waitForTabURL: "about:privatebrowsing", }); await testInteractionsOnAboutNewTab(win); await BrowserTestUtils.closeWindow(win); await SimpleTest.promiseFocus(window); }); add_task(async function clickOnEdgeOfURLBar() { const win = await BrowserTestUtils.openNewBrowserWindow(); win.gURLBar.blur(); Assert.ok( !win.gURLBar.hasAttribute("suppress-focus-border"), "URLBar does not have suppress-focus-border attribute" ); const onHiddenFocusRemoved = BrowserTestUtils.waitForCondition( () => !win.gURLBar._hideFocus ); const container = win.document.getElementById("urlbar-input-container"); container.click(); await onHiddenFocusRemoved; Assert.ok( win.gURLBar.hasAttribute("suppress-focus-border"), "suppress-focus-border is set from the beginning" ); await UrlbarTestUtils.promisePopupClose(win.window); await BrowserTestUtils.closeWindow(win); }); async function testInteractionsOnAboutNewTab(win) { info("Test for clicking on URLBar while showing about:newtab"); await testInteractionFeature(() => { info("Click on URLBar"); EventUtils.synthesizeMouseAtCenter(win.gURLBar.inputField, {}, win); }, win); info("Test for typing on .fake-editable while showing about:newtab"); await testInteractionFeature(() => { info("Type a character on .fake-editable"); EventUtils.synthesizeKey("v", {}, win); }, win); Assert.equal(win.gURLBar.value, "v", "URLBar value is correct"); info("Test for typing on .fake-editable while showing about:newtab"); await testInteractionFeature(() => { info("Paste some words on .fake-editable"); SpecialPowers.clipboardCopyString("paste test"); win.document.commandDispatcher .getControllerForCommand("cmd_paste") .doCommand("cmd_paste"); SpecialPowers.clipboardCopyString(""); }, win); Assert.equal(win.gURLBar.value, "paste test", "URLBar value is correct"); } async function testInteractionFeature(interaction, win) { info("Focus on URLBar"); win.gURLBar.value = ""; win.gURLBar.focus(); Assert.ok( !win.gURLBar.hasAttribute("suppress-focus-border"), "URLBar does not have suppress-focus-border attribute" ); info("Click on search-handoff-button in newtab page"); await ContentTask.spawn(win.gBrowser.selectedBrowser, null, async () => { await ContentTaskUtils.waitForCondition(() => content.document.querySelector(".search-handoff-button") ); content.document.querySelector(".search-handoff-button").click(); }); await BrowserTestUtils.waitForCondition( () => win.gURLBar._hideFocus, "Wait until _hideFocus will be true" ); const onHiddenFocusRemoved = BrowserTestUtils.waitForCondition( () => !win.gURLBar._hideFocus ); await interaction(); await onHiddenFocusRemoved; Assert.ok( win.gURLBar.hasAttribute("suppress-focus-border"), "suppress-focus-border is set from the beginning" ); const result = await UrlbarTestUtils.waitForAutocompleteResultAt(win, 0); Assert.ok(result, "The provider returned a result"); await UrlbarTestUtils.promisePopupClose(win); } function getSuppressFocusPromise(win = window) { return new Promise(resolve => { let observer = new MutationObserver(() => { if ( win.gURLBar.hasAttribute("suppress-focus-border") && !UrlbarTestUtils.isPopupOpen(win) ) { resolve(); observer.disconnect(); } }); observer.observe(win.gURLBar.textbox, { attributes: true, attributeFilter: ["suppress-focus-border"], }); }); } async function withAwaitProvider(args, promise, callback) { let provider = new AwaitPromiseProvider(args, promise); UrlbarProvidersManager.registerProvider(provider); try { await callback(); } catch (ex) { console.error(ex); } finally { UrlbarProvidersManager.unregisterProvider(provider); } } async function openAboutNewTab(win = window) { // We have to listen for the new tab using this brute force method. // about:newtab is preloaded in the background. When about:newtab is opened, // the cached version is shown. Since the page is already loaded, // waitForNewTab does not detect it. It also doesn't fire the TabOpen event. const tabCount = win.gBrowser.tabs.length; EventUtils.synthesizeKey("t", { accelKey: true }, win); await TestUtils.waitForCondition( () => win.gBrowser.tabs.length === tabCount + 1, "Waiting for background about:newtab to open." ); return win.gBrowser.tabs[win.gBrowser.tabs.length - 1]; }