From 911baac099447af7e8c9ddde81040c9f7dd06867 Mon Sep 17 00:00:00 2001 From: Razvan Maries Date: Sun, 12 Jul 2020 01:31:42 +0300 Subject: [PATCH] Backed out 6 changesets (bug 1648468) for perma failures on browser_test_focus_urlbar.js. CLOSED TREE Backed out changeset 60b6915e8037 (bug 1648468) Backed out changeset fc7a6b8f84a2 (bug 1648468) Backed out changeset 97c7475abf85 (bug 1648468) Backed out changeset bb37a0821844 (bug 1648468) Backed out changeset 10447a3e04ff (bug 1648468) Backed out changeset 69a210ce0e9a (bug 1648468) --- .../events/browser_test_focus_urlbar.js | 3 - .../urlbar/UrlbarMuxerUnifiedComplete.jsm | 101 +- .../urlbar/UrlbarProviderAutofill.jsm | 755 ----- .../UrlbarProviderTokenAliasEngines.jsm | 104 +- .../urlbar/UrlbarProviderUnifiedComplete.jsm | 13 +- .../urlbar/UrlbarProvidersManager.jsm | 30 +- browser/components/urlbar/UrlbarUtils.jsm | 62 - browser/components/urlbar/UrlbarView.jsm | 12 - browser/components/urlbar/moz.build | 1 - browser/components/urlbar/tests/unit/head.js | 240 +- .../tests/unit/test_autofill_about_urls.js | 100 - .../tests/unit/test_autofill_functional.js | 112 - .../unit/test_autofill_originsAndQueries.js | 2421 ----------------- .../unit/test_autofill_search_engines.js | 232 -- .../urlbar/tests/unit/test_autofill_urls.js | 133 - .../test_avoid_stripping_to_empty_tokens.js | 120 - .../urlbar/tests/unit/test_casing.js | 363 --- .../urlbar/tests/unit/test_dupe_urls.js | 63 - .../urlbar/tests/unit/test_encoded_urls.js | 97 - .../urlbar/tests/unit/test_keywords.js | 207 -- .../urlbar/tests/unit/test_query_url.js | 123 - .../tests/unit/test_search_engine_host.js | 80 - .../tests/unit/test_search_suggestions.js | 1 + .../urlbar/tests/unit/test_trimming.js | 221 -- .../components/urlbar/tests/unit/xpcshell.ini | 17 - toolkit/components/places/UnifiedComplete.jsm | 622 ++++- .../tests/unifiedcomplete/autofill_tasks.js | 1943 +++++++++++++ .../unifiedcomplete/head_autocomplete.js | 12 + .../test_autocomplete_functional.js | 62 + .../test_autofill_about_urls.js | 83 + .../unifiedcomplete}/test_autofill_origins.js | 418 +-- .../test_autofill_search_engine_aliases.js | 62 +- .../test_autofill_search_engines.js | 201 ++ .../unifiedcomplete/test_autofill_urls.js | 114 + .../test_avoid_middle_complete.js | 190 +- .../test_avoid_stripping_to_empty_tokens.js | 81 + .../tests/unifiedcomplete/test_casing.js | 212 ++ .../unifiedcomplete}/test_dedupe_prefix.js | 73 +- .../tests/unifiedcomplete/test_dupe_urls.js | 51 + .../unifiedcomplete/test_encoded_urls.js | 87 + .../tests/unifiedcomplete/test_keywords.js | 130 + .../tests/unifiedcomplete/test_query_url.js | 66 + .../test_search_engine_host.js | 57 + .../unifiedcomplete/test_swap_protocol.js | 4 +- .../tests/unifiedcomplete/test_trimming.js | 120 + .../places/tests/unifiedcomplete/xpcshell.ini | 17 + 46 files changed, 4173 insertions(+), 6043 deletions(-) delete mode 100644 browser/components/urlbar/UrlbarProviderAutofill.jsm delete mode 100644 browser/components/urlbar/tests/unit/test_autofill_about_urls.js delete mode 100644 browser/components/urlbar/tests/unit/test_autofill_functional.js delete mode 100644 browser/components/urlbar/tests/unit/test_autofill_originsAndQueries.js delete mode 100644 browser/components/urlbar/tests/unit/test_autofill_search_engines.js delete mode 100644 browser/components/urlbar/tests/unit/test_autofill_urls.js delete mode 100644 browser/components/urlbar/tests/unit/test_avoid_stripping_to_empty_tokens.js delete mode 100644 browser/components/urlbar/tests/unit/test_casing.js delete mode 100644 browser/components/urlbar/tests/unit/test_dupe_urls.js delete mode 100644 browser/components/urlbar/tests/unit/test_encoded_urls.js delete mode 100644 browser/components/urlbar/tests/unit/test_keywords.js delete mode 100644 browser/components/urlbar/tests/unit/test_query_url.js delete mode 100644 browser/components/urlbar/tests/unit/test_search_engine_host.js delete mode 100644 browser/components/urlbar/tests/unit/test_trimming.js create mode 100644 toolkit/components/places/tests/unifiedcomplete/autofill_tasks.js create mode 100644 toolkit/components/places/tests/unifiedcomplete/test_autocomplete_functional.js create mode 100644 toolkit/components/places/tests/unifiedcomplete/test_autofill_about_urls.js rename {browser/components/urlbar/tests/unit => toolkit/components/places/tests/unifiedcomplete}/test_autofill_origins.js (55%) rename {browser/components/urlbar/tests/unit => toolkit/components/places/tests/unifiedcomplete}/test_autofill_search_engine_aliases.js (68%) create mode 100644 toolkit/components/places/tests/unifiedcomplete/test_autofill_search_engines.js create mode 100644 toolkit/components/places/tests/unifiedcomplete/test_autofill_urls.js rename {browser/components/urlbar/tests/unit => toolkit/components/places/tests/unifiedcomplete}/test_avoid_middle_complete.js (53%) create mode 100644 toolkit/components/places/tests/unifiedcomplete/test_avoid_stripping_to_empty_tokens.js create mode 100644 toolkit/components/places/tests/unifiedcomplete/test_casing.js rename {browser/components/urlbar/tests/unit => toolkit/components/places/tests/unifiedcomplete}/test_dedupe_prefix.js (64%) create mode 100644 toolkit/components/places/tests/unifiedcomplete/test_dupe_urls.js create mode 100644 toolkit/components/places/tests/unifiedcomplete/test_encoded_urls.js create mode 100644 toolkit/components/places/tests/unifiedcomplete/test_keywords.js create mode 100644 toolkit/components/places/tests/unifiedcomplete/test_query_url.js create mode 100644 toolkit/components/places/tests/unifiedcomplete/test_search_engine_host.js create mode 100644 toolkit/components/places/tests/unifiedcomplete/test_trimming.js diff --git a/accessible/tests/browser/events/browser_test_focus_urlbar.js b/accessible/tests/browser/events/browser_test_focus_urlbar.js index 91840e3aa6b4..8218757aa297 100644 --- a/accessible/tests/browser/events/browser_test_focus_urlbar.js +++ b/accessible/tests/browser/events/browser_test_focus_urlbar.js @@ -337,9 +337,6 @@ async function runTipTests() { ), ]; - // Ensure the tip appears in the expected position. - matches[1].suggestedIndex = 2; - let provider = new TipTestProvider(matches); UrlbarProvidersManager.registerProvider(provider); diff --git a/browser/components/urlbar/UrlbarMuxerUnifiedComplete.jsm b/browser/components/urlbar/UrlbarMuxerUnifiedComplete.jsm index d87489902da6..b3837dd4e70d 100644 --- a/browser/components/urlbar/UrlbarMuxerUnifiedComplete.jsm +++ b/browser/components/urlbar/UrlbarMuxerUnifiedComplete.jsm @@ -48,8 +48,6 @@ const heuristicOrder = [ "UrlbarProviderSearchTips", "Omnibox", "UnifiedComplete", - "Autofill", - "TokenAliasEngines", "HeuristicFallback", ]; /** @@ -76,6 +74,8 @@ class MuxerUnifiedComplete extends UrlbarMuxer { * * @param {UrlbarQueryContext} context * The query context. + * @returns {boolean} If results were successfully sorted. This return value + * is a stopgap and can be removed when bug 1648468 lands. */ sort(context) { // This method is called multiple times per keystroke, so it should be as @@ -131,17 +131,21 @@ class MuxerUnifiedComplete extends UrlbarMuxer { let resultsWithSuggestedIndex = []; let formHistoryResults = new Set(); let formHistorySuggestions = new Set(); - // Used to deduped URLs based on their stripped prefix and title. Schema: - // {string} strippedUrl => {prefix, title, rank} - let strippedUrlToTopPrefixAndTitle = new Map(); let maxFormHistoryCount = Math.min( UrlbarPrefs.get("maxHistoricalSearchSuggestions"), context.maxResults ); + let hasUnifiedComplete = false; // Do the first pass through the results. We only collect info for the // second pass here. for (let result of context.results) { + // Keep track of whether UnifiedComplete has returned results. We will + // quit early if it hasn't. + if (result.providerName == "UnifiedComplete") { + hasUnifiedComplete = true; + } + // The "Search in a Private Window" result should only be shown when there // are other results and all of them are searches. It should not be shown // if the user typed an alias because that's an explicit engine choice. @@ -180,28 +184,16 @@ class MuxerUnifiedComplete extends UrlbarMuxer { ) { canShowTailSuggestions = false; } + } - if (result.type == UrlbarUtils.RESULT_TYPE.URL && result.payload.url) { - let [strippedUrl, prefix] = UrlbarUtils.stripPrefixAndTrim( - result.payload.url, - { - stripHttp: true, - stripHttps: true, - stripWww: true, - trimEmptyQuery: true, - } - ); - let prefixRank = UrlbarUtils.getPrefixRank(prefix); - let topPrefixData = strippedUrlToTopPrefixAndTitle.get(strippedUrl); - let topPrefixRank = topPrefixData ? topPrefixData.rank : -1; - if (topPrefixRank < prefixRank) { - strippedUrlToTopPrefixAndTitle.set(strippedUrl, { - prefix, - title: result.payload.title, - rank: prefixRank, - }); - } - } + // Quit early if we're still waiting on UnifiedComplete. If it turns out + // UnifiedComplete doesn't need to return any results, it will call sort() + // regardless to unblock showing results. + if ( + !hasUnifiedComplete && + context.pendingHeuristicProviders.has("UnifiedComplete") + ) { + return false; } // Do the second pass through results to build the list of unsorted results. @@ -212,62 +204,6 @@ class MuxerUnifiedComplete extends UrlbarMuxer { continue; } - // We expect UnifiedComplete sent us the highest-ranked www. and non-www - // origins, if any. Now, compare them to each other and to the heuristic - // result. - // 1. If the heuristic result is lower ranked than both, discard the www - // origin, unless it has a different page title than the non-www - // origin. This is a guard against deduping when www.site.com and - // site.com have different content. - // 2. If the heuristic result is higher than either the www origin or - // non-www origin: - // 2a. If the heuristic is a www origin, discard the non-www origin. - // 2b. If the heuristic is a non-www origin, discard the www origin. - if ( - !result.heuristic && - result.type == UrlbarUtils.RESULT_TYPE.URL && - result.payload.url - ) { - let [strippedUrl, prefix] = UrlbarUtils.stripPrefixAndTrim( - result.payload.url, - { - stripHttp: true, - stripHttps: true, - stripWww: true, - trimEmptyQuery: true, - } - ); - let topPrefixData = strippedUrlToTopPrefixAndTitle.get(strippedUrl); - // We don't expect completely identical URLs in the results at this - // point, so if the prefixes are the same, then we're deduping a result - // against itself. - if (topPrefixData && prefix != topPrefixData.prefix) { - let prefixRank = UrlbarUtils.getPrefixRank(prefix); - if ( - topPrefixData.rank > prefixRank && - prefix.endsWith("www.") == topPrefixData.prefix.endsWith("www.") - ) { - continue; - } else if ( - topPrefixData.rank > prefixRank && - result.payload?.title == topPrefixData.title - ) { - continue; - } - } - } - - // Exclude results that dupe autofill. - if ( - context.heuristicResult && - context.heuristicResult.providerName == "Autofill" && - result.providerName != "Autofill" && - context.heuristicResult.payload?.url == result.payload.url && - context.heuristicResult.type == result.type - ) { - continue; - } - // Exclude "Search in a Private Window" as determined in the first pass. if ( result.type == UrlbarUtils.RESULT_TYPE.SEARCH && @@ -389,6 +325,7 @@ class MuxerUnifiedComplete extends UrlbarMuxer { } context.results = sortedResults; + return true; } /** diff --git a/browser/components/urlbar/UrlbarProviderAutofill.jsm b/browser/components/urlbar/UrlbarProviderAutofill.jsm deleted file mode 100644 index 8d71535a2bc2..000000000000 --- a/browser/components/urlbar/UrlbarProviderAutofill.jsm +++ /dev/null @@ -1,755 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -/** - * This module exports a provider that provides an autofill result. - */ - -var EXPORTED_SYMBOLS = ["UrlbarProviderAutofill"]; - -const { XPCOMUtils } = ChromeUtils.import( - "resource://gre/modules/XPCOMUtils.jsm" -); -XPCOMUtils.defineLazyModuleGetters(this, { - AboutPagesUtils: "resource://gre/modules/AboutPagesUtils.jsm", - PlacesUtils: "resource://gre/modules/PlacesUtils.jsm", - UrlbarPrefs: "resource:///modules/UrlbarPrefs.jsm", - UrlbarProvider: "resource:///modules/UrlbarUtils.jsm", - UrlbarResult: "resource:///modules/UrlbarResult.jsm", - UrlbarSearchUtils: "resource:///modules/UrlbarSearchUtils.jsm", - UrlbarTokenizer: "resource:///modules/UrlbarTokenizer.jsm", - UrlbarUtils: "resource:///modules/UrlbarUtils.jsm", -}); - -// Sqlite result row index constants. -const QUERYINDEX = { - QUERYTYPE: 0, - URL: 1, - TITLE: 2, - BOOKMARKED: 3, - BOOKMARKTITLE: 4, - TAGS: 5, - VISITCOUNT: 6, - TYPED: 7, - PLACEID: 8, - SWITCHTAB: 9, - FRECENCY: 10, -}; - -// Result row indexes for originQuery() -const QUERYINDEX_ORIGIN = { - AUTOFILLED_VALUE: 1, - URL: 2, - FRECENCY: 3, -}; - -// Result row indexes for urlQuery() -const QUERYINDEX_URL = { - URL: 1, - STRIPPED_URL: 2, - FRECENCY: 3, -}; - -// AutoComplete query type constants. -// Describes the various types of queries that we can process rows for. -const QUERYTYPE = { - FILTERED: 0, - AUTOFILL_ORIGIN: 1, - AUTOFILL_URL: 2, - ADAPTIVE: 3, -}; - -// `WITH` clause for the autofill queries. autofill_frecency_threshold.value is -// the mean of all moz_origins.frecency values + stddevMultiplier * one standard -// deviation. This is inlined directly in the SQL (as opposed to being a custom -// Sqlite function for example) in order to be as efficient as possible. -const SQL_AUTOFILL_WITH = ` - WITH - frecency_stats(count, sum, squares) AS ( - SELECT - CAST((SELECT IFNULL(value, 0.0) FROM moz_meta WHERE key = 'origin_frecency_count') AS REAL), - CAST((SELECT IFNULL(value, 0.0) FROM moz_meta WHERE key = 'origin_frecency_sum') AS REAL), - CAST((SELECT IFNULL(value, 0.0) FROM moz_meta WHERE key = 'origin_frecency_sum_of_squares') AS REAL) - ), - autofill_frecency_threshold(value) AS ( - SELECT - CASE count - WHEN 0 THEN 0.0 - WHEN 1 THEN sum - ELSE (sum / count) + (:stddevMultiplier * sqrt((squares - ((sum * sum) / count)) / count)) - END - FROM frecency_stats - ) - `; - -const SQL_AUTOFILL_FRECENCY_THRESHOLD = `host_frecency >= ( - SELECT value FROM autofill_frecency_threshold - )`; - -function originQuery({ select = "", where = "", having = "" }) { - return `${SQL_AUTOFILL_WITH} - SELECT :query_type, - fixed_up_host || '/', - IFNULL(:prefix, prefix) || moz_origins.host || '/', - frecency, - bookmarked, - id - FROM ( - SELECT host, - host AS fixed_up_host, - TOTAL(frecency) AS host_frecency, - ( - SELECT TOTAL(foreign_count) > 0 - FROM moz_places - WHERE moz_places.origin_id = moz_origins.id - ) AS bookmarked - ${select} - FROM moz_origins - WHERE host BETWEEN :searchString AND :searchString || X'FFFF' - ${where} - GROUP BY host - HAVING ${having} - UNION ALL - SELECT host, - fixup_url(host) AS fixed_up_host, - TOTAL(frecency) AS host_frecency, - ( - SELECT TOTAL(foreign_count) > 0 - FROM moz_places - WHERE moz_places.origin_id = moz_origins.id - ) AS bookmarked - ${select} - FROM moz_origins - WHERE host BETWEEN 'www.' || :searchString AND 'www.' || :searchString || X'FFFF' - ${where} - GROUP BY host - HAVING ${having} - ) AS grouped_hosts - JOIN moz_origins ON moz_origins.host = grouped_hosts.host - ORDER BY frecency DESC, id DESC - LIMIT 1 `; -} - -function urlQuery(where1, where2) { - // We limit the search to places that are either bookmarked or have a frecency - // over some small, arbitrary threshold (20) in order to avoid scanning as few - // rows as possible. Keep in mind that we run this query every time the user - // types a key when the urlbar value looks like a URL with a path. - return `/* do not warn (bug no): cannot use an index to sort */ - SELECT :query_type, - url, - :strippedURL, - frecency, - foreign_count > 0 AS bookmarked, - visit_count > 0 AS visited, - id - FROM moz_places - WHERE rev_host = :revHost - ${where1} - UNION ALL - SELECT :query_type, - url, - :strippedURL, - frecency, - foreign_count > 0 AS bookmarked, - visit_count > 0 AS visited, - id - FROM moz_places - WHERE rev_host = :revHost || 'www.' - ${where2} - ORDER BY frecency DESC, id DESC - LIMIT 1 `; -} -// Queries -const QUERY_ORIGIN_HISTORY_BOOKMARK = originQuery({ - having: `bookmarked OR ${SQL_AUTOFILL_FRECENCY_THRESHOLD}`, -}); - -const QUERY_ORIGIN_PREFIX_HISTORY_BOOKMARK = originQuery({ - where: `AND prefix BETWEEN :prefix AND :prefix || X'FFFF'`, - having: `bookmarked OR ${SQL_AUTOFILL_FRECENCY_THRESHOLD}`, -}); - -const QUERY_ORIGIN_HISTORY = originQuery({ - select: `, ( - SELECT TOTAL(visit_count) > 0 - FROM moz_places - WHERE moz_places.origin_id = moz_origins.id - ) AS visited`, - having: `visited AND ${SQL_AUTOFILL_FRECENCY_THRESHOLD}`, -}); - -const QUERY_ORIGIN_PREFIX_HISTORY = originQuery({ - select: `, ( - SELECT TOTAL(visit_count) > 0 - FROM moz_places - WHERE moz_places.origin_id = moz_origins.id - ) AS visited`, - where: `AND prefix BETWEEN :prefix AND :prefix || X'FFFF'`, - having: `visited AND ${SQL_AUTOFILL_FRECENCY_THRESHOLD}`, -}); - -const QUERY_ORIGIN_BOOKMARK = originQuery({ - having: `bookmarked`, -}); - -const QUERY_ORIGIN_PREFIX_BOOKMARK = originQuery({ - where: `AND prefix BETWEEN :prefix AND :prefix || X'FFFF'`, - having: `bookmarked`, -}); - -const QUERY_URL_HISTORY_BOOKMARK = urlQuery( - `AND (bookmarked OR frecency > 20) - AND strip_prefix_and_userinfo(url) BETWEEN :strippedURL AND :strippedURL || X'FFFF'`, - `AND (bookmarked OR frecency > 20) - AND strip_prefix_and_userinfo(url) BETWEEN 'www.' || :strippedURL AND 'www.' || :strippedURL || X'FFFF'` -); - -const QUERY_URL_PREFIX_HISTORY_BOOKMARK = urlQuery( - `AND (bookmarked OR frecency > 20) - AND url BETWEEN :prefix || :strippedURL AND :prefix || :strippedURL || X'FFFF'`, - `AND (bookmarked OR frecency > 20) - AND url BETWEEN :prefix || 'www.' || :strippedURL AND :prefix || 'www.' || :strippedURL || X'FFFF'` -); - -const QUERY_URL_HISTORY = urlQuery( - `AND (visited OR NOT bookmarked) - AND frecency > 20 - AND strip_prefix_and_userinfo(url) BETWEEN :strippedURL AND :strippedURL || X'FFFF'`, - `AND (visited OR NOT bookmarked) - AND frecency > 20 - AND strip_prefix_and_userinfo(url) BETWEEN 'www.' || :strippedURL AND 'www.' || :strippedURL || X'FFFF'` -); - -const QUERY_URL_PREFIX_HISTORY = urlQuery( - `AND (visited OR NOT bookmarked) - AND frecency > 20 - AND url BETWEEN :prefix || :strippedURL AND :prefix || :strippedURL || X'FFFF'`, - `AND (visited OR NOT bookmarked) - AND frecency > 20 - AND url BETWEEN :prefix || 'www.' || :strippedURL AND :prefix || 'www.' || :strippedURL || X'FFFF'` -); - -const QUERY_URL_BOOKMARK = urlQuery( - `AND bookmarked - AND strip_prefix_and_userinfo(url) BETWEEN :strippedURL AND :strippedURL || X'FFFF'`, - `AND bookmarked - AND strip_prefix_and_userinfo(url) BETWEEN 'www.' || :strippedURL AND 'www.' || :strippedURL || X'FFFF'` -); - -const QUERY_URL_PREFIX_BOOKMARK = urlQuery( - `AND bookmarked - AND url BETWEEN :prefix || :strippedURL AND :prefix || :strippedURL || X'FFFF'`, - `AND bookmarked - AND url BETWEEN :prefix || 'www.' || :strippedURL AND :prefix || 'www.' || :strippedURL || X'FFFF'` -); - -const kProtocolsWithIcons = [ - "chrome:", - "moz-extension:", - "about:", - "http:", - "https:", - "ftp:", -]; -function iconHelper(url) { - if (typeof url == "string") { - return kProtocolsWithIcons.some(p => url.startsWith(p)) - ? "page-icon:" + url - : UrlbarUtils.ICON.DEFAULT; - } - if (url && url instanceof URL && kProtocolsWithIcons.includes(url.protocol)) { - return "page-icon:" + url.href; - } - return UrlbarUtils.ICON.DEFAULT; -} - -/** - * Class used to create the provider. - */ -class ProviderAutofill extends UrlbarProvider { - constructor() { - super(); - // Maps the running queries by queryContext. - this.queries = new Map(); - } - - /** - * Returns the name of this provider. - * @returns {string} the name of this provider. - */ - get name() { - return "Autofill"; - } - - /** - * Returns the type of this provider. - * @returns {integer} one of the types from UrlbarUtils.PROVIDER_TYPE.* - */ - get type() { - return UrlbarUtils.PROVIDER_TYPE.HEURISTIC; - } - - /** - * Whether this provider should be invoked for the given context. - * If this method returns false, the providers manager won't start a query - * with this provider, to save on resources. - * @param {UrlbarQueryContext} queryContext The query context object - * @returns {boolean} Whether this provider should be invoked for the search. - */ - async isActive(queryContext) { - // First of all, check for the autoFill pref. - if (!UrlbarPrefs.get("autoFill")) { - return false; - } - - if (!queryContext.allowAutofill) { - return false; - } - - if (queryContext.tokens.length != 1) { - return false; - } - - // autoFill can only cope with history, bookmarks, and about: entries. - if ( - !queryContext.sources.includes(UrlbarUtils.RESULT_SOURCE.HISTORY) && - !queryContext.sources.includes(UrlbarUtils.RESULT_SOURCE.BOOKMARKS) - ) { - return false; - } - - // Autofill doesn't search tags or titles - if ( - queryContext.tokens.some( - t => - t.type == UrlbarTokenizer.TYPE.RESTRICT_TAG || - t.type == UrlbarTokenizer.TYPE.RESTRICT_TITLE - ) - ) { - return false; - } - - [this._strippedPrefix, this._searchString] = UrlbarUtils.stripURLPrefix( - queryContext.searchString - ); - this._strippedPrefix = this._strippedPrefix.toLowerCase(); - - if (!this._searchString || !this._searchString.length) { - return false; - } - - // Don't try to autofill if the search term includes any whitespace. - // This may confuse completeDefaultIndex cause the AUTOCOMPLETE_MATCH - // tokenizer ends up trimming the search string and returning a value - // that doesn't match it, or is even shorter. - if (UrlbarTokenizer.REGEXP_SPACES.test(queryContext.searchString)) { - return false; - } - - // Fetch autofill result now, rather than in startQuery. We do this so the - // muxer doesn't have to wait on autofill for every query, since startQuery - // will be guaranteed to return a result very quickly using this approach. - // Bug 1651101 is filed to improve this behaviour. - let autofilled = await this._getAutofillResult(queryContext); - if (!autofilled || !this._autofillResult) { - return false; - } - - return true; - } - - /** - * Gets the provider's priority. - * @param {UrlbarQueryContext} queryContext The query context object - * @returns {number} The provider's priority for the given query. - */ - getPriority(queryContext) { - // Priority search results are restricting. - if ( - this._autofillResult && - this._autofillResult.type == UrlbarUtils.RESULT_TYPE.SEARCH - ) { - return 1; - } - - return 0; - } - - /** - * Starts querying. - * @param {object} queryContext The query context object - * @param {function} addCallback Callback invoked by the provider to add a new - * result. - * @returns {Promise} resolved when the query stops. - */ - async startQuery(queryContext, addCallback) { - // This serves as the equivalent of checking this.queries.has to see if the - // query has been cancelled, since this._autofillResult is deleted in - // cancelQuery. - if (!this._autofillResult) { - return; - } - - this._autofillResult.heuristic = true; - addCallback(this, this._autofillResult); - delete this._autofillResult; - } - - /** - * Cancels a running query. - * @param {object} queryContext The query context object - */ - cancelQuery(queryContext) { - delete this._autofillResult; - } - - /** - * Obtains the query to search for autofill origin results. - * - * @param {UrlbarQueryContext} queryContext - * @returns {array} consisting of the correctly optimized query to search the - * database with and an object containing the params to bound. - */ - _getOriginQuery(queryContext) { - // At this point, searchString is not a URL with a path; it does not - // contain a slash, except for possibly at the very end. If there is - // trailing slash, remove it when searching here to match the rest of the - // string because it may be an origin. - let searchStr = this._searchString.endsWith("/") - ? this._searchString.slice(0, -1) - : this._searchString; - - let opts = { - query_type: QUERYTYPE.AUTOFILL_ORIGIN, - searchString: searchStr.toLowerCase(), - stddevMultiplier: UrlbarPrefs.get("autoFill.stddevMultiplier"), - }; - if (this._strippedPrefix) { - opts.prefix = this._strippedPrefix; - } - - if ( - queryContext.sources.includes(UrlbarUtils.RESULT_SOURCE.HISTORY) && - queryContext.sources.includes(UrlbarUtils.RESULT_SOURCE.BOOKMARKS) - ) { - return [ - this._strippedPrefix - ? QUERY_ORIGIN_PREFIX_HISTORY_BOOKMARK - : QUERY_ORIGIN_HISTORY_BOOKMARK, - opts, - ]; - } - if (queryContext.sources.includes(UrlbarUtils.RESULT_SOURCE.HISTORY)) { - return [ - this._strippedPrefix - ? QUERY_ORIGIN_PREFIX_HISTORY - : QUERY_ORIGIN_HISTORY, - opts, - ]; - } - if (queryContext.sources.includes(UrlbarUtils.RESULT_SOURCE.BOOKMARKS)) { - return [ - this._strippedPrefix - ? QUERY_ORIGIN_PREFIX_BOOKMARK - : QUERY_ORIGIN_BOOKMARK, - opts, - ]; - } - throw new Error("Either history or bookmark behavior expected"); - } - - /** - * Obtains the query to search for autoFill url results. - * - * @param {UrlbarQueryContext} queryContext - * @returns {array} consisting of the correctly optimized query to search the - * database with and an object containing the params to bound. - */ - _getUrlQuery(queryContext) { - // Try to get the host from the search string. The host is the part of the - // URL up to either the path slash, port colon, or query "?". If the search - // string doesn't look like it begins with a host, then return; it doesn't - // make sense to do a URL query with it. - const urlQueryHostRegexp = /^[^/:?]+/; - let hostMatch = urlQueryHostRegexp.exec(this._searchString); - if (!hostMatch) { - return [null, null]; - } - - let host = hostMatch[0].toLowerCase(); - let revHost = - host - .split("") - .reverse() - .join("") + "."; - - // Build a string that's the URL stripped of its prefix, i.e., the host plus - // everything after the host. Use queryContext.searchString instead of - // this._searchString because this._searchString has had unEscapeURIForUI() - // called on it. It's therefore not necessarily the literal URL. - let strippedURL = queryContext.searchString.trim(); - if (this._strippedPrefix) { - strippedURL = strippedURL.substr(this._strippedPrefix.length); - } - strippedURL = host + strippedURL.substr(host.length); - - let opts = { - query_type: QUERYTYPE.AUTOFILL_URL, - revHost, - strippedURL, - }; - if (this._strippedPrefix) { - opts.prefix = this._strippedPrefix; - } - - if ( - queryContext.sources.includes(UrlbarUtils.RESULT_SOURCE.HISTORY) && - queryContext.sources.includes(UrlbarUtils.RESULT_SOURCE.BOOKMARKS) - ) { - return [ - this._strippedPrefix - ? QUERY_URL_PREFIX_HISTORY_BOOKMARK - : QUERY_URL_HISTORY_BOOKMARK, - opts, - ]; - } - if (queryContext.sources.includes(UrlbarUtils.RESULT_SOURCE.HISTORY)) { - return [ - this._strippedPrefix ? QUERY_URL_PREFIX_HISTORY : QUERY_URL_HISTORY, - opts, - ]; - } - if (queryContext.sources.includes(UrlbarUtils.RESULT_SOURCE.BOOKMARKS)) { - return [ - this._strippedPrefix ? QUERY_URL_PREFIX_BOOKMARK : QUERY_URL_BOOKMARK, - opts, - ]; - } - throw new Error("Either history or bookmark behavior expected"); - } - - /** - * Processes a matched row in the Places database and sets - * this._autofillResult to any matches. - * @param {object} row - * The matched row. - * @param {function} cancel - * A callback to cancel the search. - * @param {UrlbarQueryContext} queryContext - */ - _onResultRow(row, cancel, queryContext) { - let queryType = row.getResultByIndex(QUERYINDEX.QUERYTYPE); - let autofilledValue, finalCompleteValue; - switch (queryType) { - case QUERYTYPE.AUTOFILL_ORIGIN: - autofilledValue = row.getResultByIndex( - QUERYINDEX_ORIGIN.AUTOFILLED_VALUE - ); - finalCompleteValue = row.getResultByIndex(QUERYINDEX_ORIGIN.URL); - break; - case QUERYTYPE.AUTOFILL_URL: - let url = row.getResultByIndex(QUERYINDEX_URL.URL); - let strippedURL = row.getResultByIndex(QUERYINDEX_URL.STRIPPED_URL); - // We autofill urls to-the-next-slash. - // http://mozilla.org/foo/bar/baz will be autofilled to: - // - http://mozilla.org/f[oo/] - // - http://mozilla.org/foo/b[ar/] - // - http://mozilla.org/foo/bar/b[az] - let strippedURLIndex = url.indexOf(strippedURL); - let strippedPrefix = url.substr(0, strippedURLIndex); - let nextSlashIndex = url.indexOf( - "/", - strippedURLIndex + strippedURL.length - 1 - ); - if (nextSlashIndex == -1) { - autofilledValue = url.substr(strippedURLIndex); - } else { - autofilledValue = url.substring(strippedURLIndex, nextSlashIndex + 1); - } - finalCompleteValue = strippedPrefix + autofilledValue; - break; - } - - // We cancel the query right away since we're just looking for a single - // autofill result. - cancel(); - - let [title] = UrlbarUtils.stripPrefixAndTrim(finalCompleteValue, { - stripHttp: true, - trimEmptyQuery: true, - trimSlash: !this._searchString.includes("/"), - }); - let result = new UrlbarResult( - UrlbarUtils.RESULT_TYPE.URL, - UrlbarUtils.RESULT_SOURCE.HISTORY, - ...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, { - title: [title, UrlbarUtils.HIGHLIGHT.TYPED], - url: [finalCompleteValue, UrlbarUtils.HIGHLIGHT.TYPED], - icon: iconHelper(finalCompleteValue), - }) - ); - autofilledValue = - queryContext.searchString + - autofilledValue.substring(this._searchString.length); - result.autofill = { - value: autofilledValue, - selectionStart: queryContext.searchString.length, - selectionEnd: autofilledValue.length, - }; - - this._autofillResult = result; - } - - async _getAutofillResult(queryContext) { - // We may be autofilling an about: link. - this._matchAboutPageForAutofill(queryContext); - if (this._autofillResult) { - return true; - } - - // It may also look like a URL we know from the database. - await this._matchKnownUrl(queryContext); - if (this._autofillResult) { - return true; - } - - // Or it may look like a search engine domain. - await this._matchSearchEngineDomain(queryContext); - if (this._autofillResult) { - return true; - } - - return false; - } - - _matchAboutPageForAutofill(queryContext) { - // Check that the typed query is at least one character longer than the - // about: prefix. - if (this._strippedPrefix != "about:" || !this._searchString) { - return; - } - - for (const aboutUrl of AboutPagesUtils.visibleAboutUrls) { - if (aboutUrl.startsWith(`about:${this._searchString.toLowerCase()}`)) { - let [trimmedUrl] = UrlbarUtils.stripPrefixAndTrim(aboutUrl, { - stripHttp: true, - trimEmptyQuery: true, - trimSlash: !this._searchString.includes("/"), - }); - let result = new UrlbarResult( - UrlbarUtils.RESULT_TYPE.URL, - UrlbarUtils.RESULT_SOURCE.HISTORY, - ...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, { - title: [trimmedUrl, UrlbarUtils.HIGHLIGHT.TYPED], - url: [aboutUrl, UrlbarUtils.HIGHLIGHT.TYPED], - icon: iconHelper(aboutUrl), - }) - ); - let autofilledValue = - queryContext.searchString + - aboutUrl.substring(queryContext.searchString.length); - result.autofill = { - value: autofilledValue, - selectionStart: queryContext.searchString.length, - selectionEnd: autofilledValue.length, - }; - this._autofillResult = result; - return; - } - } - } - - async _matchKnownUrl(queryContext) { - let conn = await PlacesUtils.promiseLargeCacheDBConnection(); - if (!conn) { - return; - } - // If search string looks like an origin, try to autofill against origins. - // Otherwise treat it as a possible URL. When the string has only one slash - // at the end, we still treat it as an URL. - let query, params; - if ( - UrlbarTokenizer.looksLikeOrigin(this._searchString, { - ignoreKnownDomains: true, - }) - ) { - [query, params] = this._getOriginQuery(queryContext); - } else { - [query, params] = this._getUrlQuery(queryContext); - } - - // _getrlQuery doesn't always return a query. - if (query) { - await conn.executeCached(query, params, (row, cancel) => { - this._onResultRow(row, cancel, queryContext); - }); - } - } - - async _matchSearchEngineDomain(queryContext) { - if (!UrlbarPrefs.get("autoFill.searchEngines")) { - return; - } - - // engineForDomainPrefix only matches against engine domains. - // Remove an eventual trailing slash from the search string (without the - // prefix) and check if the resulting string is worth matching. - // Later, we'll verify that the found result matches the original - // searchString and eventually discard it. - let searchStr = this._searchString; - if (searchStr.indexOf("/") == searchStr.length - 1) { - searchStr = searchStr.slice(0, -1); - } - // If the search string looks more like a url than a domain, bail out. - if ( - !UrlbarTokenizer.looksLikeOrigin(searchStr, { ignoreKnownDomains: true }) - ) { - return; - } - - let engine = await UrlbarSearchUtils.engineForDomainPrefix(searchStr); - if (!engine) { - return; - } - let url = engine.searchForm; - let domain = engine.getResultDomain(); - // Verify that the match we got is acceptable. Autofilling "example/" to - // "example.com/" would not be good. - if ( - (this._strippedPrefix && !url.startsWith(this._strippedPrefix)) || - !(domain + "/").includes(this._searchString) - ) { - return; - } - - // The value that's autofilled in the input is the prefix the user typed, if - // any, plus the portion of the engine domain that the user typed. Append a - // trailing slash too, as is usual with autofill. - let value = - this._strippedPrefix + domain.substr(domain.indexOf(searchStr)) + "/"; - - let result = new UrlbarResult( - UrlbarUtils.RESULT_TYPE.SEARCH, - UrlbarUtils.RESULT_SOURCE.SEARCH, - ...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, { - engine: [engine.name, UrlbarUtils.HIGHLIGHT.TYPED], - icon: engine.iconURI ? engine.iconURI.spec : "", - }) - ); - let autofilledValue = - queryContext.searchString + - value.substring(queryContext.searchString.length); - result.autofill = { - value: autofilledValue, - selectionStart: queryContext.searchString.length, - selectionEnd: autofilledValue.length, - }; - this._autofillResult = result; - } -} - -var UrlbarProviderAutofill = new ProviderAutofill(); diff --git a/browser/components/urlbar/UrlbarProviderTokenAliasEngines.jsm b/browser/components/urlbar/UrlbarProviderTokenAliasEngines.jsm index 24ccfb0fb93d..d654b08a061c 100644 --- a/browser/components/urlbar/UrlbarProviderTokenAliasEngines.jsm +++ b/browser/components/urlbar/UrlbarProviderTokenAliasEngines.jsm @@ -14,7 +14,6 @@ const { XPCOMUtils } = ChromeUtils.import( "resource://gre/modules/XPCOMUtils.jsm" ); XPCOMUtils.defineLazyModuleGetters(this, { - UrlbarPrefs: "resource:///modules/UrlbarPrefs.jsm", UrlbarProvider: "resource:///modules/UrlbarUtils.jsm", UrlbarResult: "resource:///modules/UrlbarResult.jsm", UrlbarSearchUtils: "resource:///modules/UrlbarSearchUtils.jsm", @@ -45,7 +44,7 @@ class ProviderTokenAliasEngines extends UrlbarProvider { * @returns {integer} one of the types from UrlbarUtils.PROVIDER_TYPE.* */ get type() { - return UrlbarUtils.PROVIDER_TYPE.HEURISTIC; + return UrlbarUtils.PROVIDER_TYPE.PROFILE; } get PRIORITY() { @@ -61,34 +60,12 @@ class ProviderTokenAliasEngines extends UrlbarProvider { * @returns {boolean} Whether this provider should be invoked for the search. */ async isActive(queryContext) { - // Once the user starts typing a search string after the token, we hand off - // suggestions to UrlbarProviderSearchSuggestions. - if ( - !queryContext.searchString.startsWith("@") || - queryContext.tokens.length != 1 - ) { - return false; - } - - this._engines = await UrlbarSearchUtils.tokenAliasEngines(); - if (!this._engines.length) { - return false; - } - + this._engines = []; if (queryContext.searchString.trim() == "@") { - return true; + this._engines = await UrlbarSearchUtils.tokenAliasEngines(); } - // If there's no engine associated with the searchString, then we don't want - // to block other kinds of results. - if (UrlbarPrefs.get("autoFill") && queryContext.allowAutofill) { - this._autofillResult = this._getAutofillResult(queryContext); - if (this._autofillResult) { - return true; - } - } - - return false; + return this._engines.length; } /** @@ -112,25 +89,19 @@ class ProviderTokenAliasEngines extends UrlbarProvider { return; } - if (queryContext.searchString.trim() == "@") { - for (let { engine, tokenAliases } of this._engines) { - let result = new UrlbarResult( - UrlbarUtils.RESULT_TYPE.SEARCH, - UrlbarUtils.RESULT_SOURCE.SEARCH, - ...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, { - engine: [engine.name, UrlbarUtils.HIGHLIGHT.TYPED], - keyword: [tokenAliases[0], UrlbarUtils.HIGHLIGHT.TYPED], - query: ["", UrlbarUtils.HIGHLIGHT.TYPED], - icon: engine.iconURI ? engine.iconURI.spec : "", - keywordOffer: UrlbarUtils.KEYWORD_OFFER.SHOW, - }) - ); - addCallback(this, result); - } - } else if (this._autofillResult) { - addCallback(this, this._autofillResult); - this.queries.delete(queryContext); - return; + for (let { engine, tokenAliases } of this._engines) { + let result = new UrlbarResult( + UrlbarUtils.RESULT_TYPE.SEARCH, + UrlbarUtils.RESULT_SOURCE.SEARCH, + ...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, { + engine: [engine.name, UrlbarUtils.HIGHLIGHT.TYPED], + keyword: [tokenAliases[0], UrlbarUtils.HIGHLIGHT.TYPED], + query: ["", UrlbarUtils.HIGHLIGHT.TYPED], + icon: engine.iconURI ? engine.iconURI.spec : null, + keywordOffer: UrlbarUtils.KEYWORD_OFFER.SHOW, + }) + ); + addCallback(this, result); } this.queries.delete(queryContext); @@ -150,49 +121,8 @@ class ProviderTokenAliasEngines extends UrlbarProvider { * @param {object} queryContext The query context object */ cancelQuery(queryContext) { - delete this._autofillResult; this.queries.delete(queryContext); } - - _getAutofillResult(queryContext) { - let token = queryContext.tokens[0]; - // The user is typing a specific engine. We should show a heuristic result. - for (let { engine, tokenAliases } of this._engines) { - for (let alias of tokenAliases) { - if (alias.startsWith(token.lowerCaseValue)) { - // We found a specific engine. We will add an autofill result. - let aliasPreservingUserCase = - token.value + alias.substr(token.value.length); - let value = aliasPreservingUserCase + " "; - let result = new UrlbarResult( - UrlbarUtils.RESULT_TYPE.SEARCH, - UrlbarUtils.RESULT_SOURCE.SEARCH, - ...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, { - engine: [engine.name, UrlbarUtils.HIGHLIGHT.TYPED], - keyword: [aliasPreservingUserCase, UrlbarUtils.HIGHLIGHT.TYPED], - query: ["", UrlbarUtils.HIGHLIGHT.TYPED], - icon: engine.iconURI ? engine.iconURI.spec : "", - keywordOffer: UrlbarUtils.KEYWORD_OFFER.HIDE, - // For test interoperabilty with UrlbarProviderSearchSuggestions. - suggestion: undefined, - tailPrefix: undefined, - tail: undefined, - tailOffsetIndex: -1, - isSearchHistory: false, - }) - ); - result.heuristic = true; - result.autofill = { - value, - selectionStart: queryContext.searchString.length, - selectionEnd: value.length, - }; - return result; - } - } - } - return null; - } } var UrlbarProviderTokenAliasEngines = new ProviderTokenAliasEngines(); diff --git a/browser/components/urlbar/UrlbarProviderUnifiedComplete.jsm b/browser/components/urlbar/UrlbarProviderUnifiedComplete.jsm index ea0420964081..76515a15fde7 100644 --- a/browser/components/urlbar/UrlbarProviderUnifiedComplete.jsm +++ b/browser/components/urlbar/UrlbarProviderUnifiedComplete.jsm @@ -84,8 +84,17 @@ class ProviderUnifiedComplete extends UrlbarProvider { acResult, urls ); - for (let result of results) { - addCallback(this, result); + // The Muxer gives UnifiedComplete special status and waits for it to + // return results before sorting them. We need to know that + // UnifiedComplete has finished even if it isn't returning results, so we + // call addCallback with an empty result here, which is something only + // UnifiedComplete is allowed to do. + if (!results.length) { + addCallback(this, null); + } else { + for (let result of results) { + addCallback(this, result); + } } }); this.queries.delete(queryContext); diff --git a/browser/components/urlbar/UrlbarProvidersManager.jsm b/browser/components/urlbar/UrlbarProvidersManager.jsm index ca149c67bf4a..afd5a3e7b8ff 100644 --- a/browser/components/urlbar/UrlbarProvidersManager.jsm +++ b/browser/components/urlbar/UrlbarProvidersManager.jsm @@ -34,7 +34,6 @@ XPCOMUtils.defineLazyGetter(this, "logger", () => var localProviderModules = { UrlbarProviderUnifiedComplete: "resource:///modules/UrlbarProviderUnifiedComplete.jsm", - UrlbarProviderAutofill: "resource:///modules/UrlbarProviderAutofill.jsm", UrlbarProviderHeuristicFallback: "resource:///modules/UrlbarProviderHeuristicFallback.jsm", UrlbarProviderInterventions: @@ -454,9 +453,16 @@ class Query { return; } + let addResult = true; + + if (!result) { + addResult = false; + } + // Check if the result source should be filtered out. Pay attention to the // heuristic result though, that is supposed to be added regardless. if ( + addResult && !this.acceptableSources.includes(result.source) && !result.heuristic && // Treat form history as searches for the purpose of acceptableSources. @@ -464,21 +470,33 @@ class Query { result.source != UrlbarUtils.RESULT_SOURCE.HISTORY || !this.acceptableSources.includes(UrlbarUtils.RESULT_SOURCE.SEARCH)) ) { - return; + addResult = false; } // Filter out javascript results for safety. The provider is supposed to do // it, but we don't want to risk leaking these out. if ( + addResult && result.type != UrlbarUtils.RESULT_TYPE.KEYWORD && result.payload.url && result.payload.url.startsWith("javascript:") && !this.context.searchString.startsWith("javascript:") && UrlbarPrefs.get("filter.javascript") ) { - return; + addResult = false; } + // We wait on UnifiedComplete to return a heuristic result. If it has no + // heuristic result to return, we still need to sort and display results, so + // we follow the usual codepath to muxer.sort. We only offer this for + // UnifiedComplete, so we check the provider's name here. This is a stopgap + // measure until bug 1648468 lands. + if (!addResult) { + if (provider.name == "UnifiedComplete") { + this._notifyResultsFromProvider(provider); + } + return; + } result.providerName = provider.name; result.providerType = provider.type; this.context.results.push(result); @@ -525,7 +543,7 @@ class Query { } _notifyResults() { - this.muxer.sort(this.context); + let sorted = this.muxer.sort(this.context); if (this._heuristicProviderTimer) { this._heuristicProviderTimer.cancel().catch(Cu.reportError); @@ -537,6 +555,10 @@ class Query { this._chunkTimer = null; } + if (!sorted) { + return; + } + // Before the muxer.sort call above, this.context.results should never be // empty since this method is called when results are added. But the muxer // may have excluded one or more results from the final sorted list. For diff --git a/browser/components/urlbar/UrlbarUtils.jsm b/browser/components/urlbar/UrlbarUtils.jsm index 9a7c62e862ef..75b1c9879a27 100644 --- a/browser/components/urlbar/UrlbarUtils.jsm +++ b/browser/components/urlbar/UrlbarUtils.jsm @@ -444,16 +444,6 @@ var UrlbarUtils = { return [submission.uri.spec, submission.postData]; }, - // Ranks a URL prefix from 3 - 0 with the following preferences: - // https:// > https://www. > http:// > http://www. - // Higher is better for the purposes of deduping URLs. - // Returns -1 if the prefix does not match any of the above. - getPrefixRank(prefix) { - return ["http://www.", "http://", "https://www.", "https://"].indexOf( - prefix - ); - }, - /** * Get the number of rows a result should span in the autocomplete dropdown. * @@ -521,58 +511,6 @@ var UrlbarUtils = { } }, - /** - * Strips parts of a URL defined in `options`. - * - * @param {string} spec - * The text to modify. - * @param {object} options - * @param {boolean} options.stripHttp - * Whether to strip http. - * @param {boolean} options.stripHttps - * Whether to strip https. - * @param {boolean} options.stripWww - * Whether to strip `www.`. - * @param {boolean} options.trimSlash - * Whether to trim the trailing slash. - * @param {boolean} options.trimEmptyQuery - * Whether to trim a trailing `?`. - * @param {boolean} options.trimEmptyHash - * Whether to trim a trailing `#`. - * @returns {array} [modified, prefix, suffix] - * modified: {string} The modified spec. - * prefix: {string} The parts stripped from the prefix, if any. - * suffix: {string} The parts trimmed from the suffix, if any. - */ - stripPrefixAndTrim(spec, options = {}) { - let prefix = ""; - let suffix = ""; - if (options.stripHttp && spec.startsWith("http://")) { - spec = spec.slice(7); - prefix = "http://"; - } else if (options.stripHttps && spec.startsWith("https://")) { - spec = spec.slice(8); - prefix = "https://"; - } - if (options.stripWww && spec.startsWith("www.")) { - spec = spec.slice(4); - prefix += "www."; - } - if (options.trimEmptyHash && spec.endsWith("#")) { - spec = spec.slice(0, -1); - suffix = "#" + suffix; - } - if (options.trimEmptyQuery && spec.endsWith("?")) { - spec = spec.slice(0, -1); - suffix = "?" + suffix; - } - if (options.trimSlash && spec.endsWith("/")) { - spec = spec.slice(0, -1); - suffix = "/" + suffix; - } - return [spec, prefix, suffix]; - }, - /** * Used to filter out the javascript protocol from URIs, since we don't * support LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL for those. diff --git a/browser/components/urlbar/UrlbarView.jsm b/browser/components/urlbar/UrlbarView.jsm index 495db4ba017a..aa220626f3fd 100644 --- a/browser/components/urlbar/UrlbarView.jsm +++ b/browser/components/urlbar/UrlbarView.jsm @@ -547,18 +547,6 @@ class UrlbarView { }); } - // If we update the selected element, a new unique ID is generated for it. - // We need to ensure that aria-activedescendant reflects this new ID. - if (this.selectedElement && !this.oneOffSearchButtons.selectedButton) { - let aadID = this.input.inputField.getAttribute("aria-activedescendant"); - if (!aadID) { - Cu.reportError("Selected element but no aria-activedescendant!"); - this._setAccessibleFocus(this.selectedElement); - } else if (!this.document.getElementById(aadID)) { - this._setAccessibleFocus(this.selectedElement); - } - } - this._openPanel(); if (firstResult.heuristic) { diff --git a/browser/components/urlbar/moz.build b/browser/components/urlbar/moz.build index e3808a71a976..556eb701a1e4 100644 --- a/browser/components/urlbar/moz.build +++ b/browser/components/urlbar/moz.build @@ -11,7 +11,6 @@ EXTRA_JS_MODULES += [ 'UrlbarInput.jsm', 'UrlbarMuxerUnifiedComplete.jsm', 'UrlbarPrefs.jsm', - 'UrlbarProviderAutofill.jsm', 'UrlbarProviderExtension.jsm', 'UrlbarProviderHeuristicFallback.jsm', 'UrlbarProviderInterventions.jsm', diff --git a/browser/components/urlbar/tests/unit/head.js b/browser/components/urlbar/tests/unit/head.js index 33085d856260..0093e7c6902c 100644 --- a/browser/components/urlbar/tests/unit/head.js +++ b/browser/components/urlbar/tests/unit/head.js @@ -43,40 +43,6 @@ add_task(async function initXPCShellDependencies() { await UrlbarTestUtils.initXPCShellDependencies(); }); -/** - * Gets the database connection. If the Places connection is invalid it will - * try to create a new connection. - * - * @param [optional] aForceNewConnection - * Forces creation of a new connection to the database. When a - * connection is asyncClosed it cannot anymore schedule async statements, - * though connectionReady will keep returning true (Bug 726990). - * - * @return The database connection or null if unable to get one. - */ -var gDBConn; -function DBConn(aForceNewConnection) { - if (!aForceNewConnection) { - let db = PlacesUtils.history.DBConnection; - if (db.connectionReady) { - return db; - } - } - - // If the Places database connection has been closed, create a new connection. - if (!gDBConn || aForceNewConnection) { - let file = Services.dirsvc.get("ProfD", Ci.nsIFile); - file.append("places.sqlite"); - let dbConn = (gDBConn = Services.storage.openDatabase(file)); - - TestUtils.topicObserved("profile-before-change").then(() => - dbConn.asyncClose() - ); - } - - return gDBConn.connectionReady ? gDBConn : null; -} - /** * @param {string} searchString The search string to insert into the context. * @param {object} properties Overrides for the default values. @@ -313,69 +279,6 @@ async function addTestTailSuggestionsEngine(suggestionsFn = null) { return engine; } -/** - * Helper for tests that generate search results but aren't interested in - * suggestions, such as autofill tests. Installs a test engine and disables - * suggestions. - */ -function testEngine_setup() { - add_task(async function setup() { - await cleanupPlaces(); - let engine = await addTestSuggestionsEngine(); - let oldDefaultEngine = await Services.search.getDefault(); - - registerCleanupFunction(async () => { - Services.prefs.clearUserPref("browser.urlbar.suggest.searches"); - Services.prefs.clearUserPref( - "browser.search.separatePrivateDefault.ui.enabled" - ); - Services.search.setDefault(oldDefaultEngine); - }); - - Services.search.setDefault(engine); - Services.prefs.setBoolPref( - "browser.search.separatePrivateDefault.ui.enabled", - false - ); - Services.prefs.setBoolPref("browser.urlbar.suggest.searches", false); - }); -} - -async function cleanupPlaces() { - Services.prefs.clearUserPref("browser.urlbar.autoFill"); - Services.prefs.clearUserPref("browser.urlbar.autoFill.searchEngines"); - - await PlacesUtils.bookmarks.eraseEverything(); - await PlacesUtils.history.clear(); -} - -/** - * Returns the frecency of a url. - * - * @param {string} aURI The URI or spec to get frecency for. - * @returns {number} the frecency value. - */ -function frecencyForUrl(aURI) { - let url = aURI; - if (aURI instanceof Ci.nsIURI) { - url = aURI.spec; - } else if (aURI instanceof URL) { - url = aURI.href; - } - let stmt = DBConn().createStatement( - "SELECT frecency FROM moz_places WHERE url_hash = hash(?1) AND url = ?1" - ); - stmt.bindByIndex(0, url); - try { - if (!stmt.executeStep()) { - throw new Error("No result for frecency."); - } - return stmt.getInt32(0); - } finally { - stmt.finalize(); - } -} - /** * Creates a UrlbarResult for a bookmark result. * @param {UrlbarQueryContext} queryContext @@ -468,79 +371,6 @@ function makeOmniboxResult( return result; } -/** - * Creates a UrlbarResult for a keyword search result. - * @param {UrlbarQueryContext} queryContext - * The context that this result will be displayed in. - * @param {string} options.uri - * The page URI. - * @param {string} options.keyword - * The page's search keyword. - * @param {string} [options.title] - * The title for the bookmarked keyword page. - * @param {string} [options.iconUri] - * A URI for the engine's icon. - * @param {string} [options.postData] - * The search POST data. - * @param {boolean} [options.heuristic] - * True if this is a heuristic result. Defaults to false. - * @returns {UrlbarResult} - */ -function makeKeywordSearchResult( - queryContext, - { uri, keyword, title, iconUri, postData, heuristic = false } -) { - let result = new UrlbarResult( - UrlbarUtils.RESULT_TYPE.KEYWORD, - UrlbarUtils.RESULT_SOURCE.BOOKMARKS, - ...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, { - title: [title ? title : uri, UrlbarUtils.HIGHLIGHT.TYPED], - url: [uri, UrlbarUtils.HIGHLIGHT.TYPED], - keyword: [keyword, UrlbarUtils.HIGHLIGHT.TYPED], - input: [queryContext.searchString, UrlbarUtils.HIGHLIGHT.TYPED], - postData, - icon: typeof iconUri != "undefined" ? iconUri : `page-icon:${uri}`, - }) - ); - - if (heuristic) { - result.heuristic = heuristic; - } - return result; -} - -/** - * Creates a UrlbarResult for a priority search result. - * @param {UrlbarQueryContext} queryContext - * The context that this result will be displayed in. - * @param {string} [options.engineName] - * The name of the engine providing the suggestion. Leave blank if there - * is no suggestion. - * @param {string} [options.engineIconUri] - * A URI for the engine's icon. - * @param {boolean} [options.heuristic] - * True if this is a heuristic result. Defaults to false. - * @returns {UrlbarResult} - */ -function makePrioritySearchResult( - queryContext, - { engineName, engineIconUri, heuristic } -) { - let result = new UrlbarResult( - UrlbarUtils.RESULT_TYPE.SEARCH, - UrlbarUtils.RESULT_SOURCE.SEARCH, - ...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, { - engine: [engineName, UrlbarUtils.HIGHLIGHT.TYPED], - icon: engineIconUri ? engineIconUri : "", - }) - ); - - if (heuristic) { - result.heuristic = heuristic; - } - return result; -} - /** * Creates a UrlbarResult for a search result. * @param {UrlbarQueryContext} queryContext @@ -563,9 +393,6 @@ function makePrioritySearchResult( * True if this is a heuristic result. Defaults to false. * @param {number} [options.keywordOffer] * A value from UrlbarUtils.KEYWORD_OFFER. - * @param {string} providerName - * The name of the provider offering this result. The test suite will not - * check which provider offered a result unless this option is specified. * @returns {UrlbarResult} */ function makeSearchResult( @@ -581,7 +408,6 @@ function makeSearchResult( engineIconUri, heuristic = false, keywordOffer, - providerName, } ) { if (!keywordOffer) { @@ -627,10 +453,6 @@ function makeSearchResult( result.payload.lowerCaseSuggestion = result.payload.suggestion.toLocaleLowerCase(); } - if (providerName) { - result.providerName = providerName; - } - result.heuristic = heuristic; return result; } @@ -649,14 +471,11 @@ function makeSearchResult( * A URI for the page's icon. * @param {boolean} [options.heuristic] * True if this is a heuristic result. Defaults to false. - * * @param {string} providerName - * The name of the provider offering this result. The test suite will not - * check which provider offered a result unless this option is specified. * @returns {UrlbarResult} */ function makeVisitResult( queryContext, - { title, uri, iconUri, tags = null, heuristic = false, providerName } + { title, uri, iconUri, tags = null, heuristic = false } ) { let payload = { url: [uri, UrlbarUtils.HIGHLIGHT.TYPED], @@ -675,10 +494,6 @@ function makeVisitResult( ...UrlbarResult.payloadAndSimpleHighlights(queryContext.tokens, payload) ); - if (providerName) { - result.providerName = providerName; - } - result.heuristic = heuristic; return result; } @@ -688,26 +503,12 @@ function makeVisitResult( * the param `matches`. * @param {UrlbarQueryContext} context * The context for this query. - * @param {string} [incompleteSearch] - * A search will be fired for this string and then be immediately canceled by - * the query in `context`. - * @param {string} [autofilled] - * The autofilled value in the first result. - * @param {string} [completed] - * The value that would be filled if the autofill result was confirmed. - * Has no effect if `autofilled` is not specified. * @param {array} matches * An array of UrlbarResults. * @param {boolean} [isPrivate] * Set this to `true` to simulate a search in a private window. */ -async function check_results({ - context, - incompleteSearch, - autofilled, - completed, - matches = [], -} = {}) { +async function check_results({ context, matches = [] } = {}) { if (!context) { return; } @@ -729,35 +530,8 @@ async function check_results({ autofillFirstResult() {}, }, }); - - if (incompleteSearch) { - let incompleteContext = createContext(incompleteSearch, { - isPrivate: context.isPrivate, - }); - controller.startQuery(incompleteContext); - } await controller.startQuery(context); - if (autofilled) { - Assert.ok(context.results[0], "There is a first result."); - Assert.ok( - context.results[0].autofill, - "The first result is an autofill result" - ); - Assert.equal( - context.results[0].autofill.value, - autofilled, - "The correct value was autofilled." - ); - if (completed) { - Assert.equal( - context.results[0].payload.url, - completed, - "The completed autofill value is correct." - ); - } - } - Assert.equal( context.results.length, matches.length, @@ -775,14 +549,4 @@ async function check_results({ context.results.map(m => m.heuristic), "Heuristic results are correctly flagged." ); - - matches.forEach((match, i) => { - if (match.providerName) { - Assert.equal( - match.providerName, - context.results[i].providerName, - `The result at index ${i} is from the correct provider.` - ); - } - }); } diff --git a/browser/components/urlbar/tests/unit/test_autofill_about_urls.js b/browser/components/urlbar/tests/unit/test_autofill_about_urls.js deleted file mode 100644 index 4a15aa5e9b1a..000000000000 --- a/browser/components/urlbar/tests/unit/test_autofill_about_urls.js +++ /dev/null @@ -1,100 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -const ENGINE_NAME = "engine-suggestions.xml"; - -testEngine_setup(); - -// "about:ab" should match "about:about" -add_task(async function aboutAb() { - let context = createContext("about:ab", { isPrivate: false }); - await check_results({ - context, - autofilled: "about:about", - completed: "about:about", - matches: [ - makeVisitResult(context, { - uri: "about:about", - title: "about:about", - heuristic: true, - }), - ], - }); -}); - -// "about:Ab" should match "about:about" -add_task(async function aboutAb() { - let context = createContext("about:Ab", { isPrivate: false }); - await check_results({ - context, - autofilled: "about:About", - completed: "about:about", - matches: [ - makeVisitResult(context, { - uri: "about:about", - title: "about:about", - heuristic: true, - }), - ], - }); -}); - -// "about:about" should match "about:about" -add_task(async function aboutAbout() { - let context = createContext("about:about", { isPrivate: false }); - await check_results({ - context, - autofilled: "about:about", - completed: "about:about", - matches: [ - makeVisitResult(context, { - uri: "about:about", - title: "about:about", - heuristic: true, - }), - ], - }); -}); - -// "about:a" should complete to "about:about" and also match "about:addons" -add_task(async function aboutAboutAndAboutAddons() { - let context = createContext("about:a", { isPrivate: false }); - await check_results({ - context, - search: "about:a", - autofilled: "about:about", - completed: "about:about", - matches: [ - makeVisitResult(context, { - uri: "about:about", - title: "about:about", - heuristic: true, - }), - makeVisitResult(context, { - uri: "about:addons", - title: "about:addons", - iconUri: "", - providerName: "UnifiedComplete", - }), - ], - }); -}); - -// "about:" should *not* match anything -add_task(async function aboutColonHasNoMatch() { - let context = createContext("about:", { isPrivate: false }); - await check_results({ - context, - search: "about:", - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - providerName: "HeuristicFallback", - heuristic: true, - }), - ], - }); -}); diff --git a/browser/components/urlbar/tests/unit/test_autofill_functional.js b/browser/components/urlbar/tests/unit/test_autofill_functional.js deleted file mode 100644 index 662cf420b84c..000000000000 --- a/browser/components/urlbar/tests/unit/test_autofill_functional.js +++ /dev/null @@ -1,112 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// Functional tests for inline autocomplete - -add_task(async function setup() { - registerCleanupFunction(async () => { - Services.prefs.clearUserPref("browser.urlbar.suggest.searches"); - }); - - Services.prefs.setBoolPref("browser.urlbar.suggest.searches", false); -}); - -add_task(async function test_urls_order() { - info("Add urls, check for correct order"); - let places = [ - { uri: Services.io.newURI("http://visit1.mozilla.org") }, - { uri: Services.io.newURI("http://visit2.mozilla.org") }, - ]; - await PlacesTestUtils.addVisits(places); - let context = createContext("vis", { isPrivate: false }); - await check_results({ - context, - autofilled: "visit2.mozilla.org/", - completed: "http://visit2.mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: "http://visit2.mozilla.org/", - title: "visit2.mozilla.org", - heuristic: true, - }), - makeVisitResult(context, { - uri: "http://visit1.mozilla.org/", - title: "test visit for http://visit1.mozilla.org/", - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_bookmark_first() { - info("With a bookmark and history, the query result should be the bookmark"); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: Services.io.newURI("http://bookmark1.mozilla.org/"), - }); - await PlacesTestUtils.addVisits( - Services.io.newURI("http://bookmark1.mozilla.org/foo") - ); - let context = createContext("bookmark", { isPrivate: false }); - await check_results({ - context, - autofilled: "bookmark1.mozilla.org/", - completed: "http://bookmark1.mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: "http://bookmark1.mozilla.org/", - title: "bookmark1.mozilla.org", - heuristic: true, - }), - makeVisitResult(context, { - uri: "http://bookmark1.mozilla.org/foo", - title: "test visit for http://bookmark1.mozilla.org/foo", - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_complete_querystring() { - info("Check to make sure we autocomplete after ?"); - await PlacesTestUtils.addVisits( - Services.io.newURI("http://smokey.mozilla.org/foo?bacon=delicious") - ); - let context = createContext("smokey.mozilla.org/foo?", { isPrivate: false }); - await check_results({ - context, - autofilled: "smokey.mozilla.org/foo?bacon=delicious", - completed: "http://smokey.mozilla.org/foo?bacon=delicious", - matches: [ - makeVisitResult(context, { - uri: "http://smokey.mozilla.org/foo?bacon=delicious", - title: "smokey.mozilla.org/foo?bacon=delicious", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_complete_fragment() { - info("Check to make sure we autocomplete after #"); - await PlacesTestUtils.addVisits( - Services.io.newURI("http://smokey.mozilla.org/foo?bacon=delicious#bar") - ); - let context = createContext("smokey.mozilla.org/foo?bacon=delicious#bar", { - isPrivate: false, - }); - await check_results({ - context, - autofilled: "smokey.mozilla.org/foo?bacon=delicious#bar", - completed: "http://smokey.mozilla.org/foo?bacon=delicious#bar", - matches: [ - makeVisitResult(context, { - uri: "http://smokey.mozilla.org/foo?bacon=delicious#bar", - title: "smokey.mozilla.org/foo?bacon=delicious#bar", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); diff --git a/browser/components/urlbar/tests/unit/test_autofill_originsAndQueries.js b/browser/components/urlbar/tests/unit/test_autofill_originsAndQueries.js deleted file mode 100644 index f44e358cf46d..000000000000 --- a/browser/components/urlbar/tests/unit/test_autofill_originsAndQueries.js +++ /dev/null @@ -1,2421 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const ENGINE_NAME = "engine-suggestions.xml"; -const HEURISTIC_FALLBACK_PROVIDERNAME = "HeuristicFallback"; -const UNIFIEDCOMPLETE_PROVIDERNAME = "UnifiedComplete"; - -/** - * Helpful reminder of the `autofilled` and `completed` properties in the - * object passed to check_results: - * autofilled: expected input.value after autofill - * completed: expected input.value after autofill and enter is pressed - * - * `completed` is the URL that the controller sets to input.value, and the URL - * that will ultimately be loaded when you press enter. - **/ - -async function cleanup() { - let suggestPrefs = ["history", "bookmark", "openpage"]; - for (let type of suggestPrefs) { - Services.prefs.clearUserPref("browser.urlbar.suggest." + type); - } - await cleanupPlaces(); -} - -testEngine_setup(); - -let path; -let search; -let searchCase; -let title; -let url; -const host = "example.com"; -let origins; - -function add_autofill_task(callback) { - add_task(async () => { - info("Running subtest with origins disabled."); - origins = false; - path = "/foo"; - search = "example.com/f"; - searchCase = "EXAMPLE.COM/f"; - title = "example.com/foo"; - url = host + path; - await callback(); - - info("Running subtest with origins enabled."); - origins = true; - path = "/"; - search = "ex"; - searchCase = "EX"; - title = "example.com"; - url = host + path; - await callback(); - }); -} - -// "ex" should match http://example.com/. -add_autofill_task(async function basic() { - await PlacesTestUtils.addVisits([ - { - uri: "http://" + url, - }, - ]); - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// "EX" should match http://example.com/. -add_autofill_task(async function basicCase() { - await PlacesTestUtils.addVisits([ - { - uri: "http://" + url, - }, - ]); - let context = createContext(searchCase, { isPrivate: false }); - await check_results({ - context, - autofilled: searchCase + url.substr(searchCase.length), - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// "ex" should match http://www.example.com/. -add_autofill_task(async function noWWWShouldMatchWWW() { - await PlacesTestUtils.addVisits([ - { - uri: "http://www." + url, - }, - ]); - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "http://www." + url, - matches: [ - makeVisitResult(context, { - uri: "http://www." + url, - title: "www." + title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// "EX" should match http://www.example.com/. -add_autofill_task(async function noWWWShouldMatchWWWCase() { - await PlacesTestUtils.addVisits([ - { - uri: "http://www." + url, - }, - ]); - let context = createContext(searchCase, { isPrivate: false }); - await check_results({ - context, - autofilled: searchCase + url.substr(searchCase.length), - completed: "http://www." + url, - matches: [ - makeVisitResult(context, { - uri: "http://www." + url, - title: "www." + title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// "www.ex" should *not* match http://example.com/. -add_autofill_task(async function wwwShouldNotMatchNoWWW() { - await PlacesTestUtils.addVisits([ - { - uri: "http://" + url, - }, - ]); - let context = createContext("www." + search, { isPrivate: false }); - if (origins) { - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - } else { - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: "http://www." + search, - title: "http://www." + search, - iconUri: `page-icon:http://www.${host}/`, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - } - await cleanup(); -}); - -// "http://ex" should match http://example.com/. -add_autofill_task(async function prefix() { - await PlacesTestUtils.addVisits([ - { - uri: "http://" + url, - }, - ]); - let context = createContext("http://" + search, { isPrivate: false }); - await check_results({ - context, - autofilled: "http://" + url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// "HTTP://EX" should match http://example.com/. -add_autofill_task(async function prefixCase() { - await PlacesTestUtils.addVisits([ - { - uri: "http://" + url, - }, - ]); - let context = createContext("HTTP://" + searchCase, { isPrivate: false }); - await check_results({ - context, - autofilled: "HTTP://" + searchCase + url.substr(searchCase.length), - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// "http://ex" should match http://www.example.com/. -add_autofill_task(async function prefixNoWWWShouldMatchWWW() { - await PlacesTestUtils.addVisits([ - { - uri: "http://www." + url, - }, - ]); - let context = createContext("http://" + search, { isPrivate: false }); - await check_results({ - context, - autofilled: "http://" + url, - completed: "http://www." + url, - matches: [ - makeVisitResult(context, { - uri: "http://www." + url, - title: "www." + title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// "HTTP://EX" should match http://www.example.com/. -add_autofill_task(async function prefixNoWWWShouldMatchWWWCase() { - await PlacesTestUtils.addVisits([ - { - uri: "http://www." + url, - }, - ]); - let context = createContext("HTTP://" + searchCase, { isPrivate: false }); - await check_results({ - context, - autofilled: "HTTP://" + searchCase + url.substr(searchCase.length), - completed: "http://www." + url, - matches: [ - makeVisitResult(context, { - uri: "http://www." + url, - title: "www." + title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// "http://www.ex" should *not* match http://example.com/. -add_autofill_task(async function prefixWWWShouldNotMatchNoWWW() { - await PlacesTestUtils.addVisits([ - { - uri: "http://" + url, - }, - ]); - let context = createContext("http://www." + search, { isPrivate: false }); - let prefixedUrl = origins ? `http://www.${search}/` : `http://www.${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://www.${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - await cleanup(); -}); - -// "http://ex" should *not* match https://example.com/. -add_autofill_task(async function httpPrefixShouldNotMatchHTTPS() { - await PlacesTestUtils.addVisits([ - { - uri: "https://" + url, - }, - ]); - let context = createContext("http://" + search, { isPrivate: false }); - let prefixedUrl = origins ? `http://${search}/` : `http://${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "https://" + url, - title: "test visit for https://" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanup(); -}); - -// "ex" should match https://example.com/. -add_autofill_task(async function httpsBasic() { - await PlacesTestUtils.addVisits([ - { - uri: "https://" + url, - }, - ]); - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "https://" + url, - matches: [ - makeVisitResult(context, { - uri: "https://" + url, - title: "https://" + title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// "ex" should match https://www.example.com/. -add_autofill_task(async function httpsNoWWWShouldMatchWWW() { - await PlacesTestUtils.addVisits([ - { - uri: "https://www." + url, - }, - ]); - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "https://www." + url, - matches: [ - makeVisitResult(context, { - uri: "https://www." + url, - title: "https://www." + title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// "www.ex" should *not* match https://example.com/. -add_autofill_task(async function httpsWWWShouldNotMatchNoWWW() { - await PlacesTestUtils.addVisits([ - { - uri: "https://" + url, - }, - ]); - let context = createContext("www." + search, { isPrivate: false }); - if (origins) { - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - } else { - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: "http://www." + search, - title: "http://www." + search, - iconUri: `page-icon:http://www.${host}/`, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - } - await cleanup(); -}); - -// "https://ex" should match https://example.com/. -add_autofill_task(async function httpsPrefix() { - await PlacesTestUtils.addVisits([ - { - uri: "https://" + url, - }, - ]); - let context = createContext("https://" + search, { isPrivate: false }); - await check_results({ - context, - autofilled: "https://" + url, - completed: "https://" + url, - matches: [ - makeVisitResult(context, { - uri: "https://" + url, - title: "https://" + title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// "https://ex" should match https://www.example.com/. -add_autofill_task(async function httpsPrefixNoWWWShouldMatchWWW() { - await PlacesTestUtils.addVisits([ - { - uri: "https://www." + url, - }, - ]); - let context = createContext("https://" + search, { isPrivate: false }); - await check_results({ - context, - autofilled: "https://" + url, - completed: "https://www." + url, - matches: [ - makeVisitResult(context, { - uri: "https://www." + url, - title: "https://www." + title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// "https://www.ex" should *not* match https://example.com/. -add_autofill_task(async function httpsPrefixWWWShouldNotMatchNoWWW() { - await PlacesTestUtils.addVisits([ - { - uri: "https://" + url, - }, - ]); - let context = createContext("https://www." + search, { isPrivate: false }); - let prefixedUrl = origins - ? `https://www.${search}/` - : `https://www.${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:https://www.${host}/`, - providerame: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - await cleanup(); -}); - -// "https://ex" should *not* match http://example.com/. -add_autofill_task(async function httpsPrefixShouldNotMatchHTTP() { - await PlacesTestUtils.addVisits([ - { - uri: "http://" + url, - }, - ]); - let context = createContext("https://" + search, { isPrivate: false }); - let prefixedUrl = origins ? `https://${search}/` : `https://${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:https://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://" + url, - title: "test visit for http://" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanup(); -}); - -// "https://ex" should *not* match http://example.com/, even if the latter is -// more frecent and both could be autofilled. -add_autofill_task(async function httpsPrefixShouldNotMatchMoreFrecentHTTP() { - await PlacesTestUtils.addVisits([ - { - uri: "http://" + url, - transition: PlacesUtils.history.TRANSITIONS.TYPED, - }, - { - uri: "http://" + url, - }, - { - uri: "https://" + url, - transition: PlacesUtils.history.TRANSITIONS.TYPED, - }, - { - uri: "http://otherpage", - }, - ]); - let context = createContext("https://" + search, { isPrivate: false }); - await check_results({ - context, - autofilled: "https://" + url, - completed: "https://" + url, - matches: [ - makeVisitResult(context, { - uri: "https://" + url, - title: "https://" + title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// Autofill should respond to frecency changes. -add_autofill_task(async function frecency() { - // Start with an http visit. It should be completed. - await PlacesTestUtils.addVisits([ - { - uri: "http://" + url, - }, - ]); - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - - // Add two https visits. https should now be completed. - for (let i = 0; i < 2; i++) { - await PlacesTestUtils.addVisits([{ uri: "https://" + url }]); - } - context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "https://" + url, - matches: [ - makeVisitResult(context, { - uri: "https://" + url, - title: "https://" + title, - heuristic: true, - }), - ], - }); - - // Add two more http visits, three total. http should now be completed - // again. - for (let i = 0; i < 2; i++) { - await PlacesTestUtils.addVisits([{ uri: "http://" + url }]); - } - context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - makeVisitResult(context, { - uri: "https://" + url, - title: "test visit for https://" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - - // Add four www https visits. www https should now be completed. - for (let i = 0; i < 4; i++) { - await PlacesTestUtils.addVisits([{ uri: "https://www." + url }]); - } - context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "https://www." + url, - matches: [ - makeVisitResult(context, { - uri: "https://www." + url, - title: "https://www." + title, - heuristic: true, - }), - makeVisitResult(context, { - uri: "https://" + url, - title: "test visit for https://" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - - // Remove the www https page. - await PlacesUtils.history.remove(["https://www." + url]); - - // http should now be completed again. - context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - makeVisitResult(context, { - uri: "https://" + url, - title: "test visit for https://" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - - // Remove the http page. - await PlacesUtils.history.remove(["http://" + url]); - - // https should now be completed again. - context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "https://" + url, - matches: [ - makeVisitResult(context, { - uri: "https://" + url, - title: "https://" + title, - heuristic: true, - }), - ], - }); - - // Add a visit with a different host so that "ex" doesn't autofill it. - // https://example.com/ should still have a higher frecency though, so it - // should still be autofilled. - await PlacesTestUtils.addVisits([{ uri: "https://not-" + url }]); - context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "https://" + url, - matches: [ - makeVisitResult(context, { - uri: "https://" + url, - title: "https://" + title, - heuristic: true, - }), - makeVisitResult(context, { - uri: "https://not-" + url, - title: "test visit for https://not-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - - // Now add 10 more visits to the different host so that the frecency of - // https://example.com/ falls below the autofill threshold. It should not - // be autofilled now. - for (let i = 0; i < 10; i++) { - await PlacesTestUtils.addVisits([{ uri: "https://not-" + url }]); - } - - // In the `origins` case, the failure to make an autofill - // match means UnifiedComplete should not create a heuristic result. In the - // `!origins` case, autofill should still happen since there's no threshold - // comparison. - context = createContext(search, { isPrivate: false }); - if (origins) { - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "https://not-" + url, - title: "test visit for https://not-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "https://" + url, - title: "test visit for https://" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - } else { - await check_results({ - context, - autofilled: url, - completed: "https://" + url, - matches: [ - makeVisitResult(context, { - uri: "https://" + url, - title: "https://" + title, - heuristic: true, - }), - makeVisitResult(context, { - uri: "https://not-" + url, - title: "test visit for https://not-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - } - - // Remove the visits to the different host. - await PlacesUtils.history.remove(["https://not-" + url]); - - // https should be completed again. - context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "https://" + url, - matches: [ - makeVisitResult(context, { - uri: "https://" + url, - title: "https://" + title, - heuristic: true, - }), - ], - }); - - // Remove the https visits. - await PlacesUtils.history.remove(["https://" + url]); - - // Now nothing should be completed. - context = createContext(search, { isPrivate: false }); - if (origins) { - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - } else { - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: "http://" + search, - title: "http://" + search, - iconUri: `page-icon:http://${host}/`, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - } - - await cleanup(); -}); - -// Bookmarked places should always be autofilled, even when they don't meet -// the threshold. -add_autofill_task(async function bookmarkBelowThreshold() { - // Add some visits to a URL so that the origin autofill threshold is large. - for (let i = 0; i < 3; i++) { - await PlacesTestUtils.addVisits([ - { - uri: "http://not-" + url, - }, - ]); - } - - // Now bookmark another URL. - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://" + url, - }); - - // Make sure the bookmarked origin and place frecencies are below the - // threshold so that the origin/URL otherwise would not be autofilled. - let placeFrecency = await PlacesTestUtils.fieldInDB( - "http://" + url, - "frecency" - ); - let originFrecency = await getOriginFrecency("http://", host); - let threshold = await getOriginAutofillThreshold(); - Assert.ok( - placeFrecency < threshold, - `Place frecency should be below the threshold: ` + - `placeFrecency=${placeFrecency} threshold=${threshold}` - ); - Assert.ok( - originFrecency < threshold, - `Origin frecency should be below the threshold: ` + - `originFrecency=${originFrecency} threshold=${threshold}` - ); - - // The bookmark should be autofilled. - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - makeVisitResult(context, { - uri: "http://not-" + url, - title: "test visit for http://not-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - - await cleanup(); -}); - -// Bookmarked places should be autofilled when they *do* meet the threshold. -add_autofill_task(async function bookmarkAboveThreshold() { - // Bookmark a URL. - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://" + url, - }); - - // The frecencies of the place and origin should be >= the threshold. In - // fact they should be the same as the threshold since the place is the only - // place in the database. - let placeFrecency = await PlacesTestUtils.fieldInDB( - "http://" + url, - "frecency" - ); - let originFrecency = await getOriginFrecency("http://", host); - let threshold = await getOriginAutofillThreshold(); - Assert.equal(placeFrecency, threshold); - Assert.equal(originFrecency, threshold); - - // The bookmark should be autofilled. - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - - await cleanup(); -}); - -// Bookmark a page and then clear history. The bookmarked origin/URL should -// be autofilled even though its frecency is <= 0 since the autofill threshold -// is 0. -add_autofill_task(async function zeroThreshold() { - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://" + url, - }); - - await PlacesUtils.history.clear(); - - // Make sure the place's frecency is <= 0. (It will be reset to -1 on the - // history.clear() above, and then on idle it will be reset to 0. xpcshell - // tests disable the idle service, so in practice it should always be -1, - // but in order to avoid possible intermittent failures in the future, don't - // assume that.) - let placeFrecency = await PlacesTestUtils.fieldInDB( - "http://" + url, - "frecency" - ); - Assert.ok(placeFrecency <= 0); - - // Make sure the origin's frecency is 0. - let originFrecency = await getOriginFrecency("http://", host); - Assert.equal(originFrecency, 0); - - // Make sure the autofill threshold is 0. - let threshold = await getOriginAutofillThreshold(); - Assert.equal(threshold, 0); - - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = false -// suggest.bookmark = true -// search for: visit -// prefix search: no -// prefix matches search: n/a -// origin matches search: yes -// -// Expected result: -// should autofill: no -add_autofill_task(async function suggestHistoryFalse_visit() { - await PlacesTestUtils.addVisits("http://" + url); - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); - context = createContext(search, { isPrivate: false }); - if (origins) { - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - } else { - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: "http://" + search, - title: "http://" + search, - iconUri: `page-icon:http://${host}/`, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - } - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = false -// suggest.bookmark = true -// search for: visit -// prefix search: yes -// prefix matches search: yes -// origin matches search: yes -// -// Expected result: -// should autofill: no -add_autofill_task(async function suggestHistoryFalse_visit_prefix() { - await PlacesTestUtils.addVisits("http://" + url); - let context = createContext("http://" + search, { isPrivate: false }); - await check_results({ - context, - autofilled: "http://" + url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); - context = createContext(search, { isPrivate: false }); - if (origins) { - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - } else { - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: "http://" + search, - title: "http://" + search, - iconUri: `page-icon:http://${host}/`, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - } - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = false -// suggest.bookmark = true -// search for: bookmark -// prefix search: no -// prefix matches search: n/a -// origin matches search: yes -// -// Expected result: -// should autofill: yes -add_autofill_task(async function suggestHistoryFalse_bookmark_0() { - // Add the bookmark. - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://" + url, - }); - - // Make the bookmark fall below the autofill frecency threshold so we ensure - // the bookmark is always autofilled in this case, even if it doesn't meet - // the threshold. - let meetsThreshold = true; - while (meetsThreshold) { - // Add a visit to another origin to boost the threshold. - await PlacesTestUtils.addVisits("http://foo-" + url); - let originFrecency = await getOriginFrecency("http://", host); - let threshold = await getOriginAutofillThreshold(); - meetsThreshold = threshold <= originFrecency; - } - - // At this point, the bookmark doesn't meet the threshold, but it should - // still be autofilled. - let originFrecency = await getOriginFrecency("http://", host); - let threshold = await getOriginAutofillThreshold(); - Assert.ok(originFrecency < threshold); - - Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = false -// suggest.bookmark = true -// search for: bookmark -// prefix search: no -// prefix matches search: n/a -// origin matches search: no -// -// Expected result: -// should autofill: no -add_autofill_task(async function suggestHistoryFalse_bookmark_1() { - Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://non-matching-" + url, - }); - let context = createContext(search, { isPrivate: false }); - let matches = [ - makeBookmarkResult(context, { - uri: "http://non-matching-" + url, - title: "A bookmark", - }), - ]; - if (origins) { - matches.unshift( - makeSearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }) - ); - } else { - matches.unshift( - makeVisitResult(context, { - uri: "http://" + search, - title: "http://" + search, - iconUri: `page-icon:http://${host}/`, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }) - ); - } - await check_results({ - context, - matches, - }); - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = false -// suggest.bookmark = true -// search for: bookmark -// prefix search: yes -// prefix matches search: yes -// origin matches search: yes -// -// Expected result: -// should autofill: yes -add_autofill_task(async function suggestHistoryFalse_bookmark_prefix_0() { - // Add the bookmark. - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://" + url, - }); - - // Make the bookmark fall below the autofill frecency threshold so we ensure - // the bookmark is always autofilled in this case, even if it doesn't meet - // the threshold. - let meetsThreshold = true; - while (meetsThreshold) { - // Add a visit to another origin to boost the threshold. - await PlacesTestUtils.addVisits("http://foo-" + url); - let originFrecency = await getOriginFrecency("http://", host); - let threshold = await getOriginAutofillThreshold(); - meetsThreshold = threshold <= originFrecency; - } - - // At this point, the bookmark doesn't meet the threshold, but it should - // still be autofilled. - let originFrecency = await getOriginFrecency("http://", host); - let threshold = await getOriginAutofillThreshold(); - Assert.ok(originFrecency < threshold); - - Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://" + url, - }); - let context = createContext("http://" + search, { isPrivate: false }); - await check_results({ - context, - autofilled: "http://" + url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = false -// suggest.bookmark = true -// search for: bookmark -// prefix search: yes -// prefix matches search: no -// origin matches search: yes -// -// Expected result: -// should autofill: no -add_autofill_task(async function suggestHistoryFalse_bookmark_prefix_1() { - Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "ftp://" + url, - }); - let context = createContext("http://" + search, { isPrivate: false }); - let prefixedUrl = origins ? `http://${search}/` : `http://${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeBookmarkResult(context, { - uri: "ftp://" + url, - title: "A bookmark", - }), - ], - }); - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = false -// suggest.bookmark = true -// search for: bookmark -// prefix search: yes -// prefix matches search: yes -// origin matches search: no -// -// Expected result: -// should autofill: no -add_autofill_task(async function suggestHistoryFalse_bookmark_prefix_2() { - Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://non-matching-" + url, - }); - let context = createContext("http://" + search, { isPrivate: false }); - let prefixedUrl = origins ? `http://${search}/` : `http://${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeBookmarkResult(context, { - uri: "http://non-matching-" + url, - title: "A bookmark", - }), - ], - }); - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = false -// suggest.bookmark = true -// search for: bookmark -// prefix search: yes -// prefix matches search: no -// origin matches search: no -// -// Expected result: -// should autofill: no -add_autofill_task(async function suggestHistoryFalse_bookmark_prefix_3() { - Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "ftp://non-matching-" + url, - }); - let context = createContext("http://" + search, { isPrivate: false }); - let prefixedUrl = origins ? `http://${search}/` : `http://${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeBookmarkResult(context, { - uri: "ftp://non-matching-" + url, - title: "A bookmark", - }), - ], - }); - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visit -// prefix search: no -// prefix matches search: n/a -// origin matches search: yes -// -// Expected result: -// should autofill: yes -add_autofill_task(async function suggestBookmarkFalse_visit_0() { - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - await PlacesTestUtils.addVisits("http://" + url); - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visit -// prefix search: no -// prefix matches search: n/a -// origin matches search: no -// -// Expected result: -// should autofill: no -add_autofill_task(async function suggestBookmarkFalse_visit_1() { - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - await PlacesTestUtils.addVisits("http://non-matching-" + url); - let context = createContext(search, { isPrivate: false }); - let prefixedUrl = origins ? `http://${search}/` : `http://${search}`; - let matches = [ - makeVisitResult(context, { - uri: "http://non-matching-" + url, - title: "test visit for http://non-matching-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ]; - if (origins) { - matches.unshift( - makeSearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }) - ); - } else { - matches.unshift( - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }) - ); - } - await check_results({ - context, - matches, - }); - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visit -// prefix search: yes -// prefix matches search: yes -// origin matches search: yes -// -// Expected result: -// should autofill: yes -add_autofill_task(async function suggestBookmarkFalse_visit_prefix_0() { - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - await PlacesTestUtils.addVisits("http://" + url); - let context = createContext("http://" + search, { isPrivate: false }); - await check_results({ - context, - autofilled: "http://" + url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visit -// prefix search: yes -// prefix matches search: no -// origin matches search: yes -// -// Expected result: -// should autofill: no -add_autofill_task(async function suggestBookmarkFalse_visit_prefix_1() { - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - await PlacesTestUtils.addVisits("ftp://" + url); - let context = createContext("http://" + search, { isPrivate: false }); - let prefixedUrl = origins ? `http://${search}/` : `http://${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "ftp://" + url, - title: "test visit for ftp://" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visit -// prefix search: yes -// prefix matches search: yes -// origin matches search: no -// -// Expected result: -// should autofill: no -add_autofill_task(async function suggestBookmarkFalse_visit_prefix_2() { - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - await PlacesTestUtils.addVisits("http://non-matching-" + url); - let context = createContext("http://" + search, { isPrivate: false }); - let prefixedUrl = origins ? `http://${search}/` : `http://${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://non-matching-" + url, - title: "test visit for http://non-matching-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visit -// prefix search: yes -// prefix matches search: no -// origin matches search: no -// -// Expected result: -// should autofill: no -add_autofill_task(async function suggestBookmarkFalse_visit_prefix_3() { - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - await PlacesTestUtils.addVisits("ftp://non-matching-" + url); - let context = createContext("http://" + search, { isPrivate: false }); - let prefixedUrl = origins ? `http://${search}/` : `http://${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "ftp://non-matching-" + url, - title: "test visit for ftp://non-matching-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: unvisited bookmark -// prefix search: no -// prefix matches search: n/a -// origin matches search: yes -// -// Expected result: -// should autofill: no -add_autofill_task(async function suggestBookmarkFalse_unvisitedBookmark() { - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://" + url, - }); - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - context = createContext(search, { isPrivate: false }); - if (origins) { - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - } else { - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: "http://" + search, - title: "http://" + search, - iconUri: `page-icon:http://${host}/`, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - } - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: unvisited bookmark -// prefix search: yes -// prefix matches search: yes -// origin matches search: yes -// -// Expected result: -// should autofill: no -add_autofill_task( - async function suggestBookmarkFalse_unvisitedBookmark_prefix_0() { - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://" + url, - }); - let context = createContext("http://" + search, { isPrivate: false }); - await check_results({ - context, - autofilled: "http://" + url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - context = createContext("http://" + search, { isPrivate: false }); - let prefixedUrl = origins ? `http://${search}/` : `http://${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - await cleanup(); - } -); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: unvisited bookmark -// prefix search: yes -// prefix matches search: no -// origin matches search: yes -// -// Expected result: -// should autofill: no -add_autofill_task( - async function suggestBookmarkFalse_unvisitedBookmark_prefix_1() { - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "ftp://" + url, - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - let context = createContext("http://" + search, { isPrivate: false }); - let prefixedUrl = origins ? `http://${search}/` : `http://${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - await cleanup(); - } -); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: unvisited bookmark -// prefix search: yes -// prefix matches search: yes -// origin matches search: no -// -// Expected result: -// should autofill: no -add_autofill_task( - async function suggestBookmarkFalse_unvisitedBookmark_prefix_2() { - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://non-matching-" + url, - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - let context = createContext("http://" + search, { isPrivate: false }); - let prefixedUrl = origins ? `http://${search}/` : `http://${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - await cleanup(); - } -); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: unvisited bookmark -// prefix search: yes -// prefix matches search: no -// origin matches search: no -// -// Expected result: -// should autofill: no -add_autofill_task( - async function suggestBookmarkFalse_unvisitedBookmark_prefix_3() { - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "ftp://non-matching-" + url, - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - let context = createContext("http://" + search, { isPrivate: false }); - let prefixedUrl = origins ? `http://${search}/` : `http://${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - await cleanup(); - } -); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visited bookmark above autofill threshold -// prefix search: no -// prefix matches search: n/a -// origin matches search: yes -// -// Expected result: -// should autofill: yes -add_autofill_task(async function suggestBookmarkFalse_visitedBookmark_above() { - await PlacesTestUtils.addVisits("http://" + url); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://" + url, - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visited bookmark above autofill threshold -// prefix search: yes -// prefix matches search: yes -// origin matches search: yes -// -// Expected result: -// should autofill: yes -add_autofill_task( - async function suggestBookmarkFalse_visitedBookmarkAbove_prefix_0() { - await PlacesTestUtils.addVisits("http://" + url); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://" + url, - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - let context = createContext("http://" + search, { isPrivate: false }); - await check_results({ - context, - autofilled: "http://" + url, - completed: "http://" + url, - matches: [ - makeVisitResult(context, { - uri: "http://" + url, - title, - heuristic: true, - }), - ], - }); - await cleanup(); - } -); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visited bookmark above autofill threshold -// prefix search: yes -// prefix matches search: no -// origin matches search: yes -// -// Expected result: -// should autofill: no -add_autofill_task( - async function suggestBookmarkFalse_visitedBookmarkAbove_prefix_1() { - await PlacesTestUtils.addVisits("ftp://" + url); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "ftp://" + url, - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - let context = createContext("http://" + search, { isPrivate: false }); - let prefixedUrl = origins ? `http://${search}/` : `http://${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeBookmarkResult(context, { - uri: "ftp://" + url, - title: "A bookmark", - }), - ], - }); - await cleanup(); - } -); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visited bookmark above autofill threshold -// prefix search: yes -// prefix matches search: yes -// origin matches search: no -// -// Expected result: -// should autofill: no -add_autofill_task( - async function suggestBookmarkFalse_visitedBookmarkAbove_prefix_2() { - await PlacesTestUtils.addVisits("http://non-matching-" + url); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://non-matching-" + url, - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - let context = createContext("http://" + search, { isPrivate: false }); - let prefixedUrl = origins ? `http://${search}/` : `http://${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeBookmarkResult(context, { - uri: "http://non-matching-" + url, - title: "A bookmark", - }), - ], - }); - await cleanup(); - } -); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visited bookmark above autofill threshold -// prefix search: yes -// prefix matches search: no -// origin matches search: no -// -// Expected result: -// should autofill: no -add_autofill_task( - async function suggestBookmarkFalse_visitedBookmarkAbove_prefix_3() { - await PlacesTestUtils.addVisits("ftp://non-matching-" + url); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "ftp://non-matching-" + url, - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - let context = createContext("http://" + search, { isPrivate: false }); - let prefixedUrl = origins ? `http://${search}/` : `http://${search}`; - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: prefixedUrl, - title: prefixedUrl, - heuristic: true, - iconUri: origins ? "" : `page-icon:http://${host}/`, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeBookmarkResult(context, { - uri: "ftp://non-matching-" + url, - title: "A bookmark", - }), - ], - }); - await cleanup(); - } -); - -// The following suggestBookmarkFalse_visitedBookmarkBelow* tests are similar -// to the suggestBookmarkFalse_visitedBookmarkAbove* tests, but instead of -// checking visited bookmarks above the autofill threshold, they check visited -// bookmarks below the threshold. These tests don't make sense for URL -// queries (as opposed to origin queries) because URL queries don't use the -// same autofill threshold, so we skip them when !origins. - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visited bookmark below autofill threshold -// prefix search: no -// prefix matches search: n/a -// origin matches search: yes -// -// Expected result: -// should autofill: no -add_autofill_task(async function suggestBookmarkFalse_visitedBookmarkBelow() { - if (!origins) { - // See comment above suggestBookmarkFalse_visitedBookmarkBelow. - return; - } - // First, make sure that `url` is below the autofill threshold. - await PlacesTestUtils.addVisits("http://" + url); - for (let i = 0; i < 3; i++) { - await PlacesTestUtils.addVisits("http://some-other-" + url); - } - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://some-other-" + url, - title: "test visit for http://some-other-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://" + url, - title: "test visit for http://" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - // Now bookmark it and set suggest.bookmark to false. - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://" + url, - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - context = createContext(search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://some-other-" + url, - title: "test visit for http://some-other-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://" + url, - title: "A bookmark", - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanup(); -}); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visited bookmark below autofill threshold -// prefix search: yes -// prefix matches search: yes -// origin matches search: yes -// -// Expected result: -// should autofill: no -add_autofill_task( - async function suggestBookmarkFalse_visitedBookmarkBelow_prefix_0() { - if (!origins) { - // See comment above suggestBookmarkFalse_visitedBookmarkBelow. - return; - } - // First, make sure that `url` is below the autofill threshold. - await PlacesTestUtils.addVisits("http://" + url); - for (let i = 0; i < 3; i++) { - await PlacesTestUtils.addVisits("http://some-other-" + url); - } - let context = createContext("http://" + search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: `http://${search}/`, - title: `http://${search}/`, - heuristic: true, - iconUri: "", - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://some-other-" + url, - title: "test visit for http://some-other-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://" + url, - title: "test visit for http://" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - // Now bookmark it and set suggest.bookmark to false. - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://" + url, - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - context = createContext("http://" + search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: `http://${search}/`, - title: `http://${search}/`, - heuristic: true, - iconUri: "", - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://some-other-" + url, - title: "test visit for http://some-other-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://" + url, - title: "A bookmark", - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanup(); - } -); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visited bookmark below autofill threshold -// prefix search: yes -// prefix matches search: no -// origin matches search: yes -// -// Expected result: -// should autofill: no -add_autofill_task( - async function suggestBookmarkFalse_visitedBookmarkBelow_prefix_1() { - if (!origins) { - // See comment above suggestBookmarkFalse_visitedBookmarkBelow. - return; - } - // First, make sure that `url` is below the autofill threshold. - await PlacesTestUtils.addVisits("ftp://" + url); - for (let i = 0; i < 3; i++) { - await PlacesTestUtils.addVisits("ftp://some-other-" + url); - } - let context = createContext("http://" + search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: `http://${search}/`, - title: `http://${search}/`, - heuristic: true, - iconUri: "", - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "ftp://some-other-" + url, - title: "test visit for ftp://some-other-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "ftp://" + url, - title: "test visit for ftp://" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - // Now bookmark it and set suggest.bookmark to false. - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "ftp://" + url, - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - context = createContext("http://" + search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: `http://${search}/`, - title: `http://${search}/`, - heuristic: true, - iconUri: "", - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "ftp://some-other-" + url, - title: "test visit for ftp://some-other-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "ftp://" + url, - title: "A bookmark", - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanup(); - } -); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visited bookmark below autofill threshold -// prefix search: yes -// prefix matches search: yes -// origin matches search: no -// -// Expected result: -// should autofill: no -add_autofill_task( - async function suggestBookmarkFalse_visitedBookmarkBelow_prefix_2() { - if (!origins) { - // See comment above suggestBookmarkFalse_visitedBookmarkBelow. - return; - } - // First, make sure that `url` is below the autofill threshold. - await PlacesTestUtils.addVisits("http://non-matching-" + url); - for (let i = 0; i < 3; i++) { - await PlacesTestUtils.addVisits("http://some-other-" + url); - } - let context = createContext("http://" + search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: `http://${search}/`, - title: `http://${search}/`, - heuristic: true, - iconUri: "", - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://some-other-" + url, - title: "test visit for http://some-other-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://non-matching-" + url, - title: "test visit for http://non-matching-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - // Now bookmark it and set suggest.bookmark to false. - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "http://non-matching-" + url, - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - context = createContext("http://" + search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: `http://${search}/`, - title: `http://${search}/`, - heuristic: true, - iconUri: "", - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://some-other-" + url, - title: "test visit for http://some-other-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://non-matching-" + url, - title: "A bookmark", - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanup(); - } -); - -// Tests interaction between the suggest.history and suggest.bookmark prefs. -// -// Config: -// suggest.history = true -// suggest.bookmark = false -// search for: visited bookmark below autofill threshold -// prefix search: yes -// prefix matches search: no -// origin matches search: no -// -// Expected result: -// should autofill: no -add_autofill_task( - async function suggestBookmarkFalse_visitedBookmarkBelow_prefix_3() { - if (!origins) { - // See comment above suggestBookmarkFalse_visitedBookmarkBelow. - return; - } - // First, make sure that `url` is below the autofill threshold. - await PlacesTestUtils.addVisits("ftp://non-matching-" + url); - for (let i = 0; i < 3; i++) { - await PlacesTestUtils.addVisits("ftp://some-other-" + url); - } - let context = createContext("http://" + search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: `http://${search}/`, - title: `http://${search}/`, - heuristic: true, - iconUri: "", - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "ftp://some-other-" + url, - title: "test visit for ftp://some-other-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "ftp://non-matching-" + url, - title: "test visit for ftp://non-matching-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - // Now bookmark it and set suggest.bookmark to false. - await PlacesTestUtils.addBookmarkWithDetails({ - uri: "ftp://non-matching-" + url, - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); - context = createContext("http://" + search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: `http://${search}/`, - title: `http://${search}/`, - heuristic: true, - iconUri: "", - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "ftp://some-other-" + url, - title: "test visit for ftp://some-other-" + url, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "ftp://non-matching-" + url, - title: "A bookmark", - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanup(); - } -); -// } - -/** - * Returns the frecency of an origin. - * - * @param {string} prefix - * The origin's prefix, e.g., "http://". - * @param {string} aHost - * The origin's host. - * @returns {number} The origin's frecency. - */ -async function getOriginFrecency(prefix, aHost) { - let db = await PlacesUtils.promiseDBConnection(); - let rows = await db.execute( - ` - SELECT frecency - FROM moz_origins - WHERE prefix = :prefix AND host = :host - `, - { prefix, host: aHost } - ); - Assert.equal(rows.length, 1); - return rows[0].getResultByIndex(0); -} - -/** - * Returns the origin frecency stats. - * - * @returns {object} - * An object { count, sum, squares }. - */ -async function getOriginFrecencyStats() { - let db = await PlacesUtils.promiseDBConnection(); - let rows = await db.execute(` - SELECT - IFNULL((SELECT value FROM moz_meta WHERE key = 'origin_frecency_count'), 0), - IFNULL((SELECT value FROM moz_meta WHERE key = 'origin_frecency_sum'), 0), - IFNULL((SELECT value FROM moz_meta WHERE key = 'origin_frecency_sum_of_squares'), 0) - `); - let count = rows[0].getResultByIndex(0); - let sum = rows[0].getResultByIndex(1); - let squares = rows[0].getResultByIndex(2); - return { count, sum, squares }; -} - -/** - * Returns the origin autofill frecency threshold. - * - * @returns {number} - * The threshold. - */ -async function getOriginAutofillThreshold() { - let { count, sum, squares } = await getOriginFrecencyStats(); - if (!count) { - return 0; - } - if (count == 1) { - return sum; - } - let stddevMultiplier = UrlbarPrefs.get("autoFill.stddevMultiplier"); - return ( - sum / count + - stddevMultiplier * Math.sqrt((squares - (sum * sum) / count) / count) - ); -} diff --git a/browser/components/urlbar/tests/unit/test_autofill_search_engines.js b/browser/components/urlbar/tests/unit/test_autofill_search_engines.js deleted file mode 100644 index f2d9f2ab6209..000000000000 --- a/browser/components/urlbar/tests/unit/test_autofill_search_engines.js +++ /dev/null @@ -1,232 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// The autoFill.searchEngines pref autofills the domains of engines registered -// with the search service. That's what this test checks. It's a different -// path in UnifiedComplete.js from normal moz_places autofill, which is tested -// in test_autofill_origins.js and test_autofill_urls.js. - -"use strict"; - -const ENGINE_NAME = "TestEngine"; - -add_task(async function searchEngines() { - Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); - Services.prefs.setBoolPref("browser.urlbar.suggest.searches", false); - Services.prefs.setBoolPref( - "browser.search.separatePrivateDefault.ui.enabled", - false - ); - - registerCleanupFunction(() => { - Services.prefs.clearUserPref("browser.urlbar.autoFill.searchEngines"); - Services.prefs.clearUserPref("browser.urlbar.suggest.searches"); - Services.prefs.clearUserPref( - "browser.search.separatePrivateDefault.ui.enabled" - ); - }); - - let schemes = ["http", "https"]; - for (let i = 0; i < schemes.length; i++) { - let scheme = schemes[i]; - let engine = await Services.search.addEngineWithDetails(ENGINE_NAME, { - method: "GET", - template: scheme + "://www.example.com/", - searchGetParams: "q={searchTerms}", - }); - - let context = createContext("ex", { isPrivate: false }); - await check_results({ - context, - autofilled: "example.com/", - matches: [ - makePrioritySearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - }), - ], - }); - - context = createContext("example.com", { isPrivate: false }); - await check_results({ - context, - autofilled: "example.com/", - matches: [ - makePrioritySearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - }), - ], - }); - - context = createContext("example.com/", { isPrivate: false }); - await check_results({ - context, - autofilled: "example.com/", - matches: [ - makePrioritySearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - }), - ], - }); - - context = createContext("www.ex", { isPrivate: false }); - await check_results({ - context, - autofilled: "www.example.com/", - matches: [ - makePrioritySearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - }), - ], - }); - - context = createContext("www.example.com", { isPrivate: false }); - await check_results({ - context, - autofilled: "www.example.com/", - matches: [ - makePrioritySearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - }), - ], - }); - - context = createContext("www.example.com/", { isPrivate: false }); - await check_results({ - context, - autofilled: "www.example.com/", - matches: [ - makePrioritySearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - }), - ], - }); - - context = createContext(scheme + "://ex", { isPrivate: false }); - await check_results({ - context, - autofilled: scheme + "://example.com/", - matches: [ - makePrioritySearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - }), - ], - }); - - context = createContext(scheme + "://example.com", { isPrivate: false }); - await check_results({ - context, - autofilled: scheme + "://example.com/", - matches: [ - makePrioritySearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - }), - ], - }); - - context = createContext(scheme + "://example.com/", { isPrivate: false }); - await check_results({ - context, - autofilled: scheme + "://example.com/", - matches: [ - makePrioritySearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - }), - ], - }); - - context = createContext(scheme + "://www.ex", { isPrivate: false }); - await check_results({ - context, - autofilled: scheme + "://www.example.com/", - matches: [ - makePrioritySearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - }), - ], - }); - - context = createContext(scheme + "://www.example.com", { - isPrivate: false, - }); - await check_results({ - context, - autofilled: scheme + "://www.example.com/", - matches: [ - makePrioritySearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - }), - ], - }); - - context = createContext(scheme + "://www.example.com/", { - isPrivate: false, - }); - await check_results({ - context, - search: scheme + "://www.example.com/", - autofilled: scheme + "://www.example.com/", - matches: [ - makePrioritySearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - }), - ], - }); - - // We should just get a normal heuristic result from HeuristicFallback for - // these queries. - let otherScheme = schemes[(i + 1) % schemes.length]; - context = createContext(otherScheme + "://ex", { isPrivate: false }); - await check_results({ - context, - search: otherScheme + "://ex", - matches: [ - makeVisitResult(context, { - uri: otherScheme + "://ex/", - title: otherScheme + "://ex/", - iconUri: "", - heuristic: true, - }), - ], - }); - context = createContext(otherScheme + "://www.ex", { isPrivate: false }); - await check_results({ - context, - search: otherScheme + "://www.ex", - matches: [ - makeVisitResult(context, { - uri: otherScheme + "://www.ex/", - title: otherScheme + "://www.ex/", - iconUri: "", - heuristic: true, - }), - ], - }); - - context = createContext("example/", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: "http://example/", - title: "http://example/", - heuristic: true, - }), - ], - }); - - await Services.search.removeEngine(engine); - } -}); diff --git a/browser/components/urlbar/tests/unit/test_autofill_urls.js b/browser/components/urlbar/tests/unit/test_autofill_urls.js deleted file mode 100644 index e77e98c1e155..000000000000 --- a/browser/components/urlbar/tests/unit/test_autofill_urls.js +++ /dev/null @@ -1,133 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -const HEURISTIC_FALLBACK_PROVIDERNAME = "HeuristicFallback"; -const UNIFIEDCOMPLETE_PROVIDERNAME = "UnifiedComplete"; - -// "example.com/foo/" should match http://example.com/foo/. -testEngine_setup(); - -add_task(async function multipleSlashes() { - await PlacesTestUtils.addVisits([ - { - uri: "http://example.com/foo/", - }, - ]); - let context = createContext("example.com/foo/", { isPrivate: false }); - await check_results({ - context, - autofilled: "example.com/foo/", - completed: "http://example.com/foo/", - matches: [ - makeVisitResult(context, { - uri: "http://example.com/foo/", - title: "example.com/foo/", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -// "example.com:8888/f" should match http://example.com:8888/foo. -add_task(async function port() { - await PlacesTestUtils.addVisits([ - { - uri: "http://example.com:8888/foo", - }, - ]); - let context = createContext("example.com:8888/f", { isPrivate: false }); - await check_results({ - context, - autofilled: "example.com:8888/foo", - completed: "http://example.com:8888/foo", - matches: [ - makeVisitResult(context, { - uri: "http://example.com:8888/foo", - title: "example.com:8888/foo", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -// "example.com:8999/f" should *not* autofill http://example.com:8888/foo. -add_task(async function portNoMatch() { - await PlacesTestUtils.addVisits([ - { - uri: "http://example.com:8888/foo", - }, - ]); - let context = createContext("example.com:8999/f", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: "http://example.com:8999/f", - title: "http://example.com:8999/f", - iconUri: "page-icon:http://example.com:8999/", - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], - }); - await cleanupPlaces(); -}); - -// autofill to the next slash -add_task(async function port() { - await PlacesTestUtils.addVisits([ - { - uri: "http://example.com:8888/foo/bar/baz", - }, - ]); - let context = createContext("example.com:8888/foo/b", { isPrivate: false }); - await check_results({ - context, - autofilled: "example.com:8888/foo/bar/", - completed: "http://example.com:8888/foo/bar/", - matches: [ - makeVisitResult(context, { - uri: "http://example.com:8888/foo/bar/", - title: "example.com:8888/foo/bar/", - heuristic: true, - }), - makeVisitResult(context, { - uri: "http://example.com:8888/foo/bar/baz", - title: "test visit for http://example.com:8888/foo/bar/baz", - tags: [], - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanupPlaces(); -}); - -// autofill to the next slash, end of url -add_task(async function port() { - await PlacesTestUtils.addVisits([ - { - uri: "http://example.com:8888/foo/bar/baz", - }, - ]); - let context = createContext("example.com:8888/foo/bar/b", { - isPrivate: false, - }); - await check_results({ - context, - autofilled: "example.com:8888/foo/bar/baz", - completed: "http://example.com:8888/foo/bar/baz", - matches: [ - makeVisitResult(context, { - uri: "http://example.com:8888/foo/bar/baz", - title: "example.com:8888/foo/bar/baz", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); diff --git a/browser/components/urlbar/tests/unit/test_avoid_stripping_to_empty_tokens.js b/browser/components/urlbar/tests/unit/test_avoid_stripping_to_empty_tokens.js deleted file mode 100644 index 0287a9236185..000000000000 --- a/browser/components/urlbar/tests/unit/test_avoid_stripping_to_empty_tokens.js +++ /dev/null @@ -1,120 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const ENGINE_NAME = "engine-suggestions.xml"; - -testEngine_setup(); - -add_task(async function test_protocol_trimming() { - for (let prot of ["http", "https", "ftp"]) { - let visit = { - // Include the protocol in the query string to ensure we get matches (see bug 1059395) - uri: Services.io.newURI( - prot + - "://www.mozilla.org/test/?q=" + - prot + - encodeURIComponent("://") + - "www.foo" - ), - title: "Test title", - }; - await PlacesTestUtils.addVisits(visit); - - let input = prot + "://www."; - info("Searching for: " + input); - let context = createContext(input, { isPrivate: false }); - await check_results({ - context, - autofilled: prot + "://www.mozilla.org/", - completed: prot + "://www.mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: prot + "://www.mozilla.org/", - title: - prot == "http" ? "www.mozilla.org" : prot + "://www.mozilla.org", - heuristic: true, - }), - makeVisitResult(context, { - uri: visit.uri.spec, - title: visit.title, - }), - ], - }); - - input = "www."; - info("Searching for: " + input); - context = createContext(input, { isPrivate: false }); - await check_results({ - context, - autofilled: "www.mozilla.org/", - completed: prot + "://www.mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: prot + "://www.mozilla.org/", - title: - prot == "http" ? "www.mozilla.org" : prot + "://www.mozilla.org", - heuristic: true, - }), - makeVisitResult(context, { - uri: visit.uri.spec, - title: visit.title, - }), - ], - }); - - input = prot + "://www. "; - info("Searching for: " + input); - context = createContext(input, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: `${input.trim()}/`, - title: `${input.trim()}/`, - iconUri: "", - heuristic: true, - providerName: "HeuristicFallback", - }), - makeVisitResult(context, { - uri: visit.uri.spec, - title: visit.title, - providerName: "UnifiedComplete", - }), - ], - }); - - let inputs = [ - prot + "://", - prot + ":// ", - prot + ":// mo", - prot + "://mo te", - prot + "://www. mo", - prot + "://www.mo te", - "www. ", - "www. mo", - "www.mo te", - ]; - for (input of inputs) { - info("Searching for: " + input); - context = createContext(input, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - query: input, - heuristic: true, - }), - makeVisitResult(context, { - uri: visit.uri.spec, - title: visit.title, - providerName: "UnifiedComplete", - }), - ], - }); - } - - await cleanupPlaces(); - } -}); diff --git a/browser/components/urlbar/tests/unit/test_casing.js b/browser/components/urlbar/tests/unit/test_casing.js deleted file mode 100644 index 85501ad258ad..000000000000 --- a/browser/components/urlbar/tests/unit/test_casing.js +++ /dev/null @@ -1,363 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const ENGINE_NAME = "engine-suggestions.xml"; -const HEURISTIC_FALLBACK_PROVIDERNAME = "HeuristicFallback"; -const UNIFIEDCOMPLETE_PROVIDERNAME = "UnifiedComplete"; - -testEngine_setup(); - -add_task(async function test_casing_1() { - info("Searching for cased entry 1"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://mozilla.org/test/"), - }); - let context = createContext("MOZ", { isPrivate: false }); - await check_results({ - context, - autofilled: "MOZilla.org/", - completed: "http://mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: "http://mozilla.org/", - title: "mozilla.org", - heuristic: true, - }), - makeVisitResult(context, { - uri: "http://mozilla.org/test/", - title: "test visit for http://mozilla.org/test/", - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_casing_2() { - info("Searching for cased entry 2"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://mozilla.org/test/"), - }); - let context = createContext("mozilla.org/T", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: "http://mozilla.org/T", - title: "http://mozilla.org/T", - iconUri: "page-icon:http://mozilla.org/", - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://mozilla.org/test/", - title: "test visit for http://mozilla.org/test/", - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_casing_3() { - info("Searching for cased entry 3"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://mozilla.org/Test/"), - }); - let context = createContext("mozilla.org/T", { isPrivate: false }); - await check_results({ - context, - autofilled: "mozilla.org/Test/", - completed: "http://mozilla.org/Test/", - matches: [ - makeVisitResult(context, { - uri: "http://mozilla.org/Test/", - title: "mozilla.org/Test/", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_casing_4() { - info("Searching for cased entry 4"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://mozilla.org/Test/"), - }); - let context = createContext("mOzilla.org/t", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: "http://mozilla.org/t", - title: "http://mozilla.org/t", - iconUri: "page-icon:http://mozilla.org/", - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://mozilla.org/Test/", - title: "test visit for http://mozilla.org/Test/", - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_casing_5() { - info("Searching for cased entry 5"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://mozilla.org/Test/"), - }); - let context = createContext("mOzilla.org/T", { isPrivate: false }); - await check_results({ - context, - autofilled: "mOzilla.org/Test/", - completed: "http://mozilla.org/Test/", - matches: [ - makeVisitResult(context, { - uri: "http://mozilla.org/Test/", - title: "mozilla.org/Test/", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_untrimmed_casing() { - info("Searching for untrimmed cased entry"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://mozilla.org/Test/"), - }); - let context = createContext("http://mOz", { isPrivate: false }); - await check_results({ - context, - autofilled: "http://mOzilla.org/", - completed: "http://mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: "http://mozilla.org/", - title: "mozilla.org", - heuristic: true, - }), - makeVisitResult(context, { - uri: "http://mozilla.org/Test/", - title: "test visit for http://mozilla.org/Test/", - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_untrimmed_www_casing() { - info("Searching for untrimmed cased entry with www"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://www.mozilla.org/Test/"), - }); - let context = createContext("http://www.mOz", { isPrivate: false }); - await check_results({ - context, - autofilled: "http://www.mOzilla.org/", - completed: "http://www.mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: "http://www.mozilla.org/", - title: "www.mozilla.org", - heuristic: true, - }), - makeVisitResult(context, { - uri: "http://www.mozilla.org/Test/", - title: "test visit for http://www.mozilla.org/Test/", - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_untrimmed_path_casing() { - info("Searching for untrimmed cased entry with path"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://mozilla.org/Test/"), - }); - let context = createContext("http://mOzilla.org/t", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: "http://mozilla.org/t", - title: "http://mozilla.org/t", - iconUri: "page-icon:http://mozilla.org/", - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://mozilla.org/Test/", - title: "test visit for http://mozilla.org/Test/", - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_untrimmed_path_casing_2() { - info("Searching for untrimmed cased entry with path 2"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://mozilla.org/Test/"), - }); - let context = createContext("http://mOzilla.org/T", { isPrivate: false }); - await check_results({ - context, - autofilled: "http://mOzilla.org/Test/", - completed: "http://mozilla.org/Test/", - matches: [ - makeVisitResult(context, { - uri: "http://mozilla.org/Test/", - title: "mozilla.org/Test/", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_untrimmed_path_www_casing() { - info("Searching for untrimmed cased entry with www and path"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://www.mozilla.org/Test/"), - }); - let context = createContext("http://www.mOzilla.org/t", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: "http://www.mozilla.org/t", - title: "http://www.mozilla.org/t", - iconUri: "page-icon:http://www.mozilla.org/", - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://www.mozilla.org/Test/", - title: "test visit for http://www.mozilla.org/Test/", - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_untrimmed_path_www_casing_2() { - info("Searching for untrimmed cased entry with www and path 2"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://www.mozilla.org/Test/"), - }); - let context = createContext("http://www.mOzilla.org/T", { isPrivate: false }); - await check_results({ - context, - autofilled: "http://www.mOzilla.org/Test/", - completed: "http://www.mozilla.org/Test/", - matches: [ - makeVisitResult(context, { - uri: "http://www.mozilla.org/Test/", - title: "www.mozilla.org/Test/", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_searching() { - let uri1 = Services.io.newURI("http://dummy/1/"); - let uri2 = Services.io.newURI("http://dummy/2/"); - let uri3 = Services.io.newURI("http://dummy/3/"); - let uri4 = Services.io.newURI("http://dummy/4/"); - let uri5 = Services.io.newURI("http://dummy/5/"); - - await PlacesTestUtils.addVisits([ - { uri: uri1, title: "uppercase lambda \u039B" }, - { uri: uri2, title: "lowercase lambda \u03BB" }, - { uri: uri3, title: "symbol \u212A" }, // kelvin - { uri: uri4, title: "uppercase K" }, - { uri: uri5, title: "lowercase k" }, - ]); - - info("Search for lowercase lambda"); - let context = createContext("\u03BB", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { engineName: ENGINE_NAME, heuristic: true }), - makeVisitResult(context, { - uri: uri2.spec, - title: "lowercase lambda \u03BB", - }), - makeVisitResult(context, { - uri: uri1.spec, - title: "uppercase lambda \u039B", - }), - ], - }); - - info("Search for uppercase lambda"); - context = createContext("\u039B", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { engineName: ENGINE_NAME, heuristic: true }), - makeVisitResult(context, { - uri: uri2.spec, - title: "lowercase lambda \u03BB", - }), - makeVisitResult(context, { - uri: uri1.spec, - title: "uppercase lambda \u039B", - }), - ], - }); - - info("Search for kelvin sign"); - context = createContext("\u212A", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { engineName: ENGINE_NAME, heuristic: true }), - makeVisitResult(context, { uri: uri5.spec, title: "lowercase k" }), - makeVisitResult(context, { uri: uri4.spec, title: "uppercase K" }), - makeVisitResult(context, { uri: uri3.spec, title: "symbol \u212A" }), - ], - }); - - info("Search for lowercase k"); - context = createContext("k", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { engineName: ENGINE_NAME, heuristic: true }), - makeVisitResult(context, { uri: uri5.spec, title: "lowercase k" }), - makeVisitResult(context, { uri: uri4.spec, title: "uppercase K" }), - makeVisitResult(context, { uri: uri3.spec, title: "symbol \u212A" }), - ], - }); - - info("Search for uppercase k"); - context = createContext("K", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { engineName: ENGINE_NAME, heuristic: true }), - makeVisitResult(context, { uri: uri5.spec, title: "lowercase k" }), - makeVisitResult(context, { uri: uri4.spec, title: "uppercase K" }), - makeVisitResult(context, { uri: uri3.spec, title: "symbol \u212A" }), - ], - }); - - await cleanupPlaces(); -}); diff --git a/browser/components/urlbar/tests/unit/test_dupe_urls.js b/browser/components/urlbar/tests/unit/test_dupe_urls.js deleted file mode 100644 index 9707233279be..000000000000 --- a/browser/components/urlbar/tests/unit/test_dupe_urls.js +++ /dev/null @@ -1,63 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -// Ensure inline autocomplete doesn't return zero frecency pages. - -add_task(async function setup() { - registerCleanupFunction(async () => { - Services.prefs.clearUserPref("browser.urlbar.suggest.searches"); - }); - - Services.prefs.setBoolPref("browser.urlbar.suggest.searches", false); -}); - -add_task(async function test_dupe_urls() { - info("Searching for urls with dupes should only show one"); - await PlacesTestUtils.addVisits( - { - uri: Services.io.newURI("http://mozilla.org/"), - }, - { - uri: Services.io.newURI("http://mozilla.org/?"), - } - ); - let context = createContext("moz", { isPrivate: false }); - await check_results({ - context, - autofilled: "mozilla.org/", - completed: "http://mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: "http://mozilla.org/", - title: "mozilla.org", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_dupe_secure_urls() { - await PlacesTestUtils.addVisits( - { - uri: Services.io.newURI("https://example.org/"), - }, - { - uri: Services.io.newURI("https://example.org/?"), - } - ); - let context = createContext("exam", { isPrivate: false }); - await check_results({ - context, - autofilled: "example.org/", - completed: "https://example.org/", - matches: [ - makeVisitResult(context, { - uri: "https://example.org/", - title: "https://example.org", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); diff --git a/browser/components/urlbar/tests/unit/test_encoded_urls.js b/browser/components/urlbar/tests/unit/test_encoded_urls.js deleted file mode 100644 index 5260683dddfa..000000000000 --- a/browser/components/urlbar/tests/unit/test_encoded_urls.js +++ /dev/null @@ -1,97 +0,0 @@ -add_task(async function test_encoded() { - info("Searching for over encoded url should not break it"); - let url = "https://www.mozilla.com/search/top/?q=%25%32%35"; - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI(url), - title: url, - }); - let context = createContext(url, { isPrivate: false }); - await check_results({ - context, - autofilled: url, - completed: url, - matches: [ - makeVisitResult(context, { - uri: url, - title: url, - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_encoded_trimmed() { - info("Searching for over encoded url should not break it"); - let url = "https://www.mozilla.com/search/top/?q=%25%32%35"; - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI(url), - title: url, - }); - let context = createContext("mozilla.com/search/top/?q=%25%32%35", { - isPrivate: false, - }); - await check_results({ - context, - autofilled: "mozilla.com/search/top/?q=%25%32%35", - completed: url, - matches: [ - makeVisitResult(context, { - uri: url, - title: url, - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_encoded_partial() { - info("Searching for over encoded url should not break it"); - let url = "https://www.mozilla.com/search/top/?q=%25%32%35"; - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI(url), - title: url, - }); - let context = createContext("https://www.mozilla.com/search/top/?q=%25", { - isPrivate: false, - }); - await check_results({ - context, - autofilled: url, - completed: url, - matches: [ - makeVisitResult(context, { - uri: url, - title: url, - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_encoded_path() { - info("Searching for over encoded url should not break it"); - let url = "https://www.mozilla.com/%25%32%35/top/"; - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI(url), - title: url, - }); - let context = createContext("https://www.mozilla.com/%25%32%35/t", { - isPrivate: false, - }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: url, - title: url, - heuristic: true, - }), - ], - autofilled: url, - completed: url, - }); - await cleanupPlaces(); -}); diff --git a/browser/components/urlbar/tests/unit/test_keywords.js b/browser/components/urlbar/tests/unit/test_keywords.js deleted file mode 100644 index 04984662d343..000000000000 --- a/browser/components/urlbar/tests/unit/test_keywords.js +++ /dev/null @@ -1,207 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const ENGINE_NAME = "engine-suggestions.xml"; - -testEngine_setup(); - -add_task(async function test_non_keyword() { - info("Searching for non-keyworded entry should autoFill it"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://mozilla.org/test/"), - }); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: Services.io.newURI("http://mozilla.org/test/"), - }); - let context = createContext("moz", { isPrivate: false }); - await check_results({ - context, - autofilled: "mozilla.org/", - completed: "http://mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: "http://mozilla.org/", - title: "mozilla.org", - heuristic: true, - }), - makeBookmarkResult(context, { - uri: "http://mozilla.org/test/", - title: "A bookmark", - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_keyword() { - info("Searching for keyworded entry should not autoFill it"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://mozilla.org/test/"), - }); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: Services.io.newURI("http://mozilla.org/test/"), - keyword: "moz", - }); - let context = createContext("moz", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeKeywordSearchResult(context, { - uri: "http://mozilla.org/test/", - keyword: "moz", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_more_than_keyword() { - info("Searching for more than keyworded entry should autoFill it"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://mozilla.org/test/"), - }); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: Services.io.newURI("http://mozilla.org/test/"), - keyword: "moz", - }); - let context = createContext("mozi", { isPrivate: false }); - await check_results({ - context, - autofilled: "mozilla.org/", - completed: "http://mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: "http://mozilla.org/", - title: "mozilla.org", - heuristic: true, - }), - makeBookmarkResult(context, { - uri: "http://mozilla.org/test/", - title: "A bookmark", - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_less_than_keyword() { - info("Searching for less than keyworded entry should autoFill it"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://mozilla.org/test/"), - }); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: Services.io.newURI("http://mozilla.org/test/"), - keyword: "moz", - }); - let context = createContext("mo", { isPrivate: false }); - await check_results({ - context, - search: "mo", - autofilled: "mozilla.org/", - completed: "http://mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: "http://mozilla.org/", - title: "mozilla.org", - heuristic: true, - }), - makeBookmarkResult(context, { - uri: "http://mozilla.org/test/", - title: "A bookmark", - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_keyword_casing() { - info("Searching for keyworded entry is case-insensitive"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://mozilla.org/test/"), - }); - await PlacesTestUtils.addBookmarkWithDetails({ - uri: Services.io.newURI("http://mozilla.org/test/"), - keyword: "moz", - }); - let context = createContext("MoZ", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeKeywordSearchResult(context, { - uri: "http://mozilla.org/test/", - keyword: "MoZ", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_less_then_equal_than_keyword_bug_1124238() { - info("Searching for less than keyworded entry should autoFill it"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://mozilla.org/test/"), - }); - await PlacesTestUtils.addVisits("http://mozilla.com/"); - PlacesTestUtils.addBookmarkWithDetails({ - uri: Services.io.newURI("http://mozilla.com/"), - keyword: "moz", - }); - - let context = createContext("mo", { isPrivate: false }); - await check_results({ - context, - search: "mo", - autofilled: "mozilla.com/", - completed: "http://mozilla.com/", - matches: [ - makeVisitResult(context, { - uri: "http://mozilla.com/", - title: "mozilla.com", - heuristic: true, - }), - makeVisitResult(context, { - uri: "http://mozilla.org/test/", - title: "test visit for http://mozilla.org/test/", - }), - ], - }); - - // Search with an additional character. As the input matches a keyword, the - // completion should equal the keyword and not the URI as before. - context = createContext("moz", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeKeywordSearchResult(context, { - uri: "http://mozilla.com/", - keyword: "moz", - heuristic: true, - }), - ], - }); - - // Search with an additional character. The input doesn't match a keyword - // anymore, it should be autofilled. - context = createContext("mozi", { isPrivate: false }); - await check_results({ - context, - autofilled: "mozilla.com/", - completed: "http://mozilla.com/", - matches: [ - makeVisitResult(context, { - uri: "http://mozilla.com/", - title: "mozilla.com", - heuristic: true, - }), - makeVisitResult(context, { - uri: "http://mozilla.org/test/", - title: "test visit for http://mozilla.org/test/", - }), - ], - }); - - await cleanupPlaces(); -}); diff --git a/browser/components/urlbar/tests/unit/test_query_url.js b/browser/components/urlbar/tests/unit/test_query_url.js deleted file mode 100644 index 464cae1064b1..000000000000 --- a/browser/components/urlbar/tests/unit/test_query_url.js +++ /dev/null @@ -1,123 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -const ENGINE_NAME = "engine-suggestions.xml"; -const HEURISTIC_FALLBACK_PROVIDERNAME = "HeuristicFallback"; -const UNIFIEDCOMPLETE_PROVIDERNAME = "UnifiedComplete"; - -testEngine_setup(); - -add_task(async function test_no_slash() { - info("Searching for host match without slash should match host"); - await PlacesTestUtils.addVisits([ - { uri: "http://file.org/test/" }, - { uri: "file:///c:/test.html" }, - ]); - let context = createContext("file", { isPrivate: false }); - await check_results({ - context, - autofilled: "file.org/", - completed: "http://file.org/", - matches: [ - makeVisitResult(context, { - uri: "http://file.org/", - title: "file.org", - heuristic: true, - }), - makeVisitResult(context, { - uri: "file:///c:/test.html", - title: "test visit for file:///c:/test.html", - iconUri: UrlbarUtils.ICON.DEFAULT, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - makeVisitResult(context, { - uri: "http://file.org/test/", - title: "test visit for http://file.org/test/", - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_w_slash() { - info("Searching match with slash at the end should match url"); - await PlacesTestUtils.addVisits( - { - uri: Services.io.newURI("http://file.org/test/"), - }, - { - uri: Services.io.newURI("file:///c:/test.html"), - } - ); - let context = createContext("file.org/", { isPrivate: false }); - await check_results({ - context, - autofilled: "file.org/", - completed: "http://file.org/", - matches: [ - makeVisitResult(context, { - uri: "http://file.org/", - title: "file.org/", - heuristic: true, - }), - makeVisitResult(context, { - uri: "http://file.org/test/", - title: "test visit for http://file.org/test/", - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_middle() { - info("Searching match with slash in the middle should match url"); - await PlacesTestUtils.addVisits( - { - uri: Services.io.newURI("http://file.org/test/"), - }, - { - uri: Services.io.newURI("file:///c:/test.html"), - } - ); - let context = createContext("file.org/t", { isPrivate: false }); - await check_results({ - context, - autofilled: "file.org/test/", - completed: "http://file.org/test/", - matches: [ - makeVisitResult(context, { - uri: "http://file.org/test/", - title: "file.org/test/", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_nonhost() { - info("Searching for non-host match without slash should not match url"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("file:///c:/test.html"), - }); - let context = createContext("file", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - }), - makeVisitResult(context, { - uri: "file:///c:/test.html", - title: "test visit for file:///c:/test.html", - iconUri: UrlbarUtils.ICON.DEFAULT, - providerName: UNIFIEDCOMPLETE_PROVIDERNAME, - }), - ], - }); - await cleanupPlaces(); -}); diff --git a/browser/components/urlbar/tests/unit/test_search_engine_host.js b/browser/components/urlbar/tests/unit/test_search_engine_host.js deleted file mode 100644 index d169f787729f..000000000000 --- a/browser/components/urlbar/tests/unit/test_search_engine_host.js +++ /dev/null @@ -1,80 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - * http://creativecommons.org/publicdomain/zero/1.0/ */ - -add_task(async function test_searchEngine_autoFill() { - Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); - Services.prefs.setBoolPref("browser.urlbar.suggest.searches", false); - await Services.search.addEngineWithDetails("MySearchEngine", { - method: "GET", - template: "http://my.search.com/", - }); - let engine = Services.search.getEngineByName("MySearchEngine"); - registerCleanupFunction(async () => { - Services.prefs.clearUserPref("browser.urlbar.autoFill.searchEngines"); - Services.prefs.clearUserPref("browser.urlbar.suggest.searches"); - Services.search.removeEngine(engine); - }); - - // Add an uri that matches the search string with high frecency. - let uri = Services.io.newURI("http://www.example.com/my/"); - let visits = []; - for (let i = 0; i < 100; ++i) { - visits.push({ uri, title: "Terms - SearchEngine Search" }); - } - await PlacesTestUtils.addVisits(visits); - await PlacesTestUtils.addBookmarkWithDetails({ - uri, - title: "Example bookmark", - }); - await PlacesTestUtils.promiseAsyncUpdates(); - ok( - frecencyForUrl(uri) > 10000, - "Added URI should have expected high frecency" - ); - - info( - "Check search domain is autoFilled even if there's an higher frecency match" - ); - let context = createContext("my", { isPrivate: false }); - await check_results({ - search: "my", - autofilled: "my.search.com/", - matches: [ - makePrioritySearchResult(context, { - engineName: "MySearchEngine", - heuristic: true, - }), - ], - }); - - await cleanupPlaces(); -}); - -add_task(async function test_searchEngine_noautoFill() { - await PlacesTestUtils.addVisits( - Services.io.newURI("http://my.search.com/samplepage/") - ); - - info("Check search domain is not autoFilled if it matches a visited domain"); - let context = createContext("my", { isPrivate: false }); - await check_results({ - context, - autofilled: "my.search.com/", - completed: "http://my.search.com/", - matches: [ - // Note this result is a normal Autofill result and not a priority engine. - makeVisitResult(context, { - uri: "http://my.search.com/", - title: "my.search.com", - heuristic: true, - }), - makeVisitResult(context, { - uri: "http://my.search.com/samplepage/", - title: "test visit for http://my.search.com/samplepage/", - providerName: "UnifiedComplete", - }), - ], - }); - - await cleanupPlaces(); -}); diff --git a/browser/components/urlbar/tests/unit/test_search_suggestions.js b/browser/components/urlbar/tests/unit/test_search_suggestions.js index a0446eeb79d2..8b7b5da80267 100644 --- a/browser/components/urlbar/tests/unit/test_search_suggestions.js +++ b/browser/components/urlbar/tests/unit/test_search_suggestions.js @@ -1514,6 +1514,7 @@ add_task(async function formHistory() { uri: "http://foo.example.com/", title: "foo.example.com", heuristic: true, + tags: [], }), makeFormHistoryResult(context, { suggestion: "foo", diff --git a/browser/components/urlbar/tests/unit/test_trimming.js b/browser/components/urlbar/tests/unit/test_trimming.js deleted file mode 100644 index 32a3d61c4ee9..000000000000 --- a/browser/components/urlbar/tests/unit/test_trimming.js +++ /dev/null @@ -1,221 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -add_task(async function setup() { - registerCleanupFunction(async () => { - Services.prefs.clearUserPref("browser.urlbar.suggest.searches"); - }); - Services.prefs.setBoolPref("browser.urlbar.suggest.searches", false); -}); - -add_task(async function test_untrimmed_secure_www() { - info("Searching for untrimmed https://www entry"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("https://www.mozilla.org/test/"), - }); - let context = createContext("mo", { isPrivate: false }); - await check_results({ - context, - autofilled: "mozilla.org/", - completed: "https://www.mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: "https://www.mozilla.org/", - title: "https://www.mozilla.org", - heuristic: true, - }), - makeVisitResult(context, { - uri: "https://www.mozilla.org/test/", - title: "test visit for https://www.mozilla.org/test/", - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_untrimmed_secure_www_path() { - info("Searching for untrimmed https://www entry with path"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("https://www.mozilla.org/test/"), - }); - let context = createContext("mozilla.org/t", { isPrivate: false }); - await check_results({ - context, - autofilled: "mozilla.org/test/", - completed: "https://www.mozilla.org/test/", - matches: [ - makeVisitResult(context, { - uri: "https://www.mozilla.org/test/", - title: "https://www.mozilla.org/test/", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_untrimmed_secure() { - info("Searching for untrimmed https:// entry"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("https://mozilla.org/test/"), - }); - let context = createContext("mo", { isPrivate: false }); - await check_results({ - context, - autofilled: "mozilla.org/", - completed: "https://mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: "https://mozilla.org/", - title: "https://mozilla.org", - heuristic: true, - }), - makeVisitResult(context, { - uri: "https://mozilla.org/test/", - title: "test visit for https://mozilla.org/test/", - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_untrimmed_secure_path() { - info("Searching for untrimmed https:// entry with path"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("https://mozilla.org/test/"), - }); - let context = createContext("mozilla.org/t", { isPrivate: false }); - await check_results({ - context, - autofilled: "mozilla.org/test/", - completed: "https://mozilla.org/test/", - matches: [ - makeVisitResult(context, { - uri: "https://mozilla.org/test/", - title: "https://mozilla.org/test/", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_untrimmed_www() { - info("Searching for untrimmed http://www entry"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://www.mozilla.org/test/"), - }); - let context = createContext("mo", { isPrivate: false }); - await check_results({ - context, - autofilled: "mozilla.org/", - completed: "http://www.mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: "http://www.mozilla.org/", - title: "www.mozilla.org", - heuristic: true, - }), - makeVisitResult(context, { - uri: "http://www.mozilla.org/test/", - title: "test visit for http://www.mozilla.org/test/", - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_untrimmed_www_path() { - info("Searching for untrimmed http://www entry with path"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://www.mozilla.org/test/"), - }); - let context = createContext("mozilla.org/t", { isPrivate: false }); - await check_results({ - context, - autofilled: "mozilla.org/test/", - completed: "http://www.mozilla.org/test/", - matches: [ - makeVisitResult(context, { - uri: "http://www.mozilla.org/test/", - title: "www.mozilla.org/test/", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_untrimmed_ftp() { - info("Searching for untrimmed ftp:// entry"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("ftp://mozilla.org/test/"), - }); - let context = createContext("mo", { isPrivate: false }); - await check_results({ - context, - autofilled: "mozilla.org/", - completed: "ftp://mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: "ftp://mozilla.org/", - title: "ftp://mozilla.org", - heuristic: true, - }), - makeVisitResult(context, { - uri: "ftp://mozilla.org/test/", - title: "test visit for ftp://mozilla.org/test/", - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_untrimmed_ftp_path() { - info("Searching for untrimmed ftp:// entry with path"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("ftp://mozilla.org/test/"), - }); - let context = createContext("mozilla.org/t", { isPrivate: false }); - await check_results({ - context, - autofilled: "mozilla.org/test/", - completed: "ftp://mozilla.org/test/", - matches: [ - makeVisitResult(context, { - uri: "ftp://mozilla.org/test/", - title: "ftp://mozilla.org/test/", - heuristic: true, - }), - ], - }); - await cleanupPlaces(); -}); - -add_task(async function test_escaped_chars() { - info("Searching for URL with characters that are normally escaped"); - await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("https://www.mozilla.org/啊-test"), - }); - let context = createContext("https://www.mozilla.org/啊-test", { - isPrivate: false, - }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: "https://www.mozilla.org/%E5%95%8A-test", - title: "https://www.mozilla.org/啊-test", - iconUri: "page-icon:https://www.mozilla.org/", - heuristic: true, - }), - // UnifiedComplete escapes this character. - makeVisitResult(context, { - uri: "https://www.mozilla.org/%E5%95%8A-test", - title: "test visit for https://www.mozilla.org/%E5%95%8A-test", - }), - ], - }); - await cleanupPlaces(); -}); diff --git a/browser/components/urlbar/tests/unit/xpcshell.ini b/browser/components/urlbar/tests/unit/xpcshell.ini index 1bc0dd82b23e..d9b6a3f34966 100644 --- a/browser/components/urlbar/tests/unit/xpcshell.ini +++ b/browser/components/urlbar/tests/unit/xpcshell.ini @@ -5,20 +5,6 @@ support-files = data/engine-suggestions.xml data/engine-tail-suggestions.xml -[test_autofill_about_urls.js] -[test_autofill_functional.js] -[test_autofill_origins.js] -[test_autofill_originsAndQueries.js] -[test_autofill_search_engines.js] -[test_autofill_search_engine_aliases.js] -[test_autofill_urls.js] -[test_avoid_middle_complete.js] -[test_avoid_stripping_to_empty_tokens.js] -[test_casing.js] -[test_dedupe_prefix.js] -[test_dupe_urls.js] -[test_encoded_urls.js] -[test_keywords.js] [test_muxer.js] [test_providerHeuristicFallback.js] [test_providerOmnibox.js] @@ -28,14 +14,11 @@ support-files = [test_providersManager_maxResults.js] [test_providerUnifiedComplete.js] [test_providerUnifiedComplete_duplicate_entries.js] -[test_query_url.js] [test_queryScorer.js] -[test_search_engine_host.js] [test_search_suggestions.js] [test_search_suggestions_aliases.js] [test_search_suggestions_tail.js] [test_tokenizer.js] -[test_trimming.js] [test_UrlbarController_integration.js] [test_UrlbarController_telemetry.js] [test_UrlbarController_unit.js] diff --git a/toolkit/components/places/UnifiedComplete.jsm b/toolkit/components/places/UnifiedComplete.jsm index 276f3bbdb72c..1d4ab809363a 100644 --- a/toolkit/components/places/UnifiedComplete.jsm +++ b/toolkit/components/places/UnifiedComplete.jsm @@ -14,6 +14,8 @@ const MS_PER_DAY = 86400000; // 24 * 60 * 60 * 1000 // AutoComplete query type constants. // Describes the various types of queries that we can process rows for. const QUERYTYPE_FILTERED = 0; +const QUERYTYPE_AUTOFILL_ORIGIN = 1; +const QUERYTYPE_AUTOFILL_URL = 2; const QUERYTYPE_ADAPTIVE = 3; // The default frecency value used when inserting matches with unknown frecency. @@ -131,6 +133,201 @@ const SQL_ADAPTIVE_QUERY = `/* do not warn (bug 487789) */ ORDER BY rank DESC, h.frecency DESC LIMIT :maxResults`; +// Result row indexes for originQuery() +const QUERYINDEX_ORIGIN_AUTOFILLED_VALUE = 1; +const QUERYINDEX_ORIGIN_URL = 2; +const QUERYINDEX_ORIGIN_FRECENCY = 3; + +// `WITH` clause for the autofill queries. autofill_frecency_threshold.value is +// the mean of all moz_origins.frecency values + stddevMultiplier * one standard +// deviation. This is inlined directly in the SQL (as opposed to being a custom +// Sqlite function for example) in order to be as efficient as possible. +const SQL_AUTOFILL_WITH = ` + WITH + frecency_stats(count, sum, squares) AS ( + SELECT + CAST((SELECT IFNULL(value, 0.0) FROM moz_meta WHERE key = 'origin_frecency_count') AS REAL), + CAST((SELECT IFNULL(value, 0.0) FROM moz_meta WHERE key = 'origin_frecency_sum') AS REAL), + CAST((SELECT IFNULL(value, 0.0) FROM moz_meta WHERE key = 'origin_frecency_sum_of_squares') AS REAL) + ), + autofill_frecency_threshold(value) AS ( + SELECT + CASE count + WHEN 0 THEN 0.0 + WHEN 1 THEN sum + ELSE (sum / count) + (:stddevMultiplier * sqrt((squares - ((sum * sum) / count)) / count)) + END + FROM frecency_stats + ) +`; + +const SQL_AUTOFILL_FRECENCY_THRESHOLD = `host_frecency >= ( + SELECT value FROM autofill_frecency_threshold +)`; + +function originQuery({ select = "", where = "", having = "" }) { + return `${SQL_AUTOFILL_WITH} + SELECT :query_type, + fixed_up_host || '/', + IFNULL(:prefix, prefix) || moz_origins.host || '/', + frecency, + bookmarked, + id + FROM ( + SELECT host, + host AS fixed_up_host, + TOTAL(frecency) AS host_frecency, + ( + SELECT TOTAL(foreign_count) > 0 + FROM moz_places + WHERE moz_places.origin_id = moz_origins.id + ) AS bookmarked + ${select} + FROM moz_origins + WHERE host BETWEEN :searchString AND :searchString || X'FFFF' + ${where} + GROUP BY host + HAVING ${having} + UNION ALL + SELECT host, + fixup_url(host) AS fixed_up_host, + TOTAL(frecency) AS host_frecency, + ( + SELECT TOTAL(foreign_count) > 0 + FROM moz_places + WHERE moz_places.origin_id = moz_origins.id + ) AS bookmarked + ${select} + FROM moz_origins + WHERE host BETWEEN 'www.' || :searchString AND 'www.' || :searchString || X'FFFF' + ${where} + GROUP BY host + HAVING ${having} + ) AS grouped_hosts + JOIN moz_origins ON moz_origins.host = grouped_hosts.host + ORDER BY frecency DESC, id DESC + LIMIT 1 `; +} + +const QUERY_ORIGIN_HISTORY_BOOKMARK = originQuery({ + having: `bookmarked OR ${SQL_AUTOFILL_FRECENCY_THRESHOLD}`, +}); + +const QUERY_ORIGIN_PREFIX_HISTORY_BOOKMARK = originQuery({ + where: `AND prefix BETWEEN :prefix AND :prefix || X'FFFF'`, + having: `bookmarked OR ${SQL_AUTOFILL_FRECENCY_THRESHOLD}`, +}); + +const QUERY_ORIGIN_HISTORY = originQuery({ + select: `, ( + SELECT TOTAL(visit_count) > 0 + FROM moz_places + WHERE moz_places.origin_id = moz_origins.id + ) AS visited`, + having: `visited AND ${SQL_AUTOFILL_FRECENCY_THRESHOLD}`, +}); + +const QUERY_ORIGIN_PREFIX_HISTORY = originQuery({ + select: `, ( + SELECT TOTAL(visit_count) > 0 + FROM moz_places + WHERE moz_places.origin_id = moz_origins.id + ) AS visited`, + where: `AND prefix BETWEEN :prefix AND :prefix || X'FFFF'`, + having: `visited AND ${SQL_AUTOFILL_FRECENCY_THRESHOLD}`, +}); + +const QUERY_ORIGIN_BOOKMARK = originQuery({ + having: `bookmarked`, +}); + +const QUERY_ORIGIN_PREFIX_BOOKMARK = originQuery({ + where: `AND prefix BETWEEN :prefix AND :prefix || X'FFFF'`, + having: `bookmarked`, +}); + +// Result row indexes for urlQuery() +const QUERYINDEX_URL_URL = 1; +const QUERYINDEX_URL_STRIPPED_URL = 2; +const QUERYINDEX_URL_FRECENCY = 3; + +function urlQuery(where1, where2) { + // We limit the search to places that are either bookmarked or have a frecency + // over some small, arbitrary threshold (20) in order to avoid scanning as few + // rows as possible. Keep in mind that we run this query every time the user + // types a key when the urlbar value looks like a URL with a path. + return `/* do not warn (bug no): cannot use an index to sort */ + SELECT :query_type, + url, + :strippedURL, + frecency, + foreign_count > 0 AS bookmarked, + visit_count > 0 AS visited, + id + FROM moz_places + WHERE rev_host = :revHost + ${where1} + UNION ALL + SELECT :query_type, + url, + :strippedURL, + frecency, + foreign_count > 0 AS bookmarked, + visit_count > 0 AS visited, + id + FROM moz_places + WHERE rev_host = :revHost || 'www.' + ${where2} + ORDER BY frecency DESC, id DESC + LIMIT 1 `; +} + +const QUERY_URL_HISTORY_BOOKMARK = urlQuery( + `AND (bookmarked OR frecency > 20) + AND strip_prefix_and_userinfo(url) BETWEEN :strippedURL AND :strippedURL || X'FFFF'`, + `AND (bookmarked OR frecency > 20) + AND strip_prefix_and_userinfo(url) BETWEEN 'www.' || :strippedURL AND 'www.' || :strippedURL || X'FFFF'` +); + +const QUERY_URL_PREFIX_HISTORY_BOOKMARK = urlQuery( + `AND (bookmarked OR frecency > 20) + AND url BETWEEN :prefix || :strippedURL AND :prefix || :strippedURL || X'FFFF'`, + `AND (bookmarked OR frecency > 20) + AND url BETWEEN :prefix || 'www.' || :strippedURL AND :prefix || 'www.' || :strippedURL || X'FFFF'` +); + +const QUERY_URL_HISTORY = urlQuery( + `AND (visited OR NOT bookmarked) + AND frecency > 20 + AND strip_prefix_and_userinfo(url) BETWEEN :strippedURL AND :strippedURL || X'FFFF'`, + `AND (visited OR NOT bookmarked) + AND frecency > 20 + AND strip_prefix_and_userinfo(url) BETWEEN 'www.' || :strippedURL AND 'www.' || :strippedURL || X'FFFF'` +); + +const QUERY_URL_PREFIX_HISTORY = urlQuery( + `AND (visited OR NOT bookmarked) + AND frecency > 20 + AND url BETWEEN :prefix || :strippedURL AND :prefix || :strippedURL || X'FFFF'`, + `AND (visited OR NOT bookmarked) + AND frecency > 20 + AND url BETWEEN :prefix || 'www.' || :strippedURL AND :prefix || 'www.' || :strippedURL || X'FFFF'` +); + +const QUERY_URL_BOOKMARK = urlQuery( + `AND bookmarked + AND strip_prefix_and_userinfo(url) BETWEEN :strippedURL AND :strippedURL || X'FFFF'`, + `AND bookmarked + AND strip_prefix_and_userinfo(url) BETWEEN 'www.' || :strippedURL AND 'www.' || :strippedURL || X'FFFF'` +); + +const QUERY_URL_PREFIX_BOOKMARK = urlQuery( + `AND bookmarked + AND url BETWEEN :prefix || :strippedURL AND :prefix || :strippedURL || X'FFFF'`, + `AND bookmarked + AND url BETWEEN :prefix || 'www.' || :strippedURL AND :prefix || 'www.' || :strippedURL || X'FFFF'` +); + // Getters const { XPCOMUtils } = ChromeUtils.import( @@ -762,18 +959,20 @@ Search.prototype = { // For any given search, we run many queries/heuristics: // 1) by alias (as defined in SearchService) // 2) inline completion from search engine resultDomains - // 3) submission for the current search engine - // 4) Places keywords - // 5) adaptive learning (this._adaptiveQuery) - // 6) open pages not supported by history (this._switchToTabQuery) - // 7) query based on match behavior + // 3) inline completion for origins (this._originQuery) or urls (this._urlQuery) + // 4) directly typed in url (ie, can be navigated to as-is) + // 5) submission for the current search engine + // 6) Places keywords + // 7) adaptive learning (this._adaptiveQuery) + // 8) open pages not supported by history (this._switchToTabQuery) + // 9) query based on match behavior // - // (4) only gets run if we get any filtered tokens, since if there are no + // (6) only gets run if we get any filtered tokens, since if there are no // tokens, there is nothing to match. // - // (1) and (5) only get run if actions are enabled. When actions are + // (1), (4), (5) only get run if actions are enabled. When actions are // enabled, the first result is always a special result (resulting from one - // of the queries between (1) and (4) inclusive). As such, the UI is + // of the queries between (1) and (6) inclusive). As such, the UI is // expected to auto-select the first result when actions are enabled. If the // first result is an inline completion result, that will also be the // default result and therefore be autofilled (this also happens if actions @@ -814,14 +1013,16 @@ Search.prototype = { // If the heuristic result is an engine from a token alias, the search // restriction char, or we're in search-restriction mode, then we're done. // UrlbarProviderSearchSuggestions will handle suggestions, if any. + let tokenAliasQuery = + this._searchEngineAliasMatch && + this._searchEngineAliasMatch.isTokenAlias; let emptySearchRestriction = this._trimmedOriginalSearchString.length <= 3 && this._leadingRestrictionToken == UrlbarTokenizer.RESTRICT.SEARCH && /\s*\S?$/.test(this._trimmedOriginalSearchString); if ( emptySearchRestriction || - (tokenAliasEngines && - this._trimmedOriginalSearchString.startsWith("@")) || + tokenAliasQuery || (this.hasBehavior("search") && this.hasBehavior("restrict")) ) { this._autocompleteSearch.finishSearch(true); @@ -926,6 +1127,20 @@ Search.prototype = { } }, + _matchAboutPageForAutofill() { + if (!this._shouldMatchAboutPages()) { + return false; + } + for (const url of AboutPagesUtils.visibleAboutUrls) { + if (url.startsWith(`about:${this._searchString.toLowerCase()}`)) { + this._result.setDefaultIndex(0); + this._addAutofillMatch(url.substr(6), url); + return true; + } + } + return false; + }, + async _checkPreloadedSitesExpiry() { if (!UrlbarPrefs.get("usepreloadedtopurls.enabled")) { return; @@ -998,6 +1213,60 @@ Search.prototype = { return true; }, + async _matchSearchEngineTokenAliasForAutofill() { + // We need an "@engine" heuristic token. + let token = this._heuristicToken; + if (!token || token.length == 1 || !token.startsWith("@")) { + return false; + } + + // See if any engine has a token alias that starts with the heuristic token. + let engines = await UrlbarSearchUtils.tokenAliasEngines(); + for (let { engine, tokenAliases } of engines) { + for (let alias of tokenAliases) { + if (alias.startsWith(token.toLocaleLowerCase())) { + // We found one. The match we add here is a little special compared + // to others. It needs to be an autofill match and its `value` must + // be the string that will be autofilled so that the controller will + // autofill it. But it also must be a searchengine action so that the + // front end will style it as a search engine result. The front end + // uses `finalCompleteValue` as the URL for autofill results, so set + // that to the moz-action URL. + let aliasPreservingUserCase = token + alias.substr(token.length); + let value = aliasPreservingUserCase + " "; + this._result.setDefaultIndex(0); + this._addMatch({ + value, + finalCompleteValue: makeActionUrl("searchengine", { + engineName: engine.name, + alias: aliasPreservingUserCase, + input: value, + searchQuery: "", + }), + comment: engine.name, + frecency: FRECENCY_DEFAULT, + style: "autofill action searchengine", + icon: engine.iconURI ? engine.iconURI.spec : null, + }); + + // Set _searchEngineAliasMatch with an empty query so that we don't + // attempt to add any more matches. When a token alias is autofilled, + // the only match should be the one we just added. + this._searchEngineAliasMatch = { + engine, + alias: aliasPreservingUserCase, + query: "", + isTokenAlias: true, + }; + + return true; + } + } + } + + return false; + }, + async _matchFirstHeuristicResult(conn) { // We always try to make the first result a special "heuristic" result. The // heuristics below determine what type of result it will be, if any. @@ -1020,6 +1289,30 @@ Search.prototype = { let shouldAutofill = this._shouldAutofill; + if (this.pending && shouldAutofill) { + // It may also look like an about: link. + let matched = await this._matchAboutPageForAutofill(); + if (matched) { + return true; + } + } + + if (this.pending && shouldAutofill) { + // It may also look like a URL we know from the database. + let matched = await this._matchKnownUrl(conn); + if (matched) { + return true; + } + } + + if (this.pending && shouldAutofill) { + // Or it may look like a search engine domain. + let matched = await this._matchSearchEngineDomain(); + if (matched) { + return true; + } + } + if (this.pending && shouldAutofill) { let matched = this._matchPreloadedSiteForAutofill(); if (matched) { @@ -1027,10 +1320,44 @@ Search.prototype = { } } + if (this.pending && shouldAutofill) { + let matched = await this._matchSearchEngineTokenAliasForAutofill(); + if (matched) { + return true; + } + } + // Fall back to UrlbarProviderHeuristicFallback. return false; }, + async _matchKnownUrl(conn) { + let gotResult = false; + + // If search string looks like an origin, try to autofill against origins. + // Otherwise treat it as a possible URL. When the string has only one slash + // at the end, we still treat it as an URL. + let query, params; + if ( + UrlbarTokenizer.looksLikeOrigin(this._searchString, { + ignoreKnownDomains: true, + }) + ) { + [query, params] = this._originQuery; + } else { + [query, params] = this._urlQuery; + } + + // _urlQuery doesn't always return a query. + if (query) { + await conn.executeCached(query, params, (row, cancel) => { + gotResult = true; + this._onResultRow(row, cancel); + }); + } + return gotResult; + }, + async _matchPlacesKeyword(keyword) { let entry = await PlacesUtils.keywords.fetch(keyword); if (!entry) { @@ -1087,6 +1414,71 @@ Search.prototype = { return true; }, + async _matchSearchEngineDomain() { + if (!UrlbarPrefs.get("autoFill.searchEngines")) { + return false; + } + if (!this._searchString) { + return false; + } + + // engineForDomainPrefix only matches against engine domains. + // Remove an eventual trailing slash from the search string (without the + // prefix) and check if the resulting string is worth matching. + // Later, we'll verify that the found result matches the original + // searchString and eventually discard it. + let searchStr = this._searchString; + if (searchStr.indexOf("/") == searchStr.length - 1) { + searchStr = searchStr.slice(0, -1); + } + // If the search string looks more like a url than a domain, bail out. + if ( + !UrlbarTokenizer.looksLikeOrigin(searchStr, { ignoreKnownDomains: true }) + ) { + return false; + } + + let engine = await UrlbarSearchUtils.engineForDomainPrefix(searchStr); + if (!engine) { + return false; + } + let url = engine.searchForm; + let domain = engine.getResultDomain(); + // Verify that the match we got is acceptable. Autofilling "example/" to + // "example.com/" would not be good. + if ( + (this._strippedPrefix && !url.startsWith(this._strippedPrefix)) || + !(domain + "/").includes(this._searchString) + ) { + return false; + } + + // The value that's autofilled in the input is the prefix the user typed, if + // any, plus the portion of the engine domain that the user typed. Append a + // trailing slash too, as is usual with autofill. + let value = + this._strippedPrefix + domain.substr(domain.indexOf(searchStr)) + "/"; + + let finalCompleteValue = url; + try { + let fixupInfo = Services.uriFixup.getFixupURIInfo(url, 0); + if (fixupInfo.fixedURI) { + finalCompleteValue = fixupInfo.fixedURI.spec; + } + } catch (ex) {} + + this._result.setDefaultIndex(0); + this._addMatch({ + value, + finalCompleteValue, + comment: engine.name, + icon: engine.iconURI ? engine.iconURI.spec : null, + style: "priority-search", + frecency: Infinity, + }); + return true; + }, + async _matchSearchEngineAlias(alias) { let engine = await UrlbarSearchUtils.engineForAlias(alias); if (!engine) { @@ -1208,6 +1600,14 @@ Search.prototype = { _onResultRow(row, cancel) { let queryType = row.getResultByIndex(QUERYINDEX_QUERYTYPE); switch (queryType) { + case QUERYTYPE_AUTOFILL_ORIGIN: + this._result.setDefaultIndex(0); + this._addOriginAutofillMatch(row); + break; + case QUERYTYPE_AUTOFILL_URL: + this._result.setDefaultIndex(0); + this._addURLAutofillMatch(row); + break; case QUERYTYPE_ADAPTIVE: this._addAdaptiveQueryMatch(row); break; @@ -1336,6 +1736,16 @@ Search.prototype = { this.notifyResult(true, match.type == UrlbarUtils.RESULT_GROUP.HEURISTIC); }, + // Ranks a URL prefix from 3 - 0 with the following preferences: + // https:// > https://www. > http:// > http://www. + // Higher is better. + // Returns -1 if the prefix does not match any of the above. + _getPrefixRank(prefix) { + return ["http://www.", "http://", "https://www.", "https://"].indexOf( + prefix + ); + }, + /** * Check for duplicates and either discard the duplicate or replace the * original match, in case the new one is more specific. For example, @@ -1401,9 +1811,12 @@ Search.prototype = { // 1. If the two URLs are the same, dedupe whichever is not the // heuristic result. // 2. If they both contain www. or both do not contain it, prefer https. - // 3. If they differ by www., send both results to the Muxer and allow - // it to decide based on results from other providers. - let prefixRank = UrlbarUtils.getPrefixRank(prefix); + // 3. If they differ by www.: + // 3a. If the page titles are different, keep both. This is a guard + // against deduping when www.site.com and site.com have different + // content. + // 3b. Otherwise, dedupe based on the priorities in _getPrefixRank. + let prefixRank = this._getPrefixRank(prefix); for (let i = 0; i < this._usedURLs.length; ++i) { if (!this._usedURLs[i]) { // This is true when the result at [i] is a searchengine result. @@ -1414,9 +1827,10 @@ Search.prototype = { key: existingKey, prefix: existingPrefix, type: existingType, + comment: existingComment, } = this._usedURLs[i]; - let existingPrefixRank = UrlbarUtils.getPrefixRank(existingPrefix); + let existingPrefixRank = this._getPrefixRank(existingPrefix); if (ObjectUtils.deepEqual(existingKey, urlMapKey)) { isDupe = true; @@ -1461,12 +1875,25 @@ Search.prototype = { continue; } } else { - // We have two identical URLs that differ only by www. We need to - // be sure what the heuristic result is before deciding how we - // should dedupe. We mark these as non-duplicates and let the - // muxer handle it. - isDupe = false; - continue; + // If either result is the heuristic, this will be true and we + // will keep both results. + if (match.comment != existingComment) { + isDupe = false; + continue; + } + + if (prefixRank <= existingPrefixRank) { + break; // Replace match. + } else { + this._usedURLs[i] = { + key: urlMapKey, + action, + type: match.type, + prefix, + comment: match.comment, + }; + return { index: i, replace: true }; + } } } } @@ -1540,6 +1967,42 @@ Search.prototype = { return { index, replace }; }, + _addOriginAutofillMatch(row) { + this._addAutofillMatch( + row.getResultByIndex(QUERYINDEX_ORIGIN_AUTOFILLED_VALUE), + row.getResultByIndex(QUERYINDEX_ORIGIN_URL), + row.getResultByIndex(QUERYINDEX_ORIGIN_FRECENCY) + ); + }, + + _addURLAutofillMatch(row) { + let url = row.getResultByIndex(QUERYINDEX_URL_URL); + let strippedURL = row.getResultByIndex(QUERYINDEX_URL_STRIPPED_URL); + // We autofill urls to-the-next-slash. + // http://mozilla.org/foo/bar/baz will be autofilled to: + // - http://mozilla.org/f[oo/] + // - http://mozilla.org/foo/b[ar/] + // - http://mozilla.org/foo/bar/b[az] + let value; + let strippedURLIndex = url.indexOf(strippedURL); + let strippedPrefix = url.substr(0, strippedURLIndex); + let nextSlashIndex = url.indexOf( + "/", + strippedURLIndex + strippedURL.length - 1 + ); + if (nextSlashIndex == -1) { + value = url.substr(strippedURLIndex); + } else { + value = url.substring(strippedURLIndex, nextSlashIndex + 1); + } + + this._addAutofillMatch( + value, + strippedPrefix + value, + row.getResultByIndex(QUERYINDEX_URL_FRECENCY) + ); + }, + _addAutofillMatch( autofilledValue, finalCompleteValue, @@ -1810,6 +2273,125 @@ Search.prototype = { return true; }, + /** + * Obtains the query to search for autofill origin results. + * + * @return an array consisting of the correctly optimized query to search the + * database with and an object containing the params to bound. + */ + get _originQuery() { + // At this point, _searchString is not a URL with a path; it does not + // contain a slash, except for possibly at the very end. If there is + // trailing slash, remove it when searching here to match the rest of the + // string because it may be an origin. + let searchStr = this._searchString.endsWith("/") + ? this._searchString.slice(0, -1) + : this._searchString; + + let opts = { + query_type: QUERYTYPE_AUTOFILL_ORIGIN, + searchString: searchStr.toLowerCase(), + stddevMultiplier: UrlbarPrefs.get("autoFill.stddevMultiplier"), + }; + if (this._strippedPrefix) { + opts.prefix = this._strippedPrefix; + } + + if (this.hasBehavior("history") && this.hasBehavior("bookmark")) { + return [ + this._strippedPrefix + ? QUERY_ORIGIN_PREFIX_HISTORY_BOOKMARK + : QUERY_ORIGIN_HISTORY_BOOKMARK, + opts, + ]; + } + if (this.hasBehavior("history")) { + return [ + this._strippedPrefix + ? QUERY_ORIGIN_PREFIX_HISTORY + : QUERY_ORIGIN_HISTORY, + opts, + ]; + } + if (this.hasBehavior("bookmark")) { + return [ + this._strippedPrefix + ? QUERY_ORIGIN_PREFIX_BOOKMARK + : QUERY_ORIGIN_BOOKMARK, + opts, + ]; + } + throw new Error("Either history or bookmark behavior expected"); + }, + + /** + * Obtains the query to search for autoFill url results. + * + * @return an array consisting of the correctly optimized query to search the + * database with and an object containing the params to bound. + */ + get _urlQuery() { + // Try to get the host from the search string. The host is the part of the + // URL up to either the path slash, port colon, or query "?". If the search + // string doesn't look like it begins with a host, then return; it doesn't + // make sense to do a URL query with it. + if (!this._urlQueryHostRegexp) { + this._urlQueryHostRegexp = /^[^/:?]+/; + } + let hostMatch = this._urlQueryHostRegexp.exec(this._searchString); + if (!hostMatch) { + return [null, null]; + } + + let host = hostMatch[0].toLowerCase(); + let revHost = + host + .split("") + .reverse() + .join("") + "."; + + // Build a string that's the URL stripped of its prefix, i.e., the host plus + // everything after the host. Use _trimmedOriginalSearchString instead of + // this._searchString because this._searchString has had unEscapeURIForUI() + // called on it. It's therefore not necessarily the literal URL. + let strippedURL = this._trimmedOriginalSearchString; + if (this._strippedPrefix) { + strippedURL = strippedURL.substr(this._strippedPrefix.length); + } + strippedURL = host + strippedURL.substr(host.length); + + let opts = { + query_type: QUERYTYPE_AUTOFILL_URL, + revHost, + strippedURL, + }; + if (this._strippedPrefix) { + opts.prefix = this._strippedPrefix; + } + + if (this.hasBehavior("history") && this.hasBehavior("bookmark")) { + return [ + this._strippedPrefix + ? QUERY_URL_PREFIX_HISTORY_BOOKMARK + : QUERY_URL_HISTORY_BOOKMARK, + opts, + ]; + } + if (this.hasBehavior("history")) { + return [ + this._strippedPrefix ? QUERY_URL_PREFIX_HISTORY : QUERY_URL_HISTORY, + opts, + ]; + } + if (this.hasBehavior("bookmark")) { + return [ + this._strippedPrefix ? QUERY_URL_PREFIX_BOOKMARK : QUERY_URL_BOOKMARK, + opts, + ]; + } + throw new Error("Either history or bookmark behavior expected"); + }, + // The result is notified to the search listener on a timer, to chunk multiple // match updates together and avoid rebuilding the popup at every new match. _notifyTimer: null, diff --git a/toolkit/components/places/tests/unifiedcomplete/autofill_tasks.js b/toolkit/components/places/tests/unifiedcomplete/autofill_tasks.js new file mode 100644 index 000000000000..088ccb6c8ce0 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/autofill_tasks.js @@ -0,0 +1,1943 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* import-globals-from ../head_common.js */ +/* import-globals-from ./head_autocomplete.js */ + +function addAutofillTasks(origins) { + // Helpful reminder of the `autofilled` and `completed` properties in the + // object passed to check_autocomplete: + // + // autofilled: expected input.value after autofill + // completed: expected input.value after autofill and enter is pressed + // + // `completed` is the URL that the controller sets to input.value, and the URL + // that will ultimately be loaded when you press enter. When you press enter, + // the code path is: + // + // (1) urlbar.handleEnter + // (2) nsAutoCompleteController::HandleEnter + // (3) nsAutoCompleteController::EnterMatch (sets input.value) + // (4) input.onTextEntered + // (5) urlbar.handleCommand (loads input.value) + + let path; + let search; + let searchCase; + let comment; + if (origins) { + path = "/"; + search = "ex"; + searchCase = "EX"; + comment = "example.com"; + } else { + path = "/foo"; + search = "example.com/f"; + searchCase = "EXAMPLE.COM/f"; + comment = "example.com/foo"; + } + + let host = "example.com"; + let url = host + path; + + add_task(async function init() { + await cleanup(); + }); + + // "ex" should match http://example.com/. + add_task(async function basic() { + await PlacesTestUtils.addVisits([ + { + uri: "http://" + url, + }, + ]); + await check_autocomplete({ + search, + autofilled: url, + completed: "http://" + url, + matches: [ + { + value: url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // "EX" should match http://example.com/. + add_task(async function basicCase() { + await PlacesTestUtils.addVisits([ + { + uri: "http://" + url, + }, + ]); + await check_autocomplete({ + search: searchCase, + autofilled: searchCase + url.substr(searchCase.length), + completed: "http://" + url, + matches: [ + { + value: url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // "ex" should match http://www.example.com/. + add_task(async function noWWWShouldMatchWWW() { + await PlacesTestUtils.addVisits([ + { + uri: "http://www." + url, + }, + ]); + await check_autocomplete({ + search, + autofilled: url, + completed: "http://www." + url, + matches: [ + { + value: url, + comment: "www." + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // "EX" should match http://www.example.com/. + add_task(async function noWWWShouldMatchWWWCase() { + await PlacesTestUtils.addVisits([ + { + uri: "http://www." + url, + }, + ]); + await check_autocomplete({ + search: searchCase, + autofilled: searchCase + url.substr(searchCase.length), + completed: "http://www." + url, + matches: [ + { + value: url, + comment: "www." + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // "www.ex" should *not* match http://example.com/. + add_task(async function wwwShouldNotMatchNoWWW() { + await PlacesTestUtils.addVisits([ + { + uri: "http://" + url, + }, + ]); + await check_autocomplete({ + search: "www." + search, + matches: [], + }); + await cleanup(); + }); + + // "http://ex" should match http://example.com/. + add_task(async function prefix() { + await PlacesTestUtils.addVisits([ + { + uri: "http://" + url, + }, + ]); + await check_autocomplete({ + search: "http://" + search, + autofilled: "http://" + url, + completed: "http://" + url, + matches: [ + { + value: "http://" + url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // "HTTP://EX" should match http://example.com/. + add_task(async function prefixCase() { + await PlacesTestUtils.addVisits([ + { + uri: "http://" + url, + }, + ]); + await check_autocomplete({ + search: "HTTP://" + searchCase, + autofilled: "HTTP://" + searchCase + url.substr(searchCase.length), + completed: "http://" + url, + matches: [ + { + value: "http://" + url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // "http://ex" should match http://www.example.com/. + add_task(async function prefixNoWWWShouldMatchWWW() { + await PlacesTestUtils.addVisits([ + { + uri: "http://www." + url, + }, + ]); + await check_autocomplete({ + search: "http://" + search, + autofilled: "http://" + url, + completed: "http://www." + url, + matches: [ + { + value: "http://" + url, + comment: "www." + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // "HTTP://EX" should match http://www.example.com/. + add_task(async function prefixNoWWWShouldMatchWWWCase() { + await PlacesTestUtils.addVisits([ + { + uri: "http://www." + url, + }, + ]); + await check_autocomplete({ + search: "HTTP://" + searchCase, + autofilled: "HTTP://" + searchCase + url.substr(searchCase.length), + completed: "http://www." + url, + matches: [ + { + value: "http://" + url, + comment: "www." + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // "http://www.ex" should *not* match http://example.com/. + add_task(async function prefixWWWShouldNotMatchNoWWW() { + await PlacesTestUtils.addVisits([ + { + uri: "http://" + url, + }, + ]); + await check_autocomplete({ + search: "http://www." + search, + matches: [], + }); + await cleanup(); + }); + + // "http://ex" should *not* match https://example.com/. + add_task(async function httpPrefixShouldNotMatchHTTPS() { + await PlacesTestUtils.addVisits([ + { + uri: "https://" + url, + }, + ]); + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "https://" + url, + comment: "test visit for https://" + url, + style: ["favicon"], + }, + ], + }); + await cleanup(); + }); + + // "ex" should match https://example.com/. + add_task(async function httpsBasic() { + await PlacesTestUtils.addVisits([ + { + uri: "https://" + url, + }, + ]); + await check_autocomplete({ + search, + autofilled: url, + completed: "https://" + url, + matches: [ + { + value: url, + comment: "https://" + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // "ex" should match https://www.example.com/. + add_task(async function httpsNoWWWShouldMatchWWW() { + await PlacesTestUtils.addVisits([ + { + uri: "https://www." + url, + }, + ]); + await check_autocomplete({ + search, + autofilled: url, + completed: "https://www." + url, + matches: [ + { + value: url, + comment: "https://www." + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // "www.ex" should *not* match https://example.com/. + add_task(async function httpsWWWShouldNotMatchNoWWW() { + await PlacesTestUtils.addVisits([ + { + uri: "https://" + url, + }, + ]); + await check_autocomplete({ + search: "www." + search, + matches: [], + }); + await cleanup(); + }); + + // "https://ex" should match https://example.com/. + add_task(async function httpsPrefix() { + await PlacesTestUtils.addVisits([ + { + uri: "https://" + url, + }, + ]); + await check_autocomplete({ + search: "https://" + search, + autofilled: "https://" + url, + completed: "https://" + url, + matches: [ + { + value: "https://" + url, + comment: "https://" + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // "https://ex" should match https://www.example.com/. + add_task(async function httpsPrefixNoWWWShouldMatchWWW() { + await PlacesTestUtils.addVisits([ + { + uri: "https://www." + url, + }, + ]); + await check_autocomplete({ + search: "https://" + search, + autofilled: "https://" + url, + completed: "https://www." + url, + matches: [ + { + value: "https://" + url, + comment: "https://www." + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // "https://www.ex" should *not* match https://example.com/. + add_task(async function httpsPrefixWWWShouldNotMatchNoWWW() { + await PlacesTestUtils.addVisits([ + { + uri: "https://" + url, + }, + ]); + await check_autocomplete({ + search: "https://www." + search, + matches: [], + }); + await cleanup(); + }); + + // "https://ex" should *not* match http://example.com/. + add_task(async function httpsPrefixShouldNotMatchHTTP() { + await PlacesTestUtils.addVisits([ + { + uri: "http://" + url, + }, + ]); + await check_autocomplete({ + search: "https://" + search, + matches: [ + { + value: "http://" + url, + comment: "test visit for http://" + url, + style: ["favicon"], + }, + ], + }); + await cleanup(); + }); + + // "https://ex" should *not* match http://example.com/, even if the latter is + // more frecent and both could be autofilled. + add_task(async function httpsPrefixShouldNotMatchMoreFrecentHTTP() { + await PlacesTestUtils.addVisits([ + { + uri: "http://" + url, + transition: PlacesUtils.history.TRANSITIONS.TYPED, + }, + { + uri: "http://" + url, + }, + { + uri: "https://" + url, + transition: PlacesUtils.history.TRANSITIONS.TYPED, + }, + { + uri: "http://otherpage", + }, + ]); + await check_autocomplete({ + search: "https://" + search, + autofilled: "https://" + url, + completed: "https://" + url, + matches: [ + { + value: "https://" + url, + comment: "https://" + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // Autofill should respond to frecency changes. + add_task(async function frecency() { + // Start with an http visit. It should be completed. + await PlacesTestUtils.addVisits([ + { + uri: "http://" + url, + }, + ]); + await check_autocomplete({ + search, + autofilled: url, + completed: "http://" + url, + matches: [ + { + value: url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + + // Add two https visits. https should now be completed. + for (let i = 0; i < 2; i++) { + await PlacesTestUtils.addVisits([{ uri: "https://" + url }]); + } + await check_autocomplete({ + search, + autofilled: url, + completed: "https://" + url, + matches: [ + { + value: url, + comment: "https://" + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + + // Add two more http visits, three total. http should now be completed + // again. + for (let i = 0; i < 2; i++) { + await PlacesTestUtils.addVisits([{ uri: "http://" + url }]); + } + await check_autocomplete({ + search, + autofilled: url, + completed: "http://" + url, + matches: [ + { + value: url, + comment, + style: ["autofill", "heuristic"], + }, + { + value: "https://" + url, + comment: "test visit for https://" + url, + style: ["favicon"], + }, + ], + }); + + // Add four www https visits. www https should now be completed. + for (let i = 0; i < 4; i++) { + await PlacesTestUtils.addVisits([{ uri: "https://www." + url }]); + } + await check_autocomplete({ + search, + autofilled: url, + completed: "https://www." + url, + matches: [ + { + value: url, + comment: "https://www." + comment, + style: ["autofill", "heuristic"], + }, + { + value: "https://" + url, + comment: "test visit for https://" + url, + style: ["favicon"], + }, + ], + }); + + // Remove the www https page. + await PlacesUtils.history.remove(["https://www." + url]); + + // http should now be completed again. + await check_autocomplete({ + search, + autofilled: url, + completed: "http://" + url, + matches: [ + { + value: url, + comment, + style: ["autofill", "heuristic"], + }, + { + value: "https://" + url, + comment: "test visit for https://" + url, + style: ["favicon"], + }, + ], + }); + + // Remove the http page. + await PlacesUtils.history.remove(["http://" + url]); + + // https should now be completed again. + await check_autocomplete({ + search, + autofilled: url, + completed: "https://" + url, + matches: [ + { + value: url, + comment: "https://" + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + + // Add a visit with a different host so that "ex" doesn't autofill it. + // https://example.com/ should still have a higher frecency though, so it + // should still be autofilled. + await PlacesTestUtils.addVisits([{ uri: "https://not-" + url }]); + await check_autocomplete({ + search, + autofilled: url, + completed: "https://" + url, + matches: [ + { + value: url, + comment: "https://" + comment, + style: ["autofill", "heuristic"], + }, + { + value: "https://not-" + url, + comment: "test visit for https://not-" + url, + style: ["favicon"], + }, + ], + }); + + // Now add 10 more visits to the different host so that the frecency of + // https://example.com/ falls below the autofill threshold. It should not + // be autofilled now. + for (let i = 0; i < 10; i++) { + await PlacesTestUtils.addVisits([{ uri: "https://not-" + url }]); + } + + // Enable actions. In the `origins` case, the failure to make an autofill + // match means UnifiedComplete should not create a heuristic result. In the + // `!origins` case, autofill should still happen since there's no threshold + // comparison. + if (origins) { + await check_autocomplete({ + search, + searchParam: "enable-actions", + matches: [ + { + value: "https://not-" + url, + comment: "test visit for https://not-" + url, + style: ["favicon"], + }, + { + value: "https://" + url, + comment: "test visit for https://" + url, + style: ["favicon"], + }, + ], + }); + } else { + await check_autocomplete({ + search, + searchParam: "enable-actions", + autofilled: url, + completed: "https://" + url, + matches: [ + { + value: url, + comment: "https://" + comment, + style: ["autofill", "heuristic"], + }, + { + value: "https://not-" + url, + comment: "test visit for https://not-" + url, + style: ["favicon"], + }, + ], + }); + } + + // Remove the visits to the different host. + await PlacesUtils.history.remove(["https://not-" + url]); + + // https should be completed again. + await check_autocomplete({ + search, + autofilled: url, + completed: "https://" + url, + matches: [ + { + value: url, + comment: "https://" + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + + // Remove the https visits. + await PlacesUtils.history.remove(["https://" + url]); + + // Now nothing should be completed. + await check_autocomplete({ + search, + matches: [], + }); + + await cleanup(); + }); + + // Bookmarked places should always be autofilled, even when they don't meet + // the threshold. + add_task(async function bookmarkBelowThreshold() { + // Add some visits to a URL so that the origin autofill threshold is large. + for (let i = 0; i < 3; i++) { + await PlacesTestUtils.addVisits([ + { + uri: "http://not-" + url, + }, + ]); + } + + // Now bookmark another URL. + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://" + url, + }); + + // Make sure the bookmarked origin and place frecencies are below the + // threshold so that the origin/URL otherwise would not be autofilled. + let placeFrecency = await PlacesTestUtils.fieldInDB( + "http://" + url, + "frecency" + ); + let originFrecency = await getOriginFrecency("http://", host); + let threshold = await getOriginAutofillThreshold(); + Assert.ok( + placeFrecency < threshold, + `Place frecency should be below the threshold: ` + + `placeFrecency=${placeFrecency} threshold=${threshold}` + ); + Assert.ok( + originFrecency < threshold, + `Origin frecency should be below the threshold: ` + + `originFrecency=${originFrecency} threshold=${threshold}` + ); + + // The bookmark should be autofilled. + await check_autocomplete({ + search, + autofilled: url, + completed: "http://" + url, + matches: [ + { + value: url, + comment, + style: ["autofill", "heuristic"], + }, + { + value: "http://not-" + url, + comment: "test visit for http://not-" + url, + style: ["favicon"], + }, + ], + }); + + await cleanup(); + }); + + // Bookmarked places should be autofilled when they *do* meet the threshold. + add_task(async function bookmarkAboveThreshold() { + // Bookmark a URL. + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://" + url, + }); + + // The frecencies of the place and origin should be >= the threshold. In + // fact they should be the same as the threshold since the place is the only + // place in the database. + let placeFrecency = await PlacesTestUtils.fieldInDB( + "http://" + url, + "frecency" + ); + let originFrecency = await getOriginFrecency("http://", host); + let threshold = await getOriginAutofillThreshold(); + Assert.equal(placeFrecency, threshold); + Assert.equal(originFrecency, threshold); + + // The bookmark should be autofilled. + await check_autocomplete({ + search, + autofilled: url, + completed: "http://" + url, + matches: [ + { + value: url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + + await cleanup(); + }); + + // Bookmark a page and then clear history. The bookmarked origin/URL should + // be autofilled even though its frecency is <= 0 since the autofill threshold + // is 0. + add_task(async function zeroThreshold() { + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://" + url, + }); + + await PlacesUtils.history.clear(); + + // Make sure the place's frecency is <= 0. (It will be reset to -1 on the + // history.clear() above, and then on idle it will be reset to 0. xpcshell + // tests disable the idle service, so in practice it should always be -1, + // but in order to avoid possible intermittent failures in the future, don't + // assume that.) + let placeFrecency = await PlacesTestUtils.fieldInDB( + "http://" + url, + "frecency" + ); + Assert.ok(placeFrecency <= 0); + + // Make sure the origin's frecency is 0. + let originFrecency = await getOriginFrecency("http://", host); + Assert.equal(originFrecency, 0); + + // Make sure the autofill threshold is 0. + let threshold = await getOriginAutofillThreshold(); + Assert.equal(threshold, 0); + + await check_autocomplete({ + search, + autofilled: url, + completed: "http://" + url, + matches: [ + { + value: url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = false + // suggest.bookmark = true + // search for: visit + // prefix search: no + // prefix matches search: n/a + // origin matches search: yes + // + // Expected result: + // should autofill: no + add_task(async function suggestHistoryFalse_visit() { + await PlacesTestUtils.addVisits("http://" + url); + await check_autocomplete({ + search, + autofilled: url, + completed: "http://" + url, + matches: [ + { + value: url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); + await check_autocomplete({ + search, + matches: [], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = false + // suggest.bookmark = true + // search for: visit + // prefix search: yes + // prefix matches search: yes + // origin matches search: yes + // + // Expected result: + // should autofill: no + add_task(async function suggestHistoryFalse_visit_prefix() { + await PlacesTestUtils.addVisits("http://" + url); + await check_autocomplete({ + search: "http://" + search, + autofilled: "http://" + url, + completed: "http://" + url, + matches: [ + { + value: "http://" + url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); + await check_autocomplete({ + search: "http://" + search, + matches: [], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = false + // suggest.bookmark = true + // search for: bookmark + // prefix search: no + // prefix matches search: n/a + // origin matches search: yes + // + // Expected result: + // should autofill: yes + add_task(async function suggestHistoryFalse_bookmark_0() { + // Add the bookmark. + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://" + url, + }); + + // Make the bookmark fall below the autofill frecency threshold so we ensure + // the bookmark is always autofilled in this case, even if it doesn't meet + // the threshold. + let meetsThreshold = true; + while (meetsThreshold) { + // Add a visit to another origin to boost the threshold. + await PlacesTestUtils.addVisits("http://foo-" + url); + let originFrecency = await getOriginFrecency("http://", host); + let threshold = await getOriginAutofillThreshold(); + meetsThreshold = threshold <= originFrecency; + } + + // At this point, the bookmark doesn't meet the threshold, but it should + // still be autofilled. + let originFrecency = await getOriginFrecency("http://", host); + let threshold = await getOriginAutofillThreshold(); + Assert.ok(originFrecency < threshold); + + Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); + await check_autocomplete({ + search, + autofilled: url, + completed: "http://" + url, + matches: [ + { + value: url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = false + // suggest.bookmark = true + // search for: bookmark + // prefix search: no + // prefix matches search: n/a + // origin matches search: no + // + // Expected result: + // should autofill: no + add_task(async function suggestHistoryFalse_bookmark_1() { + Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://non-matching-" + url, + }); + await check_autocomplete({ + search, + matches: [ + { + value: "http://non-matching-" + url, + comment: "A bookmark", + style: ["bookmark"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = false + // suggest.bookmark = true + // search for: bookmark + // prefix search: yes + // prefix matches search: yes + // origin matches search: yes + // + // Expected result: + // should autofill: yes + add_task(async function suggestHistoryFalse_bookmark_prefix_0() { + // Add the bookmark. + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://" + url, + }); + + // Make the bookmark fall below the autofill frecency threshold so we ensure + // the bookmark is always autofilled in this case, even if it doesn't meet + // the threshold. + let meetsThreshold = true; + while (meetsThreshold) { + // Add a visit to another origin to boost the threshold. + await PlacesTestUtils.addVisits("http://foo-" + url); + let originFrecency = await getOriginFrecency("http://", host); + let threshold = await getOriginAutofillThreshold(); + meetsThreshold = threshold <= originFrecency; + } + + // At this point, the bookmark doesn't meet the threshold, but it should + // still be autofilled. + let originFrecency = await getOriginFrecency("http://", host); + let threshold = await getOriginAutofillThreshold(); + Assert.ok(originFrecency < threshold); + + Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://" + url, + }); + await check_autocomplete({ + search: "http://" + search, + autofilled: "http://" + url, + completed: "http://" + url, + matches: [ + { + value: "http://" + url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = false + // suggest.bookmark = true + // search for: bookmark + // prefix search: yes + // prefix matches search: no + // origin matches search: yes + // + // Expected result: + // should autofill: no + add_task(async function suggestHistoryFalse_bookmark_prefix_1() { + Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "ftp://" + url, + }); + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "ftp://" + url, + comment: "A bookmark", + style: ["bookmark"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = false + // suggest.bookmark = true + // search for: bookmark + // prefix search: yes + // prefix matches search: yes + // origin matches search: no + // + // Expected result: + // should autofill: no + add_task(async function suggestHistoryFalse_bookmark_prefix_2() { + Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://non-matching-" + url, + }); + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "http://non-matching-" + url, + comment: "A bookmark", + style: ["bookmark"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = false + // suggest.bookmark = true + // search for: bookmark + // prefix search: yes + // prefix matches search: no + // origin matches search: no + // + // Expected result: + // should autofill: no + add_task(async function suggestHistoryFalse_bookmark_prefix_3() { + Services.prefs.setBoolPref("browser.urlbar.suggest.history", false); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "ftp://non-matching-" + url, + }); + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "ftp://non-matching-" + url, + comment: "A bookmark", + style: ["bookmark"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visit + // prefix search: no + // prefix matches search: n/a + // origin matches search: yes + // + // Expected result: + // should autofill: yes + add_task(async function suggestBookmarkFalse_visit_0() { + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await PlacesTestUtils.addVisits("http://" + url); + await check_autocomplete({ + search, + autofilled: url, + completed: "http://" + url, + matches: [ + { + value: url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visit + // prefix search: no + // prefix matches search: n/a + // origin matches search: no + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_visit_1() { + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await PlacesTestUtils.addVisits("http://non-matching-" + url); + await check_autocomplete({ + search, + matches: [ + { + value: "http://non-matching-" + url, + comment: "test visit for http://non-matching-" + url, + style: ["favicon"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visit + // prefix search: yes + // prefix matches search: yes + // origin matches search: yes + // + // Expected result: + // should autofill: yes + add_task(async function suggestBookmarkFalse_visit_prefix_0() { + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await PlacesTestUtils.addVisits("http://" + url); + await check_autocomplete({ + search: "http://" + search, + autofilled: "http://" + url, + completed: "http://" + url, + matches: [ + { + value: "http://" + url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visit + // prefix search: yes + // prefix matches search: no + // origin matches search: yes + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_visit_prefix_1() { + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await PlacesTestUtils.addVisits("ftp://" + url); + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "ftp://" + url, + comment: "test visit for ftp://" + url, + style: ["favicon"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visit + // prefix search: yes + // prefix matches search: yes + // origin matches search: no + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_visit_prefix_2() { + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await PlacesTestUtils.addVisits("http://non-matching-" + url); + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "http://non-matching-" + url, + comment: "test visit for http://non-matching-" + url, + style: ["favicon"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visit + // prefix search: yes + // prefix matches search: no + // origin matches search: no + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_visit_prefix_3() { + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await PlacesTestUtils.addVisits("ftp://non-matching-" + url); + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "ftp://non-matching-" + url, + comment: "test visit for ftp://non-matching-" + url, + style: ["favicon"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: unvisited bookmark + // prefix search: no + // prefix matches search: n/a + // origin matches search: yes + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_unvisitedBookmark() { + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://" + url, + }); + await check_autocomplete({ + search, + autofilled: url, + completed: "http://" + url, + matches: [ + { + value: url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await check_autocomplete({ + search: "http://" + search, + matches: [], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: unvisited bookmark + // prefix search: yes + // prefix matches search: yes + // origin matches search: yes + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_unvisitedBookmark_prefix_0() { + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://" + url, + }); + await check_autocomplete({ + search: "http://" + search, + autofilled: "http://" + url, + completed: "http://" + url, + matches: [ + { + value: "http://" + url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await check_autocomplete({ + search: "http://" + search, + matches: [], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: unvisited bookmark + // prefix search: yes + // prefix matches search: no + // origin matches search: yes + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_unvisitedBookmark_prefix_1() { + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "ftp://" + url, + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await check_autocomplete({ + search: "http://" + search, + matches: [], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: unvisited bookmark + // prefix search: yes + // prefix matches search: yes + // origin matches search: no + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_unvisitedBookmark_prefix_2() { + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://non-matching-" + url, + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await check_autocomplete({ + search: "http://" + search, + matches: [], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: unvisited bookmark + // prefix search: yes + // prefix matches search: no + // origin matches search: no + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_unvisitedBookmark_prefix_3() { + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "ftp://non-matching-" + url, + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await check_autocomplete({ + search: "http://" + search, + matches: [], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visited bookmark above autofill threshold + // prefix search: no + // prefix matches search: n/a + // origin matches search: yes + // + // Expected result: + // should autofill: yes + add_task(async function suggestBookmarkFalse_visitedBookmark_above() { + await PlacesTestUtils.addVisits("http://" + url); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://" + url, + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await check_autocomplete({ + search, + autofilled: url, + completed: "http://" + url, + matches: [ + { + value: url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visited bookmark above autofill threshold + // prefix search: yes + // prefix matches search: yes + // origin matches search: yes + // + // Expected result: + // should autofill: yes + add_task(async function suggestBookmarkFalse_visitedBookmarkAbove_prefix_0() { + await PlacesTestUtils.addVisits("http://" + url); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://" + url, + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await check_autocomplete({ + search: "http://" + search, + autofilled: "http://" + url, + completed: "http://" + url, + matches: [ + { + value: "http://" + url, + comment, + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visited bookmark above autofill threshold + // prefix search: yes + // prefix matches search: no + // origin matches search: yes + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_visitedBookmarkAbove_prefix_1() { + await PlacesTestUtils.addVisits("ftp://" + url); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "ftp://" + url, + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "ftp://" + url, + comment: "A bookmark", + style: ["favicon"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visited bookmark above autofill threshold + // prefix search: yes + // prefix matches search: yes + // origin matches search: no + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_visitedBookmarkAbove_prefix_2() { + await PlacesTestUtils.addVisits("http://non-matching-" + url); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://non-matching-" + url, + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "http://non-matching-" + url, + comment: "A bookmark", + style: ["favicon"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visited bookmark above autofill threshold + // prefix search: yes + // prefix matches search: no + // origin matches search: no + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_visitedBookmarkAbove_prefix_3() { + await PlacesTestUtils.addVisits("ftp://non-matching-" + url); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "ftp://non-matching-" + url, + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "ftp://non-matching-" + url, + comment: "A bookmark", + style: ["favicon"], + }, + ], + }); + await cleanup(); + }); + + // The following suggestBookmarkFalse_visitedBookmarkBelow* tests are similar + // to the suggestBookmarkFalse_visitedBookmarkAbove* tests, but instead of + // checking visited bookmarks above the autofill threshold, they check visited + // bookmarks below the threshold. These tests don't make sense for URL + // queries (as opposed to origin queries) because URL queries don't use the + // same autofill threshold, so we skip them when !origins. + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visited bookmark below autofill threshold + // prefix search: no + // prefix matches search: n/a + // origin matches search: yes + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_visitedBookmarkBelow() { + if (!origins) { + // See comment above suggestBookmarkFalse_visitedBookmarkBelow. + return; + } + // First, make sure that `url` is below the autofill threshold. + await PlacesTestUtils.addVisits("http://" + url); + for (let i = 0; i < 3; i++) { + await PlacesTestUtils.addVisits("http://some-other-" + url); + } + await check_autocomplete({ + search, + matches: [ + { + value: "http://some-other-" + url, + comment: "test visit for http://some-other-" + url, + style: ["favicon"], + }, + { + value: "http://" + url, + comment: "test visit for http://" + url, + style: ["favicon"], + }, + ], + }); + // Now bookmark it and set suggest.bookmark to false. + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://" + url, + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await check_autocomplete({ + search, + matches: [ + { + value: "http://some-other-" + url, + comment: "test visit for http://some-other-" + url, + style: ["favicon"], + }, + { + value: "http://" + url, + comment: "A bookmark", + style: ["favicon"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visited bookmark below autofill threshold + // prefix search: yes + // prefix matches search: yes + // origin matches search: yes + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_visitedBookmarkBelow_prefix_0() { + if (!origins) { + // See comment above suggestBookmarkFalse_visitedBookmarkBelow. + return; + } + // First, make sure that `url` is below the autofill threshold. + await PlacesTestUtils.addVisits("http://" + url); + for (let i = 0; i < 3; i++) { + await PlacesTestUtils.addVisits("http://some-other-" + url); + } + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "http://some-other-" + url, + comment: "test visit for http://some-other-" + url, + style: ["favicon"], + }, + { + value: "http://" + url, + comment: "test visit for http://" + url, + style: ["favicon"], + }, + ], + }); + // Now bookmark it and set suggest.bookmark to false. + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://" + url, + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "http://some-other-" + url, + comment: "test visit for http://some-other-" + url, + style: ["favicon"], + }, + { + value: "http://" + url, + comment: "A bookmark", + style: ["favicon"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visited bookmark below autofill threshold + // prefix search: yes + // prefix matches search: no + // origin matches search: yes + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_visitedBookmarkBelow_prefix_1() { + if (!origins) { + // See comment above suggestBookmarkFalse_visitedBookmarkBelow. + return; + } + // First, make sure that `url` is below the autofill threshold. + await PlacesTestUtils.addVisits("ftp://" + url); + for (let i = 0; i < 3; i++) { + await PlacesTestUtils.addVisits("ftp://some-other-" + url); + } + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "ftp://some-other-" + url, + comment: "test visit for ftp://some-other-" + url, + style: ["favicon"], + }, + { + value: "ftp://" + url, + comment: "test visit for ftp://" + url, + style: ["favicon"], + }, + ], + }); + // Now bookmark it and set suggest.bookmark to false. + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "ftp://" + url, + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "ftp://some-other-" + url, + comment: "test visit for ftp://some-other-" + url, + style: ["favicon"], + }, + { + value: "ftp://" + url, + comment: "A bookmark", + style: ["favicon"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visited bookmark below autofill threshold + // prefix search: yes + // prefix matches search: yes + // origin matches search: no + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_visitedBookmarkBelow_prefix_2() { + if (!origins) { + // See comment above suggestBookmarkFalse_visitedBookmarkBelow. + return; + } + // First, make sure that `url` is below the autofill threshold. + await PlacesTestUtils.addVisits("http://non-matching-" + url); + for (let i = 0; i < 3; i++) { + await PlacesTestUtils.addVisits("http://some-other-" + url); + } + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "http://some-other-" + url, + comment: "test visit for http://some-other-" + url, + style: ["favicon"], + }, + { + value: "http://non-matching-" + url, + comment: "test visit for http://non-matching-" + url, + style: ["favicon"], + }, + ], + }); + // Now bookmark it and set suggest.bookmark to false. + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "http://non-matching-" + url, + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "http://some-other-" + url, + comment: "test visit for http://some-other-" + url, + style: ["favicon"], + }, + { + value: "http://non-matching-" + url, + comment: "A bookmark", + style: ["favicon"], + }, + ], + }); + await cleanup(); + }); + + // Tests interaction between the suggest.history and suggest.bookmark prefs. + // + // Config: + // suggest.history = true + // suggest.bookmark = false + // search for: visited bookmark below autofill threshold + // prefix search: yes + // prefix matches search: no + // origin matches search: no + // + // Expected result: + // should autofill: no + add_task(async function suggestBookmarkFalse_visitedBookmarkBelow_prefix_3() { + if (!origins) { + // See comment above suggestBookmarkFalse_visitedBookmarkBelow. + return; + } + // First, make sure that `url` is below the autofill threshold. + await PlacesTestUtils.addVisits("ftp://non-matching-" + url); + for (let i = 0; i < 3; i++) { + await PlacesTestUtils.addVisits("ftp://some-other-" + url); + } + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "ftp://some-other-" + url, + comment: "test visit for ftp://some-other-" + url, + style: ["favicon"], + }, + { + value: "ftp://non-matching-" + url, + comment: "test visit for ftp://non-matching-" + url, + style: ["favicon"], + }, + ], + }); + // Now bookmark it and set suggest.bookmark to false. + await PlacesTestUtils.addBookmarkWithDetails({ + uri: "ftp://non-matching-" + url, + }); + Services.prefs.setBoolPref("browser.urlbar.suggest.bookmark", false); + await check_autocomplete({ + search: "http://" + search, + matches: [ + { + value: "ftp://some-other-" + url, + comment: "test visit for ftp://some-other-" + url, + style: ["favicon"], + }, + { + value: "ftp://non-matching-" + url, + comment: "A bookmark", + style: ["favicon"], + }, + ], + }); + await cleanup(); + }); +} + +/** + * Returns the frecency of an origin. + * + * @param {string} prefix + * The origin's prefix, e.g., "http://". + * @param {string} host + * The origin's host. + * @returns {number} The origin's frecency. + */ +async function getOriginFrecency(prefix, host) { + let db = await PlacesUtils.promiseDBConnection(); + let rows = await db.execute( + ` + SELECT frecency + FROM moz_origins + WHERE prefix = :prefix AND host = :host + `, + { prefix, host } + ); + Assert.equal(rows.length, 1); + return rows[0].getResultByIndex(0); +} + +/** + * Returns the origin frecency stats. + * + * @returns {object} + * An object { count, sum, squares }. + */ +async function getOriginFrecencyStats() { + let db = await PlacesUtils.promiseDBConnection(); + let rows = await db.execute(` + SELECT + IFNULL((SELECT value FROM moz_meta WHERE key = 'origin_frecency_count'), 0), + IFNULL((SELECT value FROM moz_meta WHERE key = 'origin_frecency_sum'), 0), + IFNULL((SELECT value FROM moz_meta WHERE key = 'origin_frecency_sum_of_squares'), 0) + `); + let count = rows[0].getResultByIndex(0); + let sum = rows[0].getResultByIndex(1); + let squares = rows[0].getResultByIndex(2); + return { count, sum, squares }; +} + +/** + * Returns the origin autofill frecency threshold. + * + * @returns {number} + * The threshold. + */ +async function getOriginAutofillThreshold() { + let { count, sum, squares } = await getOriginFrecencyStats(); + if (!count) { + return 0; + } + if (count == 1) { + return sum; + } + let stddevMultiplier = UrlbarPrefs.get("autoFill.stddevMultiplier"); + return ( + sum / count + + stddevMultiplier * Math.sqrt((squares - (sum * sum) / count) / count) + ); +} diff --git a/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js b/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js index 0fb763095a14..51f437016b8d 100644 --- a/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js +++ b/toolkit/components/places/tests/unifiedcomplete/head_autocomplete.js @@ -44,6 +44,14 @@ var { Services.scriptloader.loadSubScript(uri.spec, this); } +// Add a lazy getter for common autofill test tasks used by some tests. +{ + /* import-globals-from ./autofill_tasks.js */ + let file = do_get_file("autofill_tasks.js", false); + let uri = Services.io.newFileURI(file); + XPCOMUtils.defineLazyScriptGetter(this, "addAutofillTasks", uri.spec); +} + // Put any other stuff relative to this test folder below. XPCOMUtils.defineLazyModuleGetters(this, { @@ -267,6 +275,10 @@ async function check_autocomplete(test) { }; }); let expectedSearches = 1; + if (test.incompleteSearch) { + controller.startSearch(test.incompleteSearch); + expectedSearches++; + } info("Searching for: '" + test.search + "'"); controller.startSearch(test.search); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_autocomplete_functional.js b/toolkit/components/places/tests/unifiedcomplete/test_autocomplete_functional.js new file mode 100644 index 000000000000..18f07eabf120 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_autocomplete_functional.js @@ -0,0 +1,62 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Functional tests for inline autocomplete + +add_task(async function test_urls_order() { + info("Add urls, check for correct order"); + let places = [ + { uri: NetUtil.newURI("http://visit1.mozilla.org") }, + { uri: NetUtil.newURI("http://visit2.mozilla.org") }, + ]; + await PlacesTestUtils.addVisits(places); + await check_autocomplete({ + search: "vis", + autofilled: "visit2.mozilla.org/", + completed: "http://visit2.mozilla.org/", + }); + await cleanup(); +}); + +add_task(async function test_bookmark_first() { + info("With a bookmark and history, the query result should be the bookmark"); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: NetUtil.newURI("http://bookmark1.mozilla.org/"), + }); + await PlacesTestUtils.addVisits( + NetUtil.newURI("http://bookmark1.mozilla.org/foo") + ); + await check_autocomplete({ + search: "bookmark", + autofilled: "bookmark1.mozilla.org/", + completed: "http://bookmark1.mozilla.org/", + }); + await cleanup(); +}); + +add_task(async function test_complete_querystring() { + info("Check to make sure we autocomplete after ?"); + await PlacesTestUtils.addVisits( + NetUtil.newURI("http://smokey.mozilla.org/foo?bacon=delicious") + ); + await check_autocomplete({ + search: "smokey.mozilla.org/foo?", + autofilled: "smokey.mozilla.org/foo?bacon=delicious", + completed: "http://smokey.mozilla.org/foo?bacon=delicious", + }); + await cleanup(); +}); + +add_task(async function test_complete_fragment() { + info("Check to make sure we autocomplete after #"); + await PlacesTestUtils.addVisits( + NetUtil.newURI("http://smokey.mozilla.org/foo?bacon=delicious#bar") + ); + await check_autocomplete({ + search: "smokey.mozilla.org/foo?bacon=delicious#bar", + autofilled: "smokey.mozilla.org/foo?bacon=delicious#bar", + completed: "http://smokey.mozilla.org/foo?bacon=delicious#bar", + }); + await cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_autofill_about_urls.js b/toolkit/components/places/tests/unifiedcomplete/test_autofill_about_urls.js new file mode 100644 index 000000000000..7de06e0551ff --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_autofill_about_urls.js @@ -0,0 +1,83 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +// "about:ab" should match "about:about" +add_task(async function aboutAb() { + await check_autocomplete({ + search: "about:ab", + autofilled: "about:about", + completed: "about:about", + matches: [ + { + value: "about:about", + comment: "about:about", + style: ["autofill", "heuristic"], + }, + ], + }); +}); + +// "about:Ab" should match "about:about" +add_task(async function aboutAb() { + await check_autocomplete({ + search: "about:Ab", + autofilled: "about:About", + completed: "about:about", + matches: [ + { + value: "about:about", + comment: "about:about", + style: ["autofill", "heuristic"], + }, + ], + }); +}); + +// "about:about" should match "about:about" +add_task(async function aboutAbout() { + await check_autocomplete({ + search: "about:about", + autofilled: "about:about", + completed: "about:about", + matches: [ + { + value: "about:about", + comment: "about:about", + style: ["autofill", "heuristic"], + }, + ], + }); +}); + +// "about:a" should complete to "about:about" and also match "about:addons" +add_task(async function aboutAboutAndAboutAddons() { + await check_autocomplete({ + search: "about:a", + autofilled: "about:about", + completed: "about:about", + matches: [ + { + value: "about:about", + comment: "about:about", + style: ["autofill", "heuristic"], + }, + { + value: "about:addons", + comment: "about:addons", + }, + ], + }); +}); + +// "about:" should *not* match anything +add_task(async function aboutColonHasNoMatch() { + await check_autocomplete({ + search: "about:", + autofilled: "about:", + completed: "about:", + matches: [], + }); +}); diff --git a/browser/components/urlbar/tests/unit/test_autofill_origins.js b/toolkit/components/places/tests/unifiedcomplete/test_autofill_origins.js similarity index 55% rename from browser/components/urlbar/tests/unit/test_autofill_origins.js rename to toolkit/components/places/tests/unifiedcomplete/test_autofill_origins.js index ac22a7408a2a..33658ee477fd 100644 --- a/browser/components/urlbar/tests/unit/test_autofill_origins.js +++ b/toolkit/components/places/tests/unifiedcomplete/test_autofill_origins.js @@ -4,20 +4,7 @@ "use strict"; -const ENGINE_NAME = "engine-suggestions.xml"; -const HEURISTIC_FALLBACK_PROVIDERNAME = "HeuristicFallback"; - -const origin = "example.com"; - -async function cleanup() { - let suggestPrefs = ["history", "bookmark", "openpage"]; - for (let type of suggestPrefs) { - Services.prefs.clearUserPref("browser.urlbar.suggest." + type); - } - await cleanupPlaces(); -} - -testEngine_setup(); +addAutofillTasks(true); // "example.com/" should match http://example.com/. i.e., the search string // should be treated as if it didn't have the trailing slash. @@ -27,18 +14,16 @@ add_task(async function trailingSlash() { uri: "http://example.com/", }, ]); - - let context = createContext(`${origin}/`, { isPrivate: false }); - await check_results({ - context, - autofilled: `${origin}/`, - completed: `http://${origin}/`, + await check_autocomplete({ + search: "example.com/", + autofilled: "example.com/", + completed: "http://example.com/", matches: [ - makeVisitResult(context, { - uri: `http://${origin}/`, - title: `${origin}/`, - heuristic: true, - }), + { + value: "example.com/", + comment: "example.com/", + style: ["autofill", "heuristic"], + }, ], }); await cleanup(); @@ -52,17 +37,16 @@ add_task(async function trailingSlashWWW() { uri: "http://www.example.com/", }, ]); - let context = createContext(`${origin}/`, { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ + search: "example.com/", autofilled: "example.com/", completed: "http://www.example.com/", matches: [ - makeVisitResult(context, { - uri: `http://www.${origin}/`, - title: `www.${origin}/`, - heuristic: true, - }), + { + value: "example.com/", + comment: "www.example.com/", + style: ["autofill", "heuristic"], + }, ], }); await cleanup(); @@ -75,17 +59,16 @@ add_task(async function port() { uri: "http://example.com:8888/", }, ]); - let context = createContext("ex", { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ + search: "ex", autofilled: "example.com:8888/", completed: "http://example.com:8888/", matches: [ - makeVisitResult(context, { - uri: `http://${origin}:8888/`, - title: `${origin}:8888`, - heuristic: true, - }), + { + value: "example.com:8888/", + comment: "example.com:8888", + style: ["autofill", "heuristic"], + }, ], }); await cleanup(); @@ -99,17 +82,16 @@ add_task(async function portPartial() { uri: "http://example.com:8888/", }, ]); - let context = createContext(`${origin}:8`, { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ + search: "example.com:8", autofilled: "example.com:8888/", completed: "http://example.com:8888/", matches: [ - makeVisitResult(context, { - uri: `http://${origin}:8888/`, - title: `${origin}:8888`, - heuristic: true, - }), + { + value: "example.com:8888/", + comment: "example.com:8888", + style: ["autofill", "heuristic"], + }, ], }); await cleanup(); @@ -123,17 +105,16 @@ add_task(async function preserveCase() { uri: "http://example.com/", }, ]); - let context = createContext("EXaM", { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ + search: "EXaM", autofilled: "EXaMple.com/", completed: "http://example.com/", matches: [ - makeVisitResult(context, { - uri: `http://${origin}/`, - title: `${origin}`, - heuristic: true, - }), + { + value: "example.com/", + comment: "example.com", + style: ["autofill", "heuristic"], + }, ], }); await cleanup(); @@ -148,17 +129,16 @@ add_task(async function preserveCasePort() { uri: "http://example.com:8888/", }, ]); - let context = createContext("EXaM", { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ + search: "EXaM", autofilled: "EXaMple.com:8888/", completed: "http://example.com:8888/", matches: [ - makeVisitResult(context, { - uri: `http://${origin}:8888/`, - title: `${origin}:8888`, - heuristic: true, - }), + { + value: "example.com:8888/", + comment: "example.com:8888", + style: ["autofill", "heuristic"], + }, ], }); await cleanup(); @@ -171,18 +151,9 @@ add_task(async function portNoMatch1() { uri: "http://example.com:8888/", }, ]); - let context = createContext(`${origin}:89`, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: `http://${origin}:89/`, - title: `http://${origin}:89/`, - iconUri: "", - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], + await check_autocomplete({ + search: "example.com:89", + matches: [], }); await cleanup(); }); @@ -194,18 +165,9 @@ add_task(async function portNoMatch2() { uri: "http://example.com:8888/", }, ]); - let context = createContext(`${origin}:9`, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: `http://${origin}:9/`, - title: `http://${origin}:9/`, - iconUri: "", - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], + await check_autocomplete({ + search: "example.com:9", + matches: [], }); await cleanup(); }); @@ -217,17 +179,9 @@ add_task(async function trailingSlash() { uri: "http://example.com/", }, ]); - let context = createContext("example/", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: "http://example/", - title: "http://example/", - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], + await check_autocomplete({ + search: "example/", + matches: [], }); await cleanup(); }); @@ -239,31 +193,21 @@ add_task(async function multidotted() { uri: "http://www.example.co.jp:8888/", }, ]); - let context = createContext("www.example.co.", { isPrivate: false }); - await check_results({ - context, - autofilled: "www.example.co.jp:8888/", + await check_autocomplete({ + search: "www.example.co.", completed: "http://www.example.co.jp:8888/", matches: [ - makeVisitResult(context, { - uri: "http://www.example.co.jp:8888/", - title: "www.example.co.jp:8888", - heuristic: true, - }), - makeSearchResult(context, { - engineName: ENGINE_NAME, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), + { + value: "www.example.co.jp:8888/", + comment: "www.example.co.jp:8888", + style: ["autofill", "heuristic"], + }, ], }); await cleanup(); }); add_task(async function test_ip() { - // IP addresses have complicated rules around whether they show - // HeuristicFallback's backup search result. Flip this pref to disable that - // backup search and simplify ths subtest. - Services.prefs.setBoolPref("keyword.enabled", false); for (let str of [ "192.168.1.1/", "255.255.255.255:8080/", @@ -274,23 +218,20 @@ add_task(async function test_ip() { info("testing " + str); await PlacesTestUtils.addVisits("http://" + str); for (let i = 1; i < str.length; ++i) { - let context = createContext(str.substring(0, i), { isPrivate: false }); - await check_results({ - context, - autofilled: str, + await check_autocomplete({ + search: str.substring(0, i), completed: "http://" + str, matches: [ - makeVisitResult(context, { - uri: "http://" + str, - title: str.replace(/\/$/, ""), // strip trailing slash - heuristic: true, - }), + { + value: str, + comment: str.replace(/\/$/, ""), // strip trailing slash + style: ["autofill", "heuristic"], + }, ], }); } await cleanup(); } - Services.prefs.clearUserPref("keyword.enabled"); }); // host starting with large number. @@ -300,17 +241,15 @@ add_task(async function large_number_host() { uri: "http://12345example.it:8888/", }, ]); - let context = createContext("1234", { isPrivate: false }); - await check_results({ - context, - autofilled: "12345example.it:8888/", + await check_autocomplete({ + search: "1234", completed: "http://12345example.it:8888/", matches: [ - makeVisitResult(context, { - uri: "http://12345example.it:8888/", - title: "12345example.it:8888", - heuristic: true, - }), + { + value: "12345example.it:8888/", + comment: "12345example.it:8888", + style: ["autofill", "heuristic"], + }, ], }); await cleanup(); @@ -357,17 +296,16 @@ add_task(async function groupByHost() { ); // The https origin should be autofilled. - let context = createContext("ex", { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ + search: "ex", autofilled: "example.com/", completed: "https://example.com/", matches: [ - makeVisitResult(context, { - uri: "https://example.com/", - title: "https://example.com", - heuristic: true, - }), + { + value: "example.com/", + comment: "https://example.com", + style: ["autofill", "heuristic"], + }, ], }); @@ -422,17 +360,16 @@ add_task(async function groupByHostNonDefaultStddevMultiplier() { ); // The https origin should be autofilled. - let context = createContext("ex", { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ + search: "ex", autofilled: "example.com/", completed: "https://example.com/", matches: [ - makeVisitResult(context, { - uri: "https://example.com/", - title: "https://example.com", - heuristic: true, - }), + { + value: "example.com/", + comment: "https://example.com", + style: ["autofill", "heuristic"], + }, ], }); @@ -441,8 +378,8 @@ add_task(async function groupByHostNonDefaultStddevMultiplier() { await cleanup(); }); -// This is similar to suggestHistoryFalse_bookmark_0 in test_autofill_tasks.js, -// but it adds unbookmarked visits for multiple URLs with the same origin. +// This is similar to suggestHistoryFalse_bookmark_0 in autofill_tasks.js, but +// it adds unbookmarked visits for multiple URLs with the same origin. add_task(async function suggestHistoryFalse_bookmark_multiple() { // Force only bookmarked pages to be suggested and therefore only bookmarked // pages to be completed. @@ -463,16 +400,9 @@ add_task(async function suggestHistoryFalse_bookmark_multiple() { uri: baseURL + "other1", }, ]); - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - heuristic: true, - }), - ], + await check_autocomplete({ + search, + matches: [], }); await PlacesTestUtils.addVisits([ @@ -480,16 +410,9 @@ add_task(async function suggestHistoryFalse_bookmark_multiple() { uri: bookmarkedURL, }, ]); - context = createContext(search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - heuristic: true, - }), - ], + await check_autocomplete({ + search, + matches: [], }); await PlacesTestUtils.addVisits([ @@ -497,37 +420,30 @@ add_task(async function suggestHistoryFalse_bookmark_multiple() { uri: baseURL + "other2", }, ]); - context = createContext(search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - heuristic: true, - }), - ], + await check_autocomplete({ + search, + matches: [], }); // Now bookmark the second URL. It should be suggested and completed. await PlacesTestUtils.addBookmarkWithDetails({ uri: bookmarkedURL, }); - context = createContext(search, { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ + search, autofilled: "example.com/", completed: baseURL, matches: [ - makeVisitResult(context, { - uri: baseURL, - title: "example.com", - heuristic: true, - }), - makeBookmarkResult(context, { - uri: bookmarkedURL, - title: "A bookmark", - }), + { + value: "example.com/", + comment: "example.com", + style: ["autofill", "heuristic"], + }, + { + value: bookmarkedURL, + comment: "A bookmark", + style: ["bookmark"], + }, ], }); @@ -557,18 +473,9 @@ add_task(async function suggestHistoryFalse_bookmark_prefix_multiple() { uri: baseURL + "other1", }, ]); - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: `${search}/`, - title: `${search}/`, - iconUri: "", - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], + await check_autocomplete({ + search, + matches: [], }); await PlacesTestUtils.addVisits([ @@ -576,18 +483,9 @@ add_task(async function suggestHistoryFalse_bookmark_prefix_multiple() { uri: bookmarkedURL, }, ]); - context = createContext(search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: `${search}/`, - title: `${search}/`, - iconUri: "", - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], + await check_autocomplete({ + search, + matches: [], }); await PlacesTestUtils.addVisits([ @@ -595,82 +493,32 @@ add_task(async function suggestHistoryFalse_bookmark_prefix_multiple() { uri: baseURL + "other2", }, ]); - context = createContext(search, { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: `${search}/`, - title: `${search}/`, - iconUri: "", - heuristic: true, - providerName: HEURISTIC_FALLBACK_PROVIDERNAME, - }), - ], + await check_autocomplete({ + search, + matches: [], }); // Now bookmark the second URL. It should be suggested and completed. await PlacesTestUtils.addBookmarkWithDetails({ uri: bookmarkedURL, }); - context = createContext(search, { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ + search, autofilled: "http://example.com/", completed: baseURL, matches: [ - makeVisitResult(context, { - uri: baseURL, - title: "example.com", - heuristic: true, - }), - makeBookmarkResult(context, { - uri: bookmarkedURL, - title: "A bookmark", - }), + { + value: "http://example.com/", + comment: "example.com", + style: ["autofill", "heuristic"], + }, + { + value: bookmarkedURL, + comment: "A bookmark", + style: ["bookmark"], + }, ], }); await cleanup(); }); - -/** - * Returns the origin frecency stats. - * - * @returns {object} - * An object { count, sum, squares }. - */ -async function getOriginFrecencyStats() { - let db = await PlacesUtils.promiseDBConnection(); - let rows = await db.execute(` - SELECT - IFNULL((SELECT value FROM moz_meta WHERE key = 'origin_frecency_count'), 0), - IFNULL((SELECT value FROM moz_meta WHERE key = 'origin_frecency_sum'), 0), - IFNULL((SELECT value FROM moz_meta WHERE key = 'origin_frecency_sum_of_squares'), 0) - `); - let count = rows[0].getResultByIndex(0); - let sum = rows[0].getResultByIndex(1); - let squares = rows[0].getResultByIndex(2); - return { count, sum, squares }; -} - -/** - * Returns the origin autofill frecency threshold. - * - * @returns {number} - * The threshold. - */ -async function getOriginAutofillThreshold() { - let { count, sum, squares } = await getOriginFrecencyStats(); - if (!count) { - return 0; - } - if (count == 1) { - return sum; - } - let stddevMultiplier = UrlbarPrefs.get("autoFill.stddevMultiplier"); - return ( - sum / count + - stddevMultiplier * Math.sqrt((squares - (sum * sum) / count) / count) - ); -} diff --git a/browser/components/urlbar/tests/unit/test_autofill_search_engine_aliases.js b/toolkit/components/places/tests/unifiedcomplete/test_autofill_search_engine_aliases.js similarity index 68% rename from browser/components/urlbar/tests/unit/test_autofill_search_engine_aliases.js rename to toolkit/components/places/tests/unifiedcomplete/test_autofill_search_engine_aliases.js index 0368221aad48..2d2fd773eb0e 100644 --- a/browser/components/urlbar/tests/unit/test_autofill_search_engine_aliases.js +++ b/toolkit/components/places/tests/unifiedcomplete/test_autofill_search_engine_aliases.js @@ -32,26 +32,30 @@ add_task(async function basic() { title: TEST_ENGINE_ALIAS, }); - let search = TEST_ENGINE_ALIAS.substr( - 0, - Math.round(TEST_ENGINE_ALIAS.length / 2) - ); let autofilledValue = TEST_ENGINE_ALIAS + " "; - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, + let completedURL = makeActionURI("searchengine", { + engineName: TEST_ENGINE_NAME, + alias: TEST_ENGINE_ALIAS, + input: autofilledValue, + searchQuery: "", + }).spec; + await check_autocomplete({ + search: TEST_ENGINE_ALIAS.substr( + 0, + Math.round(TEST_ENGINE_ALIAS.length / 2) + ), autofilled: autofilledValue, + completed: completedURL, matches: [ - makeSearchResult(context, { - engineName: TEST_ENGINE_NAME, - alias: TEST_ENGINE_ALIAS, - query: "", - keywordOffer: UrlbarUtils.KEYWORD_OFFER.HIDE, - heuristic: true, - }), + { + value: autofilledValue, + comment: TEST_ENGINE_NAME, + uri: completedURL, + style: ["autofill", "action", "searchengine", "heuristic"], + }, ], }); - await cleanupPlaces(); + await cleanup(); }); // Searching for @AUTOFI should autofill to @AUTOFIlltest, preserving the case @@ -70,21 +74,25 @@ add_task(async function preserveCase() { Math.round(TEST_ENGINE_ALIAS.length / 2) ); let alias = search + TEST_ENGINE_ALIAS.substr(search.length); - let autofilledValue = alias + " "; - let context = createContext(search, { isPrivate: false }); - await check_results({ - context, + let completedURL = makeActionURI("searchengine", { + engineName: TEST_ENGINE_NAME, + alias, + input: autofilledValue, + searchQuery: "", + }).spec; + await check_autocomplete({ + search, autofilled: autofilledValue, + completed: completedURL, matches: [ - makeSearchResult(context, { - engineName: TEST_ENGINE_NAME, - alias, - query: "", - keywordOffer: UrlbarUtils.KEYWORD_OFFER.HIDE, - heuristic: true, - }), + { + value: autofilledValue, + comment: TEST_ENGINE_NAME, + uri: completedURL, + style: ["autofill", "action", "searchengine", "heuristic"], + }, ], }); - await cleanupPlaces(); + await cleanup(); }); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_autofill_search_engines.js b/toolkit/components/places/tests/unifiedcomplete/test_autofill_search_engines.js new file mode 100644 index 000000000000..20b4d707163b --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_autofill_search_engines.js @@ -0,0 +1,201 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// The autoFill.searchEngines pref autofills the domains of engines registered +// with the search service. That's what this test checks. It's a different +// path in UnifiedComplete.js from normal moz_places autofill, which is tested +// in test_autofill_origins.js and test_autofill_urls.js. + +"use strict"; + +add_task(async function searchEngines() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); + + let schemes = ["http", "https"]; + for (let i = 0; i < schemes.length; i++) { + let scheme = schemes[i]; + let engine = await Services.search.addEngineWithDetails("TestEngine", { + method: "GET", + template: scheme + "://www.example.com/", + searchGetParams: "q={searchTerms}", + }); + + await check_autocomplete({ + search: "ex", + autofilled: "example.com/", + completed: scheme + "://www.example.com/", + matches: [ + { + value: "example.com/", + comment: "TestEngine", + style: ["heuristic", "priority-search"], + }, + ], + }); + + await check_autocomplete({ + search: "example.com", + autofilled: "example.com/", + completed: scheme + "://www.example.com/", + matches: [ + { + value: "example.com/", + comment: "TestEngine", + style: ["heuristic", "priority-search"], + }, + ], + }); + + await check_autocomplete({ + search: "example.com/", + autofilled: "example.com/", + completed: scheme + "://www.example.com/", + matches: [ + { + value: "example.com/", + comment: "TestEngine", + style: ["heuristic", "priority-search"], + }, + ], + }); + + await check_autocomplete({ + search: "www.ex", + autofilled: "www.example.com/", + completed: scheme + "://www.example.com/", + matches: [ + { + value: "www.example.com/", + comment: "TestEngine", + style: ["heuristic", "priority-search"], + }, + ], + }); + + await check_autocomplete({ + search: "www.example.com", + autofilled: "www.example.com/", + completed: scheme + "://www.example.com/", + matches: [ + { + value: "www.example.com/", + comment: "TestEngine", + style: ["heuristic", "priority-search"], + }, + ], + }); + + await check_autocomplete({ + search: "www.example.com/", + autofilled: "www.example.com/", + completed: scheme + "://www.example.com/", + matches: [ + { + value: "www.example.com/", + comment: "TestEngine", + style: ["heuristic", "priority-search"], + }, + ], + }); + + await check_autocomplete({ + search: scheme + "://ex", + autofilled: scheme + "://example.com/", + completed: scheme + "://www.example.com/", + matches: [ + { + value: scheme + "://example.com/", + comment: "TestEngine", + style: ["heuristic", "priority-search"], + }, + ], + }); + + await check_autocomplete({ + search: scheme + "://example.com", + autofilled: scheme + "://example.com/", + completed: scheme + "://www.example.com/", + matches: [ + { + value: scheme + "://example.com/", + comment: "TestEngine", + style: ["heuristic", "priority-search"], + }, + ], + }); + + await check_autocomplete({ + search: scheme + "://example.com/", + autofilled: scheme + "://example.com/", + completed: scheme + "://www.example.com/", + matches: [ + { + value: scheme + "://example.com/", + comment: "TestEngine", + style: ["heuristic", "priority-search"], + }, + ], + }); + + await check_autocomplete({ + search: scheme + "://www.ex", + autofilled: scheme + "://www.example.com/", + completed: scheme + "://www.example.com/", + matches: [ + { + value: scheme + "://www.example.com/", + comment: "TestEngine", + style: ["heuristic", "priority-search"], + }, + ], + }); + + await check_autocomplete({ + search: scheme + "://www.example.com", + autofilled: scheme + "://www.example.com/", + completed: scheme + "://www.example.com/", + matches: [ + { + value: scheme + "://www.example.com/", + comment: "TestEngine", + style: ["heuristic", "priority-search"], + }, + ], + }); + + await check_autocomplete({ + search: scheme + "://www.example.com/", + autofilled: scheme + "://www.example.com/", + completed: scheme + "://www.example.com/", + matches: [ + { + value: scheme + "://www.example.com/", + comment: "TestEngine", + style: ["heuristic", "priority-search"], + }, + ], + }); + + let otherScheme = schemes[(i + 1) % schemes.length]; + await check_autocomplete({ + search: otherScheme + "://ex", + matches: [], + }); + await check_autocomplete({ + search: otherScheme + "://www.ex", + matches: [], + }); + + await check_autocomplete({ + search: "example/", + autofilled: "example/", + completed: "example/", + matches: [], + }); + + await Services.search.removeEngine(engine); + } + + await cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_autofill_urls.js b/toolkit/components/places/tests/unifiedcomplete/test_autofill_urls.js new file mode 100644 index 000000000000..9a8bd8ce9dd2 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_autofill_urls.js @@ -0,0 +1,114 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +addAutofillTasks(false); + +// "example.com/foo/" should match http://example.com/foo/. +add_task(async function multipleSlashes() { + await PlacesTestUtils.addVisits([ + { + uri: "http://example.com/foo/", + }, + ]); + await check_autocomplete({ + search: "example.com/foo/", + autofilled: "example.com/foo/", + completed: "http://example.com/foo/", + matches: [ + { + value: "example.com/foo/", + comment: "example.com/foo/", + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); +}); + +// "example.com:8888/f" should match http://example.com:8888/foo. +add_task(async function port() { + await PlacesTestUtils.addVisits([ + { + uri: "http://example.com:8888/foo", + }, + ]); + await check_autocomplete({ + search: "example.com:8888/f", + autofilled: "example.com:8888/foo", + completed: "http://example.com:8888/foo", + matches: [ + { + value: "example.com:8888/foo", + comment: "example.com:8888/foo", + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); +}); + +// "example.com:8999/f" should *not* match http://example.com:8888/foo. +add_task(async function portNoMatch() { + await PlacesTestUtils.addVisits([ + { + uri: "http://example.com:8888/foo", + }, + ]); + await check_autocomplete({ + search: "example.com:8999/f", + matches: [], + }); + await cleanup(); +}); + +// autofill to the next slash +add_task(async function port() { + await PlacesTestUtils.addVisits([ + { + uri: "http://example.com:8888/foo/bar/baz", + }, + ]); + await check_autocomplete({ + search: "example.com:8888/foo/b", + autofilled: "example.com:8888/foo/bar/", + completed: "http://example.com:8888/foo/bar/", + matches: [ + { + value: "example.com:8888/foo/bar/", + comment: "example.com:8888/foo/bar/", + style: ["autofill", "heuristic"], + }, + { + value: "http://example.com:8888/foo/bar/baz", + comment: "test visit for http://example.com:8888/foo/bar/baz", + style: ["favicon"], + }, + ], + }); + await cleanup(); +}); + +// autofill to the next slash, end of url +add_task(async function port() { + await PlacesTestUtils.addVisits([ + { + uri: "http://example.com:8888/foo/bar/baz", + }, + ]); + await check_autocomplete({ + search: "example.com:8888/foo/bar/b", + autofilled: "example.com:8888/foo/bar/baz", + completed: "http://example.com:8888/foo/bar/baz", + matches: [ + { + value: "example.com:8888/foo/bar/baz", + comment: "example.com:8888/foo/bar/baz", + style: ["autofill", "heuristic"], + }, + ], + }); + await cleanup(); +}); diff --git a/browser/components/urlbar/tests/unit/test_avoid_middle_complete.js b/toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js similarity index 53% rename from browser/components/urlbar/tests/unit/test_avoid_middle_complete.js rename to toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js index 4c304e27583b..b81ce7c1f959 100644 --- a/browser/components/urlbar/tests/unit/test_avoid_middle_complete.js +++ b/toolkit/components/places/tests/unifiedcomplete/test_avoid_middle_complete.js @@ -2,58 +2,36 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -const ENGINE_NAME = "engine-suggestions.xml"; - -testEngine_setup(); - add_task(async function test_prefix_space_noautofill() { await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://moz.org/test/"), + uri: NetUtil.newURI("http://moz.org/test/"), + transition: TRANSITION_TYPED, }); info("Should not try to autoFill if search string contains a space"); - let context = createContext(" mo", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - query: " mo", - heuristic: true, - }), - makeVisitResult(context, { - uri: "http://moz.org/test/", - title: "test visit for http://moz.org/test/", - }), - ], + await check_autocomplete({ + search: " mo", + autofilled: " mo", + completed: " mo", }); - await cleanupPlaces(); + await cleanup(); }); add_task(async function test_trailing_space_noautofill() { await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://moz.org/test/"), + uri: NetUtil.newURI("http://moz.org/test/"), + transition: TRANSITION_TYPED, }); info("Should not try to autoFill if search string contains a space"); - let context = createContext("mo ", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - query: "mo ", - heuristic: true, - }), - makeVisitResult(context, { - uri: "http://moz.org/test/", - title: "test visit for http://moz.org/test/", - }), - ], + await check_autocomplete({ + search: "mo ", + autofilled: "mo ", + completed: "mo ", }); - await cleanupPlaces(); + await cleanup(); }); add_task(async function test_searchEngine_autofill() { @@ -68,18 +46,13 @@ add_task(async function test_searchEngine_autofill() { info( "Should autoFill search engine if search string does not contains a space" ); - let context = createContext("ca", { isPrivate: false }); - await check_results({ - context, - matches: [ - makePrioritySearchResult(context, { - engineName: "CakeSearch", - heuristic: true, - }), - ], + await check_autocomplete({ + search: "ca", + autofilled: "cake.search/", + completed: "http://cake.search/", }); - await cleanupPlaces(); + await cleanup(); }); add_task(async function test_searchEngine_prefix_space_noautofill() { @@ -94,19 +67,13 @@ add_task(async function test_searchEngine_prefix_space_noautofill() { info( "Should not try to autoFill search engine if search string contains a space" ); - let context = createContext(" cu", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - query: " cu", - heuristic: true, - }), - ], + await check_autocomplete({ + search: " cu", + autofilled: " cu", + completed: " cu", }); - await cleanupPlaces(); + await cleanup(); }); add_task(async function test_searchEngine_trailing_space_noautofill() { @@ -121,19 +88,13 @@ add_task(async function test_searchEngine_trailing_space_noautofill() { info( "Should not try to autoFill search engine if search string contains a space" ); - let context = createContext("ba ", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - query: "ba ", - heuristic: true, - }), - ], + await check_autocomplete({ + search: "ba ", + autofilled: "ba ", + completed: "ba ", }); - await cleanupPlaces(); + await cleanup(); }); add_task(async function test_searchEngine_www_noautofill() { @@ -148,18 +109,13 @@ add_task(async function test_searchEngine_www_noautofill() { info( "Should not autoFill search engine if search string contains www. but engine doesn't" ); - let context = createContext("www.ham", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeSearchResult(context, { - engineName: ENGINE_NAME, - heuristic: true, - }), - ], + await check_autocomplete({ + search: "www.ham", + autofilled: "www.ham", + completed: "www.ham", }); - await cleanupPlaces(); + await cleanup(); }); add_task(async function test_searchEngine_different_scheme_noautofill() { @@ -174,20 +130,13 @@ add_task(async function test_searchEngine_different_scheme_noautofill() { info( "Should not autoFill search engine if search string has a different scheme." ); - let context = createContext("http://pie", { isPrivate: false }); - await check_results({ - context, - matches: [ - makeVisitResult(context, { - uri: "http://pie/", - title: "http://pie/", - iconUri: "", - heuristic: true, - }), - ], + await check_autocomplete({ + search: "http://pie", + autofilled: "http://pie", + completed: "http://pie", }); - await cleanupPlaces(); + await cleanup(); }); add_task(async function test_searchEngine_matching_prefix_autofill() { @@ -200,77 +149,46 @@ add_task(async function test_searchEngine_matching_prefix_autofill() { registerCleanupFunction(async () => Services.search.removeEngine(engine)); info("Should autoFill search engine if search string has matching prefix."); - let context = createContext("http://www.be", { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ + search: "http://www.be", autofilled: "http://www.bean.search/", - matches: [ - makePrioritySearchResult(context, { - engineName: "BeanSearch", - heuristic: true, - }), - ], + completed: "http://www.bean.search/", }); info("Should autoFill search engine if search string has www prefix."); - context = createContext("www.be", { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ + search: "www.be", autofilled: "www.bean.search/", - matches: [ - makePrioritySearchResult(context, { - engineName: "BeanSearch", - heuristic: true, - }), - ], + completed: "http://www.bean.search/", }); info("Should autoFill search engine if search string has matching scheme."); - context = createContext("http://be", { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ + search: "http://be", autofilled: "http://bean.search/", - matches: [ - makePrioritySearchResult(context, { - engineName: "BeanSearch", - heuristic: true, - }), - ], + completed: "http://www.bean.search/", }); - await cleanupPlaces(); + await cleanup(); }); add_task(async function test_prefix_autofill() { await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://mozilla.org/test/"), + uri: NetUtil.newURI("http://mozilla.org/test/"), }); await PlacesTestUtils.addVisits({ - uri: Services.io.newURI("http://moz.org/test/"), + uri: NetUtil.newURI("http://moz.org/test/"), }); info( "Should not try to autoFill in-the-middle if a search is canceled immediately" ); - let context = createContext("mozi", { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ incompleteSearch: "moz", + search: "mozi", autofilled: "mozilla.org/", completed: "http://mozilla.org/", - matches: [ - makeVisitResult(context, { - uri: "http://mozilla.org/", - title: "mozilla.org", - heuristic: true, - }), - makeVisitResult(context, { - uri: "http://mozilla.org/test/", - title: "test visit for http://mozilla.org/test/", - providerName: "UnifiedComplete", - }), - ], }); - await cleanupPlaces(); + await cleanup(); }); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_avoid_stripping_to_empty_tokens.js b/toolkit/components/places/tests/unifiedcomplete/test_avoid_stripping_to_empty_tokens.js new file mode 100644 index 000000000000..fb22092ad7fa --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_avoid_stripping_to_empty_tokens.js @@ -0,0 +1,81 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(async function test_protocol_trimming() { + for (let prot of ["http", "https", "ftp"]) { + let visit = { + // Include the protocol in the query string to ensure we get matches (see bug 1059395) + uri: NetUtil.newURI( + prot + + "://www.mozilla.org/test/?q=" + + prot + + encodeURIComponent("://") + + "www.foo" + ), + title: "Test title", + transition: TRANSITION_TYPED, + }; + await PlacesTestUtils.addVisits(visit); + + let input = prot + "://www."; + info("Searching for: " + input); + await check_autocomplete({ + search: input, + matches: [ + { + value: prot + "://www.mozilla.org/", + comment: + prot == "http" ? "www.mozilla.org" : prot + "://www.mozilla.org", + style: ["autofill", "heuristic"], + }, + { + value: visit.uri.spec, + comment: visit.title, + style: ["favicon"], + }, + ], + }); + + input = "www."; + info("Searching for: " + input); + await check_autocomplete({ + search: input, + matches: [ + { + value: "www.mozilla.org/", + comment: + prot == "http" ? "www.mozilla.org" : prot + "://www.mozilla.org", + style: ["autofill", "heuristic"], + }, + { + value: visit.uri.spec, + comment: visit.title, + style: ["favicon"], + }, + ], + }); + + let inputs = [ + prot + "://", + prot + ":// ", + prot + ":// mo", + prot + "://mo te", + prot + "://www. ", + prot + "://www. mo", + prot + "://www.mo te", + "www. ", + "www. mo", + "www.mo te", + ]; + for (input of inputs) { + info("Searching for: " + input); + await check_autocomplete({ + search: input, + matches: [{ uri: visit.uri, title: visit.title }], + }); + } + + await cleanup(); + } +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_casing.js b/toolkit/components/places/tests/unifiedcomplete/test_casing.js new file mode 100644 index 000000000000..b0fcf4ecfd6d --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_casing.js @@ -0,0 +1,212 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(async function test_casing_1() { + info("Searching for cased entry 1"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/test/"), + }); + await check_autocomplete({ + search: "MOZ", + autofilled: "MOZilla.org/", + completed: "http://mozilla.org/", + }); + await cleanup(); +}); + +add_task(async function test_casing_2() { + info("Searching for cased entry 2"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/test/"), + }); + await check_autocomplete({ + search: "mozilla.org/T", + autofilled: "mozilla.org/T", + completed: "mozilla.org/T", + }); + await cleanup(); +}); + +add_task(async function test_casing_3() { + info("Searching for cased entry 3"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/Test/"), + }); + await check_autocomplete({ + search: "mozilla.org/T", + autofilled: "mozilla.org/Test/", + completed: "http://mozilla.org/Test/", + }); + await cleanup(); +}); + +add_task(async function test_casing_4() { + info("Searching for cased entry 4"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/Test/"), + }); + await check_autocomplete({ + search: "mOzilla.org/t", + autofilled: "mOzilla.org/t", + completed: "mOzilla.org/t", + }); + await cleanup(); +}); + +add_task(async function test_casing_5() { + info("Searching for cased entry 5"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/Test/"), + }); + await check_autocomplete({ + search: "mOzilla.org/T", + autofilled: "mOzilla.org/Test/", + completed: "http://mozilla.org/Test/", + }); + await cleanup(); +}); + +add_task(async function test_untrimmed_casing() { + info("Searching for untrimmed cased entry"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/Test/"), + }); + await check_autocomplete({ + search: "http://mOz", + autofilled: "http://mOzilla.org/", + completed: "http://mozilla.org/", + }); + await cleanup(); +}); + +add_task(async function test_untrimmed_www_casing() { + info("Searching for untrimmed cased entry with www"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://www.mozilla.org/Test/"), + }); + await check_autocomplete({ + search: "http://www.mOz", + autofilled: "http://www.mOzilla.org/", + completed: "http://www.mozilla.org/", + }); + await cleanup(); +}); + +add_task(async function test_untrimmed_path_casing() { + info("Searching for untrimmed cased entry with path"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/Test/"), + }); + await check_autocomplete({ + search: "http://mOzilla.org/t", + autofilled: "http://mOzilla.org/t", + completed: "http://mOzilla.org/t", + }); + await cleanup(); +}); + +add_task(async function test_untrimmed_path_casing_2() { + info("Searching for untrimmed cased entry with path 2"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://mozilla.org/Test/"), + }); + await check_autocomplete({ + search: "http://mOzilla.org/T", + autofilled: "http://mOzilla.org/Test/", + completed: "http://mozilla.org/Test/", + }); + await cleanup(); +}); + +add_task(async function test_untrimmed_path_www_casing() { + info("Searching for untrimmed cased entry with www and path"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://www.mozilla.org/Test/"), + }); + await check_autocomplete({ + search: "http://www.mOzilla.org/t", + autofilled: "http://www.mOzilla.org/t", + completed: "http://www.mOzilla.org/t", + }); + await cleanup(); +}); + +add_task(async function test_untrimmed_path_www_casing_2() { + info("Searching for untrimmed cased entry with www and path 2"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://www.mozilla.org/Test/"), + }); + await check_autocomplete({ + search: "http://www.mOzilla.org/T", + autofilled: "http://www.mOzilla.org/Test/", + completed: "http://www.mozilla.org/Test/", + }); + await cleanup(); +}); + +add_task(async function test_searching() { + let uri1 = NetUtil.newURI("http://dummy/1/"); + let uri2 = NetUtil.newURI("http://dummy/2/"); + let uri3 = NetUtil.newURI("http://dummy/3/"); + let uri4 = NetUtil.newURI("http://dummy/4/"); + let uri5 = NetUtil.newURI("http://dummy/5/"); + + await PlacesTestUtils.addVisits([ + { uri: uri1, title: "uppercase lambda \u039B" }, + { uri: uri2, title: "lowercase lambda \u03BB" }, + { uri: uri3, title: "symbol \u212A" }, // kelvin + { uri: uri4, title: "uppercase K" }, + { uri: uri5, title: "lowercase k" }, + ]); + + info("Search for lowercase lambda"); + await check_autocomplete({ + search: "\u03BB", + matches: [ + { uri: uri1, title: "uppercase lambda \u039B" }, + { uri: uri2, title: "lowercase lambda \u03BB" }, + ], + }); + + info("Search for uppercase lambda"); + await check_autocomplete({ + search: "\u039B", + matches: [ + { uri: uri1, title: "uppercase lambda \u039B" }, + { uri: uri2, title: "lowercase lambda \u03BB" }, + ], + }); + + info("Search for kelvin sign"); + await check_autocomplete({ + search: "\u212A", + matches: [ + { uri: uri3, title: "symbol \u212A" }, + { uri: uri4, title: "uppercase K" }, + { uri: uri5, title: "lowercase k" }, + ], + }); + + info("Search for lowercase k"); + await check_autocomplete({ + search: "k", + matches: [ + { uri: uri3, title: "symbol \u212A" }, + { uri: uri4, title: "uppercase K" }, + { uri: uri5, title: "lowercase k" }, + ], + }); + + info("Search for uppercase k"); + await check_autocomplete({ + search: "K", + matches: [ + { uri: uri3, title: "symbol \u212A" }, + { uri: uri4, title: "uppercase K" }, + { uri: uri5, title: "lowercase k" }, + ], + }); + + await cleanup(); +}); diff --git a/browser/components/urlbar/tests/unit/test_dedupe_prefix.js b/toolkit/components/places/tests/unifiedcomplete/test_dedupe_prefix.js similarity index 64% rename from browser/components/urlbar/tests/unit/test_dedupe_prefix.js rename to toolkit/components/places/tests/unifiedcomplete/test_dedupe_prefix.js index 58f223fbc45a..c6dcb106eb0c 100644 --- a/browser/components/urlbar/tests/unit/test_dedupe_prefix.js +++ b/toolkit/components/places/tests/unifiedcomplete/test_dedupe_prefix.js @@ -31,23 +31,22 @@ add_task(async function dedupe_prefix() { }, ]); - // We should get https://www. as the heuristic result but https:// in the + // We should get https://www. as the heuristic result and https:// in the // results since the latter's prefix is a higher priority. - let context = createContext("example.com/foo/", { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ + search: "example.com/foo/", autofilled: "example.com/foo/", completed: "https://www.example.com/foo/", matches: [ - makeVisitResult(context, { - uri: "https://www.example.com/foo/", - title: "https://www.example.com/foo/", - heuristic: true, - }), - makeVisitResult(context, { - uri: "https://example.com/foo/", - title: "Example Page", - }), + { + value: "example.com/foo/", + comment: "https://www.example.com/foo/", + style: ["autofill", "heuristic"], + }, + { + value: "https://example.com/foo/", + comment: "Example Page", + }, ], }); @@ -63,21 +62,20 @@ add_task(async function dedupe_prefix() { ]); } - context = createContext("example.com/foo/", { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ + search: "example.com/foo/", autofilled: "example.com/foo/", completed: "http://www.example.com/foo/", matches: [ - makeVisitResult(context, { - uri: "http://www.example.com/foo/", - title: "www.example.com/foo/", - heuristic: true, - }), - makeVisitResult(context, { - uri: "https://example.com/foo/", - title: "Example Page", - }), + { + value: "example.com/foo/", + comment: "www.example.com/foo/", + style: ["autofill", "heuristic"], + }, + { + value: "https://example.com/foo/", + comment: "Example Page", + }, ], }); @@ -94,23 +92,22 @@ add_task(async function dedupe_prefix() { ]); } - context = createContext("example.com/foo/", { isPrivate: false }); - await check_results({ - context, + await check_autocomplete({ + search: "example.com/foo/", autofilled: "example.com/foo/", completed: "https://example.com/foo/", matches: [ - makeVisitResult(context, { - uri: "https://example.com/foo/", - title: "https://example.com/foo/", - heuristic: true, - }), - makeVisitResult(context, { - uri: "https://www.example.com/foo/", - title: "Example Page", - }), + { + value: "example.com/foo/", + comment: "https://example.com/foo/", + style: ["autofill", "heuristic"], + }, + { + value: "https://www.example.com/foo/", + comment: "Example Page", + }, ], }); - await cleanupPlaces(); + await cleanup(); }); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_dupe_urls.js b/toolkit/components/places/tests/unifiedcomplete/test_dupe_urls.js new file mode 100644 index 000000000000..c8324dc597b9 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_dupe_urls.js @@ -0,0 +1,51 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +// Ensure inline autocomplete doesn't return zero frecency pages. + +add_task(async function test_dupe_urls() { + info("Searching for urls with dupes should only show one"); + await PlacesTestUtils.addVisits( + { + uri: NetUtil.newURI("http://mozilla.org/"), + }, + { + uri: NetUtil.newURI("http://mozilla.org/?"), + } + ); + await check_autocomplete({ + search: "moz", + autofilled: "mozilla.org/", + completed: "http://mozilla.org/", + matches: [ + { + value: "mozilla.org/", + comment: "mozilla.org", + style: ["autofill", "heuristic"], + }, + ], + }); +}); + +add_task(async function test_dupe_secure_urls() { + await PlacesTestUtils.addVisits( + { + uri: NetUtil.newURI("https://example.org/"), + }, + { + uri: NetUtil.newURI("https://example.org/?"), + } + ); + await check_autocomplete({ + search: "exam", + autofilled: "example.org/", + completed: "https://example.org/", + matches: [ + { + value: "example.org/", + comment: "https://example.org", + style: ["autofill", "heuristic"], + }, + ], + }); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_encoded_urls.js b/toolkit/components/places/tests/unifiedcomplete/test_encoded_urls.js new file mode 100644 index 000000000000..45b2bf62ea1f --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_encoded_urls.js @@ -0,0 +1,87 @@ +add_task(async function test_encoded() { + info("Searching for over encoded url should not break it"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("https://www.mozilla.com/search/top/?q=%25%32%35"), + title: "https://www.mozilla.com/search/top/?q=%25%32%35", + transition: TRANSITION_TYPED, + }); + await check_autocomplete({ + search: "https://www.mozilla.com/search/top/?q=%25%32%35", + matches: [ + { + uri: NetUtil.newURI("https://www.mozilla.com/search/top/?q=%25%32%35"), + title: "https://www.mozilla.com/search/top/?q=%25%32%35", + style: ["autofill", "heuristic"], + }, + ], + autofilled: "https://www.mozilla.com/search/top/?q=%25%32%35", + completed: "https://www.mozilla.com/search/top/?q=%25%32%35", + }); + await cleanup(); +}); + +add_task(async function test_encoded_trimmed() { + info("Searching for over encoded url should not break it"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("https://www.mozilla.com/search/top/?q=%25%32%35"), + title: "https://www.mozilla.com/search/top/?q=%25%32%35", + transition: TRANSITION_TYPED, + }); + await check_autocomplete({ + search: "mozilla.com/search/top/?q=%25%32%35", + matches: [ + { + value: "mozilla.com/search/top/?q=%25%32%35", + comment: "https://www.mozilla.com/search/top/?q=%25%32%35", + style: ["autofill", "heuristic"], + }, + ], + autofilled: "mozilla.com/search/top/?q=%25%32%35", + completed: "https://www.mozilla.com/search/top/?q=%25%32%35", + }); + await cleanup(); +}); + +add_task(async function test_encoded_partial() { + info("Searching for over encoded url should not break it"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("https://www.mozilla.com/search/top/?q=%25%32%35"), + title: "https://www.mozilla.com/search/top/?q=%25%32%35", + transition: TRANSITION_TYPED, + }); + await check_autocomplete({ + search: "https://www.mozilla.com/search/top/?q=%25", + matches: [ + { + uri: NetUtil.newURI("https://www.mozilla.com/search/top/?q=%25%32%35"), + title: "https://www.mozilla.com/search/top/?q=%25%32%35", + style: ["autofill", "heuristic"], + }, + ], + autofilled: "https://www.mozilla.com/search/top/?q=%25%32%35", + completed: "https://www.mozilla.com/search/top/?q=%25%32%35", + }); + await cleanup(); +}); + +add_task(async function test_encoded_path() { + info("Searching for over encoded url should not break it"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("https://www.mozilla.com/%25%32%35/top/"), + title: "https://www.mozilla.com/%25%32%35/top/", + transition: TRANSITION_TYPED, + }); + await check_autocomplete({ + search: "https://www.mozilla.com/%25%32%35/t", + matches: [ + { + uri: NetUtil.newURI("https://www.mozilla.com/%25%32%35/top/"), + title: "https://www.mozilla.com/%25%32%35/top/", + style: ["autofill", "heuristic"], + }, + ], + autofilled: "https://www.mozilla.com/%25%32%35/top/", + completed: "https://www.mozilla.com/%25%32%35/top/", + }); + await cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_keywords.js b/toolkit/components/places/tests/unifiedcomplete/test_keywords.js new file mode 100644 index 000000000000..72e92e2e0c14 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_keywords.js @@ -0,0 +1,130 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(async function test_non_keyword() { + info("Searching for non-keyworded entry should autoFill it"); + await PlacesTestUtils.addVisits({ + uri: Services.io.newURI("http://mozilla.org/test/"), + }); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: Services.io.newURI("http://mozilla.org/test/"), + }); + await check_autocomplete({ + search: "moz", + autofilled: "mozilla.org/", + completed: "http://mozilla.org/", + }); + await cleanup(); +}); + +add_task(async function test_keyword() { + info("Searching for keyworded entry should not autoFill it"); + await PlacesTestUtils.addVisits({ + uri: Services.io.newURI("http://mozilla.org/test/"), + }); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: Services.io.newURI("http://mozilla.org/test/"), + keyword: "moz", + }); + await check_autocomplete({ + search: "moz", + autofilled: "moz", + completed: "moz", + }); + await cleanup(); +}); + +add_task(async function test_more_than_keyword() { + info("Searching for more than keyworded entry should autoFill it"); + await PlacesTestUtils.addVisits({ + uri: Services.io.newURI("http://mozilla.org/test/"), + }); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: Services.io.newURI("http://mozilla.org/test/"), + keyword: "moz", + }); + await check_autocomplete({ + search: "mozi", + autofilled: "mozilla.org/", + completed: "http://mozilla.org/", + }); + await cleanup(); +}); + +add_task(async function test_less_than_keyword() { + info("Searching for less than keyworded entry should autoFill it"); + await PlacesTestUtils.addVisits({ + uri: Services.io.newURI("http://mozilla.org/test/"), + }); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: Services.io.newURI("http://mozilla.org/test/"), + keyword: "moz", + }); + await check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "http://mozilla.org/", + }); + await cleanup(); +}); + +add_task(async function test_keyword_casing() { + info("Searching for keyworded entry is case-insensitive"); + await PlacesTestUtils.addVisits({ + uri: Services.io.newURI("http://mozilla.org/test/"), + }); + await PlacesTestUtils.addBookmarkWithDetails({ + uri: Services.io.newURI("http://mozilla.org/test/"), + keyword: "moz", + }); + await check_autocomplete({ + search: "MoZ", + autofilled: "MoZ", + completed: "MoZ", + }); + await cleanup(); +}); + +add_task(async function test_less_then_equal_than_keyword_bug_1124238() { + info("Searching for less than keyworded entry should autoFill it"); + await PlacesTestUtils.addVisits({ + uri: Services.io.newURI("http://mozilla.org/test/"), + transition: TRANSITION_TYPED, + }); + await PlacesTestUtils.addVisits("http://mozilla.com/"); + PlacesTestUtils.addBookmarkWithDetails({ + uri: Services.io.newURI("http://mozilla.com/"), + keyword: "moz", + }); + + let input = await check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "http://mozilla.org/", + }); + + info(input.textValue); + + // Emulate the input of an additional character. As the input matches a + // keyword, the completion should equal the keyword and not the URI as before. + input.textValue = "moz"; + await check_autocomplete({ + input, + search: "moz", + autofilled: "moz", + completed: "moz", + }); + + // Emulate the input of an additional character. The input doesn't match a + // keyword anymore, it should be autofilled. + input.textValue = "moz"; + await check_autocomplete({ + input, + search: "mozi", + autofilled: "mozilla.org/", + completed: "http://mozilla.org/", + }); + + await cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_query_url.js b/toolkit/components/places/tests/unifiedcomplete/test_query_url.js new file mode 100644 index 000000000000..9c56ac1b36ce --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_query_url.js @@ -0,0 +1,66 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(async function test_no_slash() { + info("Searching for host match without slash should match host"); + await PlacesTestUtils.addVisits([ + { uri: "http://file.org/test/" }, + { uri: "file:///c:/test.html" }, + ]); + await check_autocomplete({ + search: "file", + autofilled: "file.org/", + completed: "http://file.org/", + }); + await cleanup(); +}); + +add_task(async function test_w_slash() { + info("Searching match with slash at the end should match url"); + await PlacesTestUtils.addVisits( + { + uri: NetUtil.newURI("http://file.org/test/"), + }, + { + uri: NetUtil.newURI("file:///c:/test.html"), + } + ); + await check_autocomplete({ + search: "file.org/", + autofilled: "file.org/", + completed: "http://file.org/", + }); + await cleanup(); +}); + +add_task(async function test_middle() { + info("Searching match with slash in the middle should match url"); + await PlacesTestUtils.addVisits( + { + uri: NetUtil.newURI("http://file.org/test/"), + }, + { + uri: NetUtil.newURI("file:///c:/test.html"), + } + ); + await check_autocomplete({ + search: "file.org/t", + autofilled: "file.org/test/", + completed: "http://file.org/test/", + }); + await cleanup(); +}); + +add_task(async function test_nonhost() { + info("Searching for non-host match without slash should not match url"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("file:///c:/test.html"), + }); + await check_autocomplete({ + search: "file", + autofilled: "file", + completed: "file", + }); + await cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_search_engine_host.js b/toolkit/components/places/tests/unifiedcomplete/test_search_engine_host.js new file mode 100644 index 000000000000..5cff197505b8 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_search_engine_host.js @@ -0,0 +1,57 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +add_task(async function test_searchEngine_autoFill() { + Services.prefs.setBoolPref("browser.urlbar.autoFill.searchEngines", true); + await Services.search.addEngineWithDetails("MySearchEngine", { + method: "GET", + template: "http://my.search.com/", + }); + let engine = Services.search.getEngineByName("MySearchEngine"); + registerCleanupFunction(async () => Services.search.removeEngine(engine)); + + // Add an uri that matches the search string with high frecency. + let uri = NetUtil.newURI("http://www.example.com/my/"); + let visits = []; + for (let i = 0; i < 100; ++i) { + visits.push({ uri, title: "Terms - SearchEngine Search" }); + } + await PlacesTestUtils.addVisits(visits); + await PlacesTestUtils.addBookmarkWithDetails({ + uri, + title: "Example bookmark", + }); + await PlacesTestUtils.promiseAsyncUpdates(); + ok( + frecencyForUrl(uri) > 10000, + "Added URI should have expected high frecency" + ); + + info( + "Check search domain is autoFilled even if there's an higher frecency match" + ); + await check_autocomplete({ + search: "my", + autofilled: "my.search.com/", + completed: "http://my.search.com/", + }); + + await cleanup(); +}); + +add_task(async function test_searchEngine_noautoFill() { + let engineName = "engine-rel-searchform.xml"; + let engine = await addTestEngine(engineName); + equal(engine.searchForm, "http://example.com/?search"); + + await PlacesTestUtils.addVisits(NetUtil.newURI("http://example.com/my/")); + + info("Check search domain is not autoFilled if it matches a visited domain"); + await check_autocomplete({ + search: "example", + autofilled: "example.com/", + completed: "http://example.com/", + }); + + await cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/test_swap_protocol.js b/toolkit/components/places/tests/unifiedcomplete/test_swap_protocol.js index 92927d6f2b26..de1c7b97f5a6 100644 --- a/toolkit/components/places/tests/unifiedcomplete/test_swap_protocol.js +++ b/toolkit/components/places/tests/unifiedcomplete/test_swap_protocol.js @@ -31,11 +31,11 @@ add_task(async function test_swap_protocol() { { uri: uri8, title: "title" }, ]); - // uri1 and uri2 won't appear since they are lower-ranked duplicates of uri6. + // uri1, uri2, and uri5 won't appear since they are duplicates of uri6, except + // for their prefixes. let allMatches = [ { uri: uri3, title: "title" }, { uri: uri4, title: "title" }, - { uri: uri5, title: "title" }, { uri: uri6, title: "title" }, ]; diff --git a/toolkit/components/places/tests/unifiedcomplete/test_trimming.js b/toolkit/components/places/tests/unifiedcomplete/test_trimming.js new file mode 100644 index 000000000000..2b519b9c4bd6 --- /dev/null +++ b/toolkit/components/places/tests/unifiedcomplete/test_trimming.js @@ -0,0 +1,120 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +add_task(async function test_untrimmed_secure_www() { + info("Searching for untrimmed https://www entry"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("https://www.mozilla.org/test/"), + }); + await check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "https://www.mozilla.org/", + }); + await cleanup(); +}); + +add_task(async function test_untrimmed_secure_www_path() { + info("Searching for untrimmed https://www entry with path"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("https://www.mozilla.org/test/"), + }); + await check_autocomplete({ + search: "mozilla.org/t", + autofilled: "mozilla.org/test/", + completed: "https://www.mozilla.org/test/", + }); + await cleanup(); +}); + +add_task(async function test_untrimmed_secure() { + info("Searching for untrimmed https:// entry"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("https://mozilla.org/test/"), + }); + await check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "https://mozilla.org/", + }); + await cleanup(); +}); + +add_task(async function test_untrimmed_secure_path() { + info("Searching for untrimmed https:// entry with path"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("https://mozilla.org/test/"), + }); + await check_autocomplete({ + search: "mozilla.org/t", + autofilled: "mozilla.org/test/", + completed: "https://mozilla.org/test/", + }); + await cleanup(); +}); + +add_task(async function test_untrimmed_www() { + info("Searching for untrimmed http://www entry"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://www.mozilla.org/test/"), + }); + await check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "http://www.mozilla.org/", + }); + await cleanup(); +}); + +add_task(async function test_untrimmed_www_path() { + info("Searching for untrimmed http://www entry with path"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("http://www.mozilla.org/test/"), + }); + await check_autocomplete({ + search: "mozilla.org/t", + autofilled: "mozilla.org/test/", + completed: "http://www.mozilla.org/test/", + }); + await cleanup(); +}); + +add_task(async function test_untrimmed_ftp() { + info("Searching for untrimmed ftp:// entry"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("ftp://mozilla.org/test/"), + }); + await check_autocomplete({ + search: "mo", + autofilled: "mozilla.org/", + completed: "ftp://mozilla.org/", + }); + await cleanup(); +}); + +add_task(async function test_untrimmed_ftp_path() { + info("Searching for untrimmed ftp:// entry with path"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("ftp://mozilla.org/test/"), + }); + await check_autocomplete({ + search: "mozilla.org/t", + autofilled: "mozilla.org/test/", + completed: "ftp://mozilla.org/test/", + }); + await cleanup(); +}); + +add_task(async function test_escaped_chars() { + info("Searching for URL with characters that are normally escaped"); + await PlacesTestUtils.addVisits({ + uri: NetUtil.newURI("https://www.mozilla.org/啊-test"), + }); + await check_autocomplete({ + search: "https://www.mozilla.org/啊-test", + autofilled: "https://www.mozilla.org/啊-test", + completed: "https://www.mozilla.org/啊-test", + }); + await cleanup(); +}); diff --git a/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini b/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini index cf800156825e..992dccb38a7c 100644 --- a/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini +++ b/toolkit/components/places/tests/unifiedcomplete/xpcshell.ini @@ -6,28 +6,45 @@ support-files = data/engine-rel-searchform.xml data/engine-suggestions.xml !/toolkit/components/places/tests/favicons/favicon-normal16.png + autofill_tasks.js [test_416211.js] [test_416214.js] [test_417798.js] [test_418257.js] [test_422277.js] +[test_autocomplete_functional.js] [test_autocomplete_stopSearch_no_throw.js] +[test_autofill_about_urls.js] +[test_autofill_origins.js] +[test_autofill_search_engine_aliases.js] +[test_autofill_search_engines.js] +[test_autofill_urls.js] +[test_avoid_middle_complete.js] +[test_avoid_stripping_to_empty_tokens.js] +[test_casing.js] +[test_dedupe_prefix.js] [test_do_not_trim.js] [test_download_embed_bookmarks.js] +[test_dupe_urls.js] [test_empty_search.js] +[test_encoded_urls.js] [test_escape_self.js] [test_history_autocomplete_tags.js] [test_ignore_protocol.js] [test_keyword_search.js] [test_keyword_search_actions.js] +[test_keywords.js] [test_multi_word_search.js] [test_preloaded_sites.js] +[test_query_url.js] [test_remote_tab_matches.js] skip-if = !sync [test_search_engine_alias.js] +[test_search_engine_host.js] [test_search_engine_restyle.js] [test_special_search.js] [test_swap_protocol.js] [test_tab_matches.js] +[test_trimming.js] [test_word_boundary_search.js]