/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; ChromeUtils.defineESModuleGetters(this, { UrlbarProvider: "resource:///modules/UrlbarUtils.sys.mjs", UrlbarProvidersManager: "resource:///modules/UrlbarProvidersManager.sys.mjs", UrlbarUtils: "resource:///modules/UrlbarUtils.sys.mjs", }); const TEST_ENGINE_NAME = "Test"; const TEST_ENGINE_ALIAS = "@test"; const TEST_ENGINE_DOMAIN = "example.com"; // This test has many subtests and can time out in verify mode. requestLongerTimeout(5); // Each test is a function that executes an urlbar action and returns the // expected event object. const tests = [ async function (win) { info("Type something, press Enter."); win.gURLBar.select(); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "x", fireInputEvent: true, }); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "1", numWords: "1", selIndex: "0", selType: "searchengine", provider: "HeuristicFallback", }, }; }, async function (win) { info("Type a multi-word query, press Enter."); win.gURLBar.select(); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "multi word query ", fireInputEvent: true, }); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "17", numWords: "3", selIndex: "0", selType: "searchengine", provider: "HeuristicFallback", }, }; }, async function (win) { info("Paste something, press Enter."); win.gURLBar.select(); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await SimpleTest.promiseClipboardChange("test", () => { clipboardHelper.copyString("test"); }); win.document.commandDispatcher .getControllerForCommand("cmd_paste") .doCommand("cmd_paste"); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "pasted", extra: { elapsed: val => parseInt(val) > 0, numChars: "4", numWords: "1", selIndex: "0", selType: "searchengine", provider: "HeuristicFallback", }, }; }, async function (win) { info("Type something, click one-off and press enter."); win.gURLBar.select(); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "test", fireInputEvent: true, }); let searchPromise = UrlbarTestUtils.promiseSearchComplete(win); EventUtils.synthesizeKey("KEY_ArrowDown", { altKey: true }, win); let selectedOneOff = UrlbarTestUtils.getOneOffSearchButtons(win).selectedButton; selectedOneOff.click(); await searchPromise; await UrlbarTestUtils.assertSearchMode(win, { engineName: selectedOneOff.engine.name, entry: "oneoff", }); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "4", numWords: "1", selIndex: "0", selType: "searchengine", provider: "HeuristicFallback", }, }; }, async function (win) { info( "Type something, select one-off with enter, and select result with enter." ); win.gURLBar.select(); let searchPromise = UrlbarTestUtils.promiseSearchComplete(win); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "test", fireInputEvent: true, }); EventUtils.synthesizeKey("KEY_ArrowDown", { altKey: true }, win); let selectedOneOff = UrlbarTestUtils.getOneOffSearchButtons(win).selectedButton; Assert.ok(selectedOneOff); EventUtils.synthesizeKey("VK_RETURN", {}, win); await searchPromise; EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "4", numWords: "1", selIndex: "0", selType: "searchengine", provider: "HeuristicFallback", }, }; }, async function (win) { info("Type something, ESC, type something else, press Enter."); win.gURLBar.select(); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); EventUtils.synthesizeKey("x", {}, win); EventUtils.synthesizeKey("VK_ESCAPE", {}, win); EventUtils.synthesizeKey("y", {}, win); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "1", numWords: "1", selIndex: "0", selType: "searchengine", provider: "HeuristicFallback", }, }; }, async function (win) { info("Type a keyword, Enter."); win.gURLBar.select(); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "kw test", fireInputEvent: true, }); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "7", numWords: "2", selIndex: "0", selType: "keyword", provider: "BookmarkKeywords", }, }; }, async function (win) { let tipProvider = registerTipProvider(); info("Selecting a tip's main button, enter."); win.gURLBar.search("x"); await UrlbarTestUtils.promiseSearchComplete(win); EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); EventUtils.synthesizeKey("VK_RETURN", {}, win); unregisterTipProvider(tipProvider); return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "1", numWords: "1", selIndex: "1", selType: "tip", provider: tipProvider.name, }, }; }, async function (win) { let tipProvider = registerTipProvider(); info("Selecting a tip's help option."); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); win.gURLBar.search("x"); await UrlbarTestUtils.promiseSearchComplete(win); EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); if (UrlbarPrefs.get("resultMenu")) { await UrlbarTestUtils.openResultMenuAndPressAccesskey(win, "h"); } else { EventUtils.synthesizeKey("KEY_Tab", {}, win); EventUtils.synthesizeKey("VK_RETURN", {}, win); } await promise; unregisterTipProvider(tipProvider); return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "1", numWords: "1", selIndex: "1", selType: "tiphelp", provider: tipProvider.name, }, }; }, async function (win) { info("Type something and canonize"); win.gURLBar.select(); const promise = BrowserTestUtils.waitForDocLoadAndStopIt( "https://www.example.com/", win.gBrowser.selectedBrowser ); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "example", fireInputEvent: true, }); EventUtils.synthesizeKey("VK_RETURN", { ctrlKey: true }, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "7", numWords: "1", selIndex: "0", selType: "canonized", provider: "Autofill", }, }; }, async function (win) { info("Type something, click on bookmark entry."); // Add a clean bookmark. const bookmark = await PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid, url: "http://example.com/bookmark", title: "bookmark", }); win.gURLBar.select(); let url = "http://example.com/bookmark"; let promise = BrowserTestUtils.browserLoaded( win.gBrowser.selectedBrowser, false, url ); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "boo", fireInputEvent: true, }); while (win.gURLBar.untrimmedValue != url) { EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); } let element = UrlbarTestUtils.getSelectedRow(win); EventUtils.synthesizeMouseAtCenter(element, {}, win); await promise; await PlacesUtils.bookmarks.remove(bookmark); return { category: "urlbar", method: "engagement", object: "click", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "3", numWords: "1", selIndex: val => parseInt(val) > 0, selType: "bookmark", provider: "Places", }, }; }, async function (win) { info("Type an autofilled string, Enter."); win.gURLBar.select(); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "exa", fireInputEvent: true, }); // Check it's autofilled. Assert.equal(win.gURLBar.selectionStart, 3); Assert.equal(win.gURLBar.selectionEnd, 12); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "3", numWords: "1", selIndex: "0", selType: "autofill_origin", provider: "Autofill", }, }; }, async function (win) { info("Type something, select bookmark entry, Enter."); // Add a clean bookmark and the input history in order to detect in InputHistory // provider and to not show adaptive history autofill. const bookmark = await PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid, url: "http://example.com/bookmark", title: "bookmark", }); await UrlbarUtils.addToInputHistory( "http://example.com/bookmark", "bookmark" ); win.gURLBar.select(); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "boo", fireInputEvent: true, }); while (win.gURLBar.untrimmedValue != "http://example.com/bookmark") { EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); } EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; await PlacesUtils.bookmarks.remove(bookmark); return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "3", numWords: "1", selIndex: val => parseInt(val) > 0, selType: "bookmark", provider: "InputHistory", }, }; }, async function (win) { info("Type something, select remote search suggestion, Enter."); win.gURLBar.select(); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "foo", fireInputEvent: true, }); while (win.gURLBar.untrimmedValue != "foofoo") { EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); } EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "3", numWords: "1", selIndex: val => parseInt(val) > 0, selType: "searchsuggestion", provider: "SearchSuggestions", }, }; }, async function (win) { info("Type something, select form history, Enter."); await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.maxHistoricalSearchSuggestions", 2]], }); await UrlbarTestUtils.formHistory.add(["foofoo", "foobar"]); win.gURLBar.select(); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "foo", fireInputEvent: true, }); while (win.gURLBar.untrimmedValue != "foofoo") { EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); } EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; await SpecialPowers.popPrefEnv(); return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "3", numWords: "1", selIndex: val => parseInt(val) > 0, selType: "formhistory", provider: "SearchSuggestions", }, }; }, async function (win) { info("Type @, enter on a keywordoffer, then search and press enter."); win.gURLBar.select(); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "@", fireInputEvent: true, }); while (win.gURLBar.searchMode?.engineName != TEST_ENGINE_NAME) { EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); } EventUtils.synthesizeKey("VK_RETURN", {}, win); await UrlbarTestUtils.promiseSearchComplete(win); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "moz", fireInputEvent: true, }); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return [ // engagement on the keyword offer result to enter search mode { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "1", numWords: "1", selIndex: "6", selType: "searchengine", provider: "TokenAliasEngines", }, }, // engagement on the search heuristic { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "3", numWords: "1", selIndex: "0", selType: "searchengine", provider: "HeuristicFallback", }, }, ]; }, async function (win) { info("Type an @alias, then space, then search and press enter."); const alias = "testalias"; await SearchTestUtils.installSearchExtension({ name: "AliasTest", keyword: alias, }); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: `${alias} `, }); await UrlbarTestUtils.assertSearchMode(win, { engineName: "AliasTest", entry: "typed", }); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "moz", fireInputEvent: true, }); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "3", numWords: "1", selIndex: "0", selType: "searchengine", provider: "HeuristicFallback", }, }; }, async function (win) { info("Drop something."); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); EventUtils.synthesizeDrop( win.document.getElementById("back-button"), win.gURLBar.inputField, [[{ type: "text/plain", data: "www.example.com" }]], "copy", win ); await promise; return { category: "urlbar", method: "engagement", object: "drop_go", value: "dropped", extra: { elapsed: val => parseInt(val) > 0, numChars: "15", numWords: "1", selIndex: "-1", selType: "none", provider: "", }, }; }, async function (win) { info("Paste and Go something."); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await SimpleTest.promiseClipboardChange("www.example.com", () => { clipboardHelper.copyString("www.example.com"); }); let inputBox = win.gURLBar.querySelector("moz-input-box"); let cxmenu = inputBox.menupopup; let cxmenuPromise = BrowserTestUtils.waitForEvent(cxmenu, "popupshown"); EventUtils.synthesizeMouseAtCenter( win.gURLBar.inputField, { type: "contextmenu", button: 2, }, win ); await cxmenuPromise; let menuitem = inputBox.getMenuItem("paste-and-go"); cxmenu.activateItem(menuitem); await promise; return { category: "urlbar", method: "engagement", object: "paste_go", value: "pasted", extra: { elapsed: val => parseInt(val) > 0, numChars: "15", numWords: "1", selIndex: "-1", selType: "none", provider: "", }, }; }, // The URLs in the down arrow/autoOpen tests must vary from test to test, // else the first Top Site results will be a switch-to-tab result and a page // load will not occur. async function (win) { info("Open the panel with DOWN, select with DOWN, Enter."); await addTopSite("http://example.org/"); win.gURLBar.value = ""; win.gURLBar.select(); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promisePopupOpen(win, () => { EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); }); await UrlbarTestUtils.promiseSearchComplete(win); while (win.gURLBar.untrimmedValue != "http://example.org/") { EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); } EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "topsites", extra: { elapsed: val => parseInt(val) > 0, numChars: "0", numWords: "0", selType: "history", selIndex: val => parseInt(val) >= 0, provider: "UrlbarProviderTopSites", }, }; }, async function (win) { info("Open the panel with DOWN, click on entry."); await addTopSite("http://example.com/"); win.gURLBar.value = ""; win.gURLBar.select(); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promisePopupOpen(win, () => { EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); }); while (win.gURLBar.untrimmedValue != "http://example.com/") { EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); } let element = UrlbarTestUtils.getSelectedRow(win); EventUtils.synthesizeMouseAtCenter(element, {}, win); await promise; return { category: "urlbar", method: "engagement", object: "click", value: "topsites", extra: { elapsed: val => parseInt(val) > 0, numChars: "0", numWords: "0", selType: "history", selIndex: "0", provider: "UrlbarProviderTopSites", }, }; }, // The URLs in the autoOpen tests must vary from test to test, else // the first Top Site results will be a switch-to-tab result and a page load // will not occur. async function (win) { info( "With pageproxystate=valid, autoopen the panel, select with DOWN, Enter." ); await addTopSite("http://example.org/"); win.gURLBar.value = ""; let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promisePopupOpen(win, () => { win.document.getElementById("Browser:OpenLocation").doCommand(); }); await UrlbarTestUtils.promiseSearchComplete(win); while (win.gURLBar.untrimmedValue != "http://example.org/") { EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); } EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "topsites", extra: { elapsed: val => parseInt(val) > 0, numChars: "0", numWords: "0", selType: "history", selIndex: val => parseInt(val) >= 0, provider: "UrlbarProviderTopSites", }, }; }, async function (win) { info("With pageproxystate=valid, autoopen the panel, click on entry."); await addTopSite("http://example.com/"); win.gURLBar.value = ""; let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promisePopupOpen(win, () => { win.document.getElementById("Browser:OpenLocation").doCommand(); }); await UrlbarTestUtils.promiseSearchComplete(win); while (win.gURLBar.untrimmedValue != "http://example.com/") { EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); } let element = UrlbarTestUtils.getSelectedRow(win); EventUtils.synthesizeMouseAtCenter(element, {}, win); await promise; return { category: "urlbar", method: "engagement", object: "click", value: "topsites", extra: { elapsed: val => parseInt(val) > 0, numChars: "0", numWords: "0", selType: "history", selIndex: "0", provider: "UrlbarProviderTopSites", }, }; }, async function (win) { info("With pageproxystate=invalid, open retained results, Enter."); await addTopSite("http://example.org/"); win.gURLBar.value = "example.org"; win.gURLBar.setPageProxyState("invalid"); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promisePopupOpen(win, () => { win.document.getElementById("Browser:OpenLocation").doCommand(); }); await UrlbarTestUtils.promiseSearchComplete(win); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "returned", extra: { elapsed: val => parseInt(val) > 0, numChars: "11", numWords: "1", selType: "autofill_origin", selIndex: "0", provider: "Autofill", }, }; }, async function (win) { info("With pageproxystate=invalid, open retained results, click on entry."); // This value must be different from the previous test, to avoid reopening // the view. win.gURLBar.value = "example.com"; win.gURLBar.setPageProxyState("invalid"); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promisePopupOpen(win, () => { win.document.getElementById("Browser:OpenLocation").doCommand(); }); await UrlbarTestUtils.promiseSearchComplete(win); let element = UrlbarTestUtils.getSelectedRow(win); EventUtils.synthesizeMouseAtCenter(element, {}, win); await promise; return { category: "urlbar", method: "engagement", object: "click", value: "returned", extra: { elapsed: val => parseInt(val) > 0, numChars: "11", numWords: "1", selType: "autofill_origin", selIndex: "0", provider: "Autofill", }, }; }, async function (win) { info("Reopen the view: type, blur, focus, confirm."); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "search", fireInputEvent: true, }); await UrlbarTestUtils.promisePopupClose(win, () => { win.gURLBar.blur(); }); await UrlbarTestUtils.promisePopupOpen(win, () => { win.document.getElementById("Browser:OpenLocation").doCommand(); }); await UrlbarTestUtils.promiseSearchComplete(win); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return [ { category: "urlbar", method: "abandonment", object: "blur", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "6", numWords: "1", }, }, { category: "urlbar", method: "engagement", object: "enter", value: "returned", extra: { elapsed: val => parseInt(val) > 0, numChars: "6", numWords: "1", selType: "searchengine", selIndex: "0", provider: "HeuristicFallback", }, }, ]; }, async function (win) { info("Open search mode with a keyboard shortcut."); // Bug 1797801: If the search mode used is the same as the default engine and // showSearchTerms is enabled, the chiclet will remain in the urlbar on the search. // Subsequent tests rely on search mode not already been selected. await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.showSearchTerms.featureGate", false]], }); let defaultEngine = await Services.search.getDefault(); win.gURLBar.select(); EventUtils.synthesizeKey("k", { accelKey: true }, win); await UrlbarTestUtils.assertSearchMode(win, { source: UrlbarUtils.RESULT_SOURCE.SEARCH, engineName: defaultEngine.name, entry: "shortcut", }); // Execute a search to finish the engagement. let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "moz", fireInputEvent: true, }); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; await SpecialPowers.popPrefEnv(); return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "3", numWords: "1", selIndex: "0", selType: "searchengine", provider: "HeuristicFallback", }, }; }, async function (win) { info("Open search mode from a tab-to-search result."); await SpecialPowers.pushPrefEnv({ set: [["browser.urlbar.tabToSearch.onboard.interactionsLeft", 0]], }); await PlacesUtils.history.clear(); for (let i = 0; i < 3; i++) { await PlacesTestUtils.addVisits([`https://${TEST_ENGINE_DOMAIN}/`]); } await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: TEST_ENGINE_DOMAIN.slice(0, 4), }); let tabToSearchResult = ( await UrlbarTestUtils.waitForAutocompleteResultAt(win, 1) ).result; Assert.equal( tabToSearchResult.providerName, "TabToSearch", "The second result is a tab-to-search result." ); // Select the tab-to-search result. EventUtils.synthesizeKey("KEY_ArrowDown", {}, win); let searchPromise = UrlbarTestUtils.promiseSearchComplete(win); EventUtils.synthesizeKey("KEY_Enter", {}, win); await searchPromise; await UrlbarTestUtils.assertSearchMode(win, { engineName: TEST_ENGINE_NAME, entry: "tabtosearch", }); // Execute a search to finish the engagement. let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "moz", fireInputEvent: true, }); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; await PlacesUtils.history.clear(); await SpecialPowers.popPrefEnv(); return [ // engagement on the tab-to-search to enter search mode { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "4", numWords: "1", selIndex: "1", selType: "tabtosearch", provider: "TabToSearch", }, }, // engagement on the search heuristic { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "3", numWords: "1", selIndex: "0", selType: "searchengine", provider: "HeuristicFallback", }, }, ]; }, async function (win) { info("Sanity check we are not stuck on 'returned'"); win.gURLBar.select(); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "x", fireInputEvent: true, }); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "1", numWords: "1", selIndex: "0", selType: "searchengine", provider: "HeuristicFallback", }, }; }, async function (win) { info("Reopen the view: type, blur, focus, backspace, type, confirm."); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "search", fireInputEvent: true, }); await UrlbarTestUtils.promisePopupClose(win, () => { win.gURLBar.blur(); }); await UrlbarTestUtils.promisePopupOpen(win, () => { win.document.getElementById("Browser:OpenLocation").doCommand(); }); EventUtils.synthesizeKey("VK_RIGHT", {}, win); EventUtils.synthesizeKey("VK_BACK_SPACE", {}, win); EventUtils.synthesizeKey("x", {}, win); await UrlbarTestUtils.promiseSearchComplete(win); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return [ { category: "urlbar", method: "abandonment", object: "blur", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "6", numWords: "1", }, }, { category: "urlbar", method: "engagement", object: "enter", value: "returned", extra: { elapsed: val => parseInt(val) > 0, numChars: "6", numWords: "1", selType: "searchengine", selIndex: "0", provider: "HeuristicFallback", }, }, ]; }, async function (win) { info("Reopen the view: type, blur, focus, type (overwrite), confirm."); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "search", fireInputEvent: true, }); await UrlbarTestUtils.promisePopupClose(win, () => { win.gURLBar.blur(); }); await UrlbarTestUtils.promisePopupOpen(win, () => { win.document.getElementById("Browser:OpenLocation").doCommand(); }); EventUtils.synthesizeKey("x", {}, win); await UrlbarTestUtils.promiseSearchComplete(win); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return [ { category: "urlbar", method: "abandonment", object: "blur", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "6", numWords: "1", }, }, { category: "urlbar", method: "engagement", object: "enter", value: "restarted", extra: { elapsed: val => parseInt(val) > 0, numChars: "1", numWords: "1", selType: "searchengine", selIndex: "0", provider: "HeuristicFallback", }, }, ]; }, async function (win) { info("Sanity check we are not stuck on 'restarted'"); win.gURLBar.select(); let promise = BrowserTestUtils.browserLoaded(win.gBrowser.selectedBrowser); await UrlbarTestUtils.promiseAutocompleteResultPopup({ window: win, value: "x", fireInputEvent: true, }); EventUtils.synthesizeKey("VK_RETURN", {}, win); await promise; return { category: "urlbar", method: "engagement", object: "enter", value: "typed", extra: { elapsed: val => parseInt(val) > 0, numChars: "1", numWords: "1", selIndex: "0", selType: "searchengine", provider: "HeuristicFallback", }, }; }, ]; add_setup(async function () { await PlacesUtils.history.clear(); await PlacesUtils.bookmarks.eraseEverything(); // Create a new search engine and mark it as default let engine = await SearchTestUtils.promiseNewSearchEngine({ url: getRootDirectory(gTestPath) + "searchSuggestionEngine.xml", setAsDefault: true, }); await Services.search.moveEngine(engine, 0); await SearchTestUtils.installSearchExtension({ name: TEST_ENGINE_NAME, keyword: TEST_ENGINE_ALIAS, search_url: `https://${TEST_ENGINE_DOMAIN}/`, }); // Add a bookmark and a keyword. let bm = await PlacesUtils.bookmarks.insert({ parentGuid: PlacesUtils.bookmarks.unfiledGuid, url: "http://example.com/?q=%s", title: "test", }); await PlacesUtils.keywords.insert({ keyword: "kw", url: "http://example.com/?q=%s", }); registerCleanupFunction(async function () { await PlacesUtils.keywords.remove("kw"); await PlacesUtils.bookmarks.remove(bm); await PlacesUtils.history.clear(); }); }); async function doTest(eventTelemetryEnabled) { await SpecialPowers.pushPrefEnv({ set: [ ["browser.urlbar.eventTelemetry.enabled", eventTelemetryEnabled], ["browser.urlbar.suggest.searches", true], ], }); const win = await BrowserTestUtils.openNewBrowserWindow(); // This is not necessary after each loop, because assertEvents does it. Services.telemetry.clearEvents(); Services.telemetry.clearScalars(); for (let i = 0; i < tests.length; i++) { info(`Running test at index ${i}`); let events = await tests[i](win); if (events === null) { info("Skipping test"); continue; } if (!Array.isArray(events)) { events = [events]; } // Always blur to ensure it's not accounted as an additional abandonment. win.gURLBar.setSearchMode({}); win.gURLBar.blur(); TelemetryTestUtils.assertEvents(eventTelemetryEnabled ? events : [], { category: "urlbar", }); // Scalars should be recorded regardless of `eventTelemetry.enabled`. let scalars = TelemetryTestUtils.getProcessScalars("parent", false, true); TelemetryTestUtils.assertScalar( scalars, "urlbar.engagement", events.filter(e => e.method == "engagement").length || undefined ); TelemetryTestUtils.assertScalar( scalars, "urlbar.abandonment", events.filter(e => e.method == "abandonment").length || undefined ); await UrlbarTestUtils.formHistory.clear(win); } await BrowserTestUtils.closeWindow(win); await SpecialPowers.popPrefEnv(); } add_task(async function enabled() { await doTest(true); }); add_task(async function disabled() { await doTest(false); }); /** * Replaces the contents of Top Sites with the specified site. * * @param {string} site * A site to add to Top Sites. */ async function addTopSite(site) { await PlacesUtils.history.clear(); for (let i = 0; i < 5; i++) { await PlacesTestUtils.addVisits(site); } await updateTopSites(sites => sites && sites[0] && sites[0].url == site); } function registerTipProvider() { let provider = new UrlbarTestUtils.TestProvider({ results: tipMatches, priority: 1, }); UrlbarProvidersManager.registerProvider(provider); return provider; } function unregisterTipProvider(provider) { UrlbarProvidersManager.unregisterProvider(provider); } let tipMatches = [ new UrlbarResult( UrlbarUtils.RESULT_TYPE.URL, UrlbarUtils.RESULT_SOURCE.HISTORY, { url: "http://mozilla.org/a" } ), new UrlbarResult( UrlbarUtils.RESULT_TYPE.TIP, UrlbarUtils.RESULT_SOURCE.OTHER_LOCAL, { helpUrl: "http://example.com/", helpL10n: { id: UrlbarPrefs.get("resultMenu") ? "urlbar-result-menu-tip-get-help" : "urlbar-tip-help-icon", }, type: "test", titleL10n: { id: "urlbar-search-tips-confirm" }, buttons: [ { url: "http://example.com/", l10n: { id: "urlbar-search-tips-confirm" }, }, ], } ), new UrlbarResult( UrlbarUtils.RESULT_TYPE.URL, UrlbarUtils.RESULT_SOURCE.HISTORY, { url: "http://mozilla.org/b" } ), new UrlbarResult( UrlbarUtils.RESULT_TYPE.URL, UrlbarUtils.RESULT_SOURCE.HISTORY, { url: "http://mozilla.org/c" } ), ];