diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index 13ef6d15337..7a39d31c7f1 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -457,8 +457,6 @@ @BINPATH@/components/nsPlacesDBFlush.js @BINPATH@/components/nsPlacesAutoComplete.manifest @BINPATH@/components/nsPlacesAutoComplete.js -@BINPATH@/components/UnifiedComplete.manifest -@BINPATH@/components/UnifiedComplete.js @BINPATH@/components/nsPlacesExpiration.js @BINPATH@/components/PlacesProtocolHandler.js @BINPATH@/components/PlacesCategoriesStarter.js diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 95c88ce6b56..a91f8c1ee8c 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -81,10 +81,6 @@ Components.classes["@mozilla.org/autocomplete/search;1?name=history"] .getService(Components.interfaces.mozIPlacesAutoComplete); - - Components.classes["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"] - .getService(Components.interfaces.mozIPlacesAutoComplete); - document.getAnonymousElementByAttribute(this, "anonid", "tabbox"); @@ -748,10 +744,8 @@ } let autocomplete = this.mTabBrowser._placesAutocomplete; - let unifiedComplete = this.mTabBrowser._unifiedComplete; if (this.mBrowser.registeredOpenURI) { autocomplete.unregisterOpenPage(this.mBrowser.registeredOpenURI); - unifiedComplete.unregisterOpenPage(this.mBrowser.registeredOpenURI); delete this.mBrowser.registeredOpenURI; } // Tabs in private windows aren't registered as "Open" so @@ -760,7 +754,6 @@ (!PrivateBrowsingUtils.isWindowPrivate(window) || PrivateBrowsingUtils.permanentPrivateBrowsing)) { autocomplete.registerOpenPage(aLocation); - unifiedComplete.registerOpenPage(aLocation); this.mBrowser.registeredOpenURI = aLocation; } } @@ -1976,7 +1969,6 @@ if (browser.registeredOpenURI && !aTabWillBeMoved) { this._placesAutocomplete.unregisterOpenPage(browser.registeredOpenURI); - this._unifiedComplete.unregisterOpenPage(browser.registeredOpenURI); delete browser.registeredOpenURI; } @@ -2303,7 +2295,6 @@ // If the current URI is registered as open remove it from the list. if (aOurBrowser.registeredOpenURI) { this._placesAutocomplete.unregisterOpenPage(aOurBrowser.registeredOpenURI); - this._unifiedComplete.unregisterOpenPage(aOurBrowser.registeredOpenURI); delete aOurBrowser.registeredOpenURI; } @@ -3113,7 +3104,6 @@ let browser = this.getBrowserAtIndex(i); if (browser.registeredOpenURI) { this._placesAutocomplete.unregisterOpenPage(browser.registeredOpenURI); - this._unifiedComplete.unregisterOpenPage(aOurBrowser.registeredOpenURI); delete browser.registeredOpenURI; } browser.webProgress.removeProgressListener(this.mTabFilters[i]); diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml index 1208022789d..1468efb592c 100644 --- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -68,12 +68,6 @@ this.inputField.addEventListener("overflow", this, false); this.inputField.addEventListener("underflow", this, false); - try { - if (this._prefs.getBoolPref("unifiedcomplete")) { - this.setAttribute("autocompletesearch", "unifiedcomplete"); - } - } catch (ex) {} - const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; var textBox = document.getAnonymousElementByAttribute(this, "anonid", "textbox-input-box"); @@ -605,14 +599,6 @@ case "trimURLs": this._mayTrimURLs = this._prefs.getBoolPref(aData); break; - case "unifiedcomplete": - let useUnifiedComplete = false; - try { - useUnifiedComplete = this._prefs.getBoolPref(aData); - } catch (ex) {} - this.setAttribute("autocompletesearch", - useUnifiedComplete ? "unifiedcomplete" - : "urlinline history"); } } ]]> diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index 16dca339f9a..292e9e9b429 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -430,8 +430,6 @@ @BINPATH@/components/nsTaggingService.js @BINPATH@/components/nsPlacesAutoComplete.manifest @BINPATH@/components/nsPlacesAutoComplete.js -@BINPATH@/components/UnifiedComplete.manifest -@BINPATH@/components/UnifiedComplete.js @BINPATH@/components/nsPlacesExpiration.js @BINPATH@/browser/components/PlacesProtocolHandler.js @BINPATH@/components/PlacesCategoriesStarter.js diff --git a/toolkit/components/places/PriorityUrlProvider.jsm b/toolkit/components/places/PriorityUrlProvider.jsm index dad4c179920..2befbf2f86d 100644 --- a/toolkit/components/places/PriorityUrlProvider.jsm +++ b/toolkit/components/places/PriorityUrlProvider.jsm @@ -126,7 +126,7 @@ this.PriorityUrlProvider = Object.freeze({ matches.delete(token); }, - getMatch: function (searchToken) { + getMatchingSpec: function (searchToken) { return Task.spawn(function* () { yield promiseInitialized(); for (let [token, match] of matches.entries()) { diff --git a/toolkit/components/places/UnifiedComplete.js b/toolkit/components/places/UnifiedComplete.js deleted file mode 100644 index 1c1fd4e1281..00000000000 --- a/toolkit/components/places/UnifiedComplete.js +++ /dev/null @@ -1,1236 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: sw=2 ts=2 sts=2 expandtab - * 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"; - -//////////////////////////////////////////////////////////////////////////////// -//// Constants - -const Cc = Components.classes; -const Ci = Components.interfaces; -const Cr = Components.results; -const Cu = Components.utils; - -const TOPIC_SHUTDOWN = "places-shutdown"; -const TOPIC_PREFCHANGED = "nsPref:changed"; - -const DEFAULT_BEHAVIOR = 0; - -const PREF_BRANCH = "browser.urlbar"; - -// Prefs are defined as [pref name, default value]. -const PREF_ENABLED = [ "autocomplete.enabled", true ]; -const PREF_AUTOFILL = [ "autoFill", true ]; -const PREF_AUTOFILL_TYPED = [ "autoFill.typed", true ]; -const PREF_AUTOFILL_PRIORITY = [ "autoFill.priority", true ]; -const PREF_DELAY = [ "delay", 50 ]; -const PREF_BEHAVIOR = [ "matchBehavior", MATCH_BOUNDARY_ANYWHERE ]; -const PREF_DEFAULT_BEHAVIOR = [ "default.behavior", DEFAULT_BEHAVIOR ]; -const PREF_EMPTY_BEHAVIOR = [ "default.behavior.emptyRestriction", - Ci.mozIPlacesAutoComplete.BEHAVIOR_HISTORY | - Ci.mozIPlacesAutoComplete.BEHAVIOR_TYPED ]; -const PREF_FILTER_JS = [ "filter.javascript", true ]; -const PREF_MAXRESULTS = [ "maxRichResults", 25 ]; -const PREF_RESTRICT_HISTORY = [ "restrict.history", "^" ]; -const PREF_RESTRICT_BOOKMARKS = [ "restrict.bookmark", "*" ]; -const PREF_RESTRICT_TYPED = [ "restrict.typed", "~" ]; -const PREF_RESTRICT_TAG = [ "restrict.tag", "+" ]; -const PREF_RESTRICT_SWITCHTAB = [ "restrict.openpage", "%" ]; -const PREF_MATCH_TITLE = [ "match.title", "#" ]; -const PREF_MATCH_URL = [ "match.url", "@" ]; - -// Match type constants. -// These indicate what type of search function we should be using. -const MATCH_ANYWHERE = Ci.mozIPlacesAutoComplete.MATCH_ANYWHERE; -const MATCH_BOUNDARY_ANYWHERE = Ci.mozIPlacesAutoComplete.MATCH_BOUNDARY_ANYWHERE; -const MATCH_BOUNDARY = Ci.mozIPlacesAutoComplete.MATCH_BOUNDARY; -const MATCH_BEGINNING = Ci.mozIPlacesAutoComplete.MATCH_BEGINNING; -const MATCH_BEGINNING_CASE_SENSITIVE = Ci.mozIPlacesAutoComplete.MATCH_BEGINNING_CASE_SENSITIVE; - -// AutoComplete query type constants. -// Describes the various types of queries that we can process rows for. -const QUERYTYPE_KEYWORD = 0; -const QUERYTYPE_FILTERED = 1; -const QUERYTYPE_AUTOFILL_HOST = 2; -const QUERYTYPE_AUTOFILL_URL = 3; - -// This separator is used as an RTL-friendly way to split the title and tags. -// It can also be used by an nsIAutoCompleteResult consumer to re-split the -// "comment" back into the title and the tag. -const TITLE_TAGS_SEPARATOR = " \u2013 "; - -// Telemetry probes. -const TELEMETRY_1ST_RESULT = "PLACES_AUTOCOMPLETE_1ST_RESULT_TIME_MS"; - -// The default frecency value used when inserting priority results. -const FRECENCY_PRIORITY_DEFAULT = 1000; - -// Sqlite result row index constants. -const QUERYINDEX_QUERYTYPE = 0; -const QUERYINDEX_URL = 1; -const QUERYINDEX_TITLE = 2; -const QUERYINDEX_ICONURL = 3; -const QUERYINDEX_BOOKMARKED = 4; -const QUERYINDEX_BOOKMARKTITLE = 5; -const QUERYINDEX_TAGS = 6; -const QUERYINDEX_VISITCOUNT = 7; -const QUERYINDEX_TYPED = 8; -const QUERYINDEX_PLACEID = 9; -const QUERYINDEX_SWITCHTAB = 10; -const QUERYINDEX_FRECENCY = 11; - -// This SQL query fragment provides the following: -// - whether the entry is bookmarked (QUERYINDEX_BOOKMARKED) -// - the bookmark title, if it is a bookmark (QUERYINDEX_BOOKMARKTITLE) -// - the tags associated with a bookmarked entry (QUERYINDEX_TAGS) -const SQL_BOOKMARK_TAGS_FRAGMENT = sql( - "EXISTS(SELECT 1 FROM moz_bookmarks WHERE fk = h.id) AS bookmarked,", - "( SELECT title FROM moz_bookmarks WHERE fk = h.id AND title NOTNULL", - "ORDER BY lastModified DESC LIMIT 1", - ") AS btitle,", - "( SELECT GROUP_CONCAT(t.title, ',')", - "FROM moz_bookmarks b", - "JOIN moz_bookmarks t ON t.id = +b.parent AND t.parent = :parent", - "WHERE b.fk = h.id", - ") AS tags"); - -// TODO bug 412736: in case of a frecency tie, we might break it with h.typed -// and h.visit_count. That is slower though, so not doing it yet... -const SQL_DEFAULT_QUERY = sql( - "SELECT :query_type, h.url, h.title, f.url,", SQL_BOOKMARK_TAGS_FRAGMENT, ",", - "h.visit_count, h.typed, h.id, t.open_count, h.frecency", - "FROM moz_places h", - "LEFT JOIN moz_favicons f ON f.id = h.favicon_id", - "LEFT JOIN moz_openpages_temp t ON t.url = h.url", - "WHERE h.frecency <> 0", - "AND AUTOCOMPLETE_MATCH(:searchString, h.url,", - "IFNULL(btitle, h.title), tags,", - "h.visit_count, h.typed,", - "bookmarked, t.open_count,", - ":matchBehavior, :searchBehavior)", - "/*CONDITIONS*/", - "ORDER BY h.frecency DESC, h.id DESC", - "LIMIT :maxResults"); - -// Enforce ignoring the visit_count index, since the frecency one is much -// faster in this case. ANALYZE helps the query planner to figure out the -// faster path, but it may not have up-to-date information yet. -const SQL_HISTORY_QUERY = SQL_DEFAULT_QUERY.replace("/*CONDITIONS*/", - "AND +h.visit_count > 0", "g"); - -const SQL_BOOKMARK_QUERY = SQL_DEFAULT_QUERY.replace("/*CONDITIONS*/", - "AND bookmarked", "g"); - -const SQL_TAGS_QUERY = SQL_DEFAULT_QUERY.replace("/*CONDITIONS*/", - "AND tags NOTNULL", "g"); - -const SQL_TYPED_QUERY = SQL_DEFAULT_QUERY.replace("/*CONDITIONS*/", - "AND h.typed = 1", "g"); - -const SQL_SWITCHTAB_QUERY = sql( - "SELECT :query_type, t.url, t.url, NULL, NULL, NULL, NULL, NULL, NULL, NULL,", - "t.open_count, NULL", - "FROM moz_openpages_temp t", - "LEFT JOIN moz_places h ON h.url = t.url", - "WHERE h.id IS NULL", - "AND AUTOCOMPLETE_MATCH(:searchString, t.url, t.url, NULL,", - "NULL, NULL, NULL, t.open_count,", - ":matchBehavior, :searchBehavior)", - "ORDER BY t.ROWID DESC", - "LIMIT :maxResults"); - -const SQL_ADAPTIVE_QUERY = sql( - "/* do not warn (bug 487789) */", - "SELECT :query_type, h.url, h.title, f.url,", SQL_BOOKMARK_TAGS_FRAGMENT, ",", - "h.visit_count, h.typed, h.id, t.open_count, h.frecency", - "FROM (", - "SELECT ROUND(MAX(use_count) * (1 + (input = :search_string)), 1) AS rank,", - "place_id", - "FROM moz_inputhistory", - "WHERE input BETWEEN :search_string AND :search_string || X'FFFF'", - "GROUP BY place_id", - ") AS i", - "JOIN moz_places h ON h.id = i.place_id", - "LEFT JOIN moz_favicons f ON f.id = h.favicon_id", - "LEFT JOIN moz_openpages_temp t ON t.url = h.url", - "WHERE AUTOCOMPLETE_MATCH(NULL, h.url,", - "IFNULL(btitle, h.title), tags,", - "h.visit_count, h.typed, bookmarked,", - "t.open_count,", - ":matchBehavior, :searchBehavior)", - "ORDER BY rank DESC, h.frecency DESC"); - -const SQL_KEYWORD_QUERY = sql( - "/* do not warn (bug 487787) */", - "SELECT :query_type,", - "(SELECT REPLACE(url, '%s', :query_string) FROM moz_places WHERE id = b.fk)", - "AS search_url, h.title,", - "IFNULL(f.url, (SELECT f.url", - "FROM moz_places", - "JOIN moz_favicons f ON f.id = favicon_id", - "WHERE rev_host = (SELECT rev_host FROM moz_places WHERE id = b.fk)", - "ORDER BY frecency DESC", - "LIMIT 1)", - "),", - "1, b.title, NULL, h.visit_count, h.typed, IFNULL(h.id, b.fk),", - "t.open_count, h.frecency", - "FROM moz_keywords k", - "JOIN moz_bookmarks b ON b.keyword_id = k.id", - "LEFT JOIN moz_places h ON h.url = search_url", - "LEFT JOIN moz_favicons f ON f.id = h.favicon_id", - "LEFT JOIN moz_openpages_temp t ON t.url = search_url", - "WHERE LOWER(k.keyword) = LOWER(:keyword)", - "ORDER BY h.frecency DESC"); - -const SQL_HOST_QUERY = sql( - "/* do not warn (bug NA): not worth to index on (typed, frecency) */", - "SELECT :query_type, host || '/', prefix || host || '/',", - "NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, frecency", - "FROM moz_hosts", - "WHERE host BETWEEN :searchString AND :searchString || X'FFFF'", - "AND frecency <> 0", - "/*CONDITIONS*/", - "ORDER BY frecency DESC", - "LIMIT 1"); - -const SQL_TYPED_HOST_QUERY = SQL_HOST_QUERY.replace("/*CONDITIONS*/", - "AND typed = 1"); -const SQL_URL_QUERY = sql( - "/* do not warn (bug no): cannot use an index */", - "SELECT :query_type, h.url,", - "NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, h.frecency", - "FROM moz_places h", - "WHERE h.frecency <> 0", - "/*CONDITIONS*/", - "AND AUTOCOMPLETE_MATCH(:searchString, h.url,", - "h.title, '',", - "h.visit_count, h.typed, 0, 0,", - ":matchBehavior, :searchBehavior)", - "ORDER BY h.frecency DESC, h.id DESC", - "LIMIT 1"); - -const SQL_TYPED_URL_QUERY = SQL_URL_QUERY.replace("/*CONDITIONS*/", - "AND typed = 1"); - -//////////////////////////////////////////////////////////////////////////////// -//// Getters - -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); - -XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils", - "resource://gre/modules/PlacesUtils.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch", - "resource://gre/modules/TelemetryStopwatch.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "NetUtil", - "resource://gre/modules/NetUtil.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Preferences", - "resource://gre/modules/Preferences.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Sqlite", - "resource://gre/modules/Sqlite.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "OS", - "resource://gre/modules/osfile.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Promise", - "resource://gre/modules/Promise.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "Task", - "resource://gre/modules/Task.jsm"); -XPCOMUtils.defineLazyModuleGetter(this, "PriorityUrlProvider", - "resource://gre/modules/PriorityUrlProvider.jsm"); - -XPCOMUtils.defineLazyServiceGetter(this, "textURIService", - "@mozilla.org/intl/texttosuburi;1", - "nsITextToSubURI"); - -/** - * Storage object for switch-to-tab entries. - * This takes care of caching and registering open pages, that will be reused - * by switch-to-tab queries. It has an internal cache, so that the Sqlite - * store is lazy initialized only on first use. - * It has a simple API: - * initDatabase(conn): initializes the temporary Sqlite entities to store data - * add(uri): adds a given nsIURI to the store - * delete(uri): removes a given nsIURI from the store - * shutdown(): stops storing data to Sqlite - */ -XPCOMUtils.defineLazyGetter(this, "SwitchToTabStorage", () => Object.seal({ - _conn: null, - // Temporary queue used while the database connection is not available. - _queue: new Set(), - initDatabase: Task.async(function* (conn) { - // To reduce IO use an in-memory table for switch-to-tab tracking. - // Note: this should be kept up-to-date with the definition in - // nsPlacesTables.h. - yield conn.execute(sql( - "CREATE TEMP TABLE moz_openpages_temp (", - "url TEXT PRIMARY KEY,", - "open_count INTEGER", - ")")); - - // Note: this should be kept up-to-date with the definition in - // nsPlacesTriggers.h. - yield conn.execute(sql( - "CREATE TEMPORARY TRIGGER moz_openpages_temp_afterupdate_trigger", - "AFTER UPDATE OF open_count ON moz_openpages_temp FOR EACH ROW", - "WHEN NEW.open_count = 0", - "BEGIN", - "DELETE FROM moz_openpages_temp", - "WHERE url = NEW.url;", - "END")); - - this._conn = conn; - - // Populate the table with the current cache contents... - this._queue.forEach(this.add, this); - // ...then clear it to avoid double additions. - this._queue.clear(); - }), - - add: function (uri) { - if (!this._conn) { - this._queue.add(uri); - return; - } - this._conn.executeCached(sql( - "INSERT OR REPLACE INTO moz_openpages_temp (url, open_count)", - "VALUES ( :url, IFNULL( (SELECT open_count + 1", - "FROM moz_openpages_temp", - "WHERE url = :url),", - "1", - ")", - ")" - ), { url: uri.spec }); - }, - - delete: function (uri) { - if (!this._conn) { - this._queue.delete(uri); - return; - } - this._conn.executeCached(sql( - "UPDATE moz_openpages_temp", - "SET open_count = open_count - 1", - "WHERE url = :url" - ), { url: uri.spec }); - }, - - shutdown: function () { - this._conn = null; - this._queue.clear(); - } -})); - -/** - * This helper keeps track of preferences and keeps their values up-to-date. - */ -XPCOMUtils.defineLazyGetter(this, "Prefs", () => { - let prefs = new Preferences(PREF_BRANCH); - - function loadPrefs() { - store.enabled = prefs.get(...PREF_ENABLED); - store.autofill = prefs.get(...PREF_AUTOFILL); - store.autofillTyped = prefs.get(...PREF_AUTOFILL_TYPED); - store.autofillPriority = prefs.get(...PREF_AUTOFILL_PRIORITY); - store.delay = prefs.get(...PREF_DELAY); - store.matchBehavior = prefs.get(...PREF_BEHAVIOR); - store.filterJavaScript = prefs.get(...PREF_FILTER_JS); - store.maxRichResults = prefs.get(...PREF_MAXRESULTS); - store.restrictHistoryToken = prefs.get(...PREF_RESTRICT_HISTORY); - store.restrictBookmarkToken = prefs.get(...PREF_RESTRICT_BOOKMARKS); - store.restrictTypedToken = prefs.get(...PREF_RESTRICT_TYPED); - store.restrictTagToken = prefs.get(...PREF_RESTRICT_TAG); - store.restrictOpenPageToken = prefs.get(...PREF_RESTRICT_SWITCHTAB); - store.matchTitleToken = prefs.get(...PREF_MATCH_TITLE); - store.matchURLToken = prefs.get(...PREF_MATCH_URL); - store.defaultBehavior = prefs.get(...PREF_DEFAULT_BEHAVIOR); - // Further restrictions to apply for "empty searches" (i.e. searches for ""). - store.emptySearchDefaultBehavior = store.defaultBehavior | - prefs.get(...PREF_EMPTY_BEHAVIOR); - - // Validate matchBehavior; default to MATCH_BOUNDARY_ANYWHERE. - if (store.matchBehavior != MATCH_ANYWHERE && - store.matchBehavior != MATCH_BOUNDARY && - store.matchBehavior != MATCH_BEGINNING) { - store.matchBehavior = MATCH_BOUNDARY_ANYWHERE; - } - - store.tokenToBehaviorMap = new Map([ - [ store.restrictHistoryToken, "history" ], - [ store.restrictBookmarkToken, "bookmark" ], - [ store.restrictTagToken, "tag" ], - [ store.restrictOpenPageToken, "openpage" ], - [ store.matchTitleToken, "title" ], - [ store.matchURLToken, "url" ], - [ store.restrictTypedToken, "typed" ] - ]); - } - - let store = { - observe: function (subject, topic, data) { - loadPrefs(); - }, - QueryInterface: XPCOMUtils.generateQI([ Ci.nsIObserver ]) - }; - loadPrefs(); - prefs.observe("", store); - - return Object.seal(store); -}); - -//////////////////////////////////////////////////////////////////////////////// -//// Helper functions - -/** - * Joins multiple sql tokens into a single sql query. - */ -function sql(...parts) parts.join(" "); - -/** - * Used to unescape encoded URI strings and drop information that we do not - * care about. - * - * @param spec - * The text to unescape and modify. - * @return the modified spec. - */ -function fixupSearchText(spec) - textURIService.unEscapeURIForUI("UTF-8", stripPrefix(spec)); - -/** - * Generates the tokens used in searching from a given string. - * - * @param searchString - * The string to generate tokens from. - * @return an array of tokens. - * @note Calling split on an empty string will return an array containing one - * empty string. We don't want that, as it'll break our logic, so return - * an empty array then. - */ -function getUnfilteredSearchTokens(searchString) - searchString.length ? searchString.split(" ") : []; - -/** - * Strip prefixes from the URI that we don't care about for searching. - * - * @param spec - * The text to modify. - * @return the modified spec. - */ -function stripPrefix(spec) -{ - ["http://", "https://", "ftp://"].some(scheme => { - if (spec.startsWith(scheme)) { - spec = spec.slice(scheme.length); - return true; - } - return false; - }); - - if (spec.startsWith("www.")) { - spec = spec.slice(4); - } - return spec; -} - -//////////////////////////////////////////////////////////////////////////////// -//// Search Class -//// Manages a single instance of an autocomplete search. - -function Search(searchString, searchParam, autocompleteListener, - resultListener, autocompleteSearch) { - // We want to store the original string with no leading or trailing - // whitespace for case sensitive searches. - this._originalSearchString = searchString.trim(); - this._searchString = fixupSearchText(this._originalSearchString.toLowerCase()); - this._searchTokens = - this.filterTokens(getUnfilteredSearchTokens(this._searchString)); - // The protocol and the host are lowercased by nsIURI, so it's fine to - // lowercase the typed prefix, to add it back to the results later. - this._strippedPrefix = this._originalSearchString.slice( - 0, this._originalSearchString.length - this._searchString.length - ).toLowerCase(); - // The URIs in the database are fixed-up, so we can match on a lowercased - // host, but the path must be matched in a case sensitive way. - let pathIndex = - this._originalSearchString.indexOf("/", this._strippedPrefix.length); - this._autofillUrlSearchString = fixupSearchText( - this._originalSearchString.slice(0, pathIndex).toLowerCase() + - this._originalSearchString.slice(pathIndex) - ); - - this._enableActions = searchParam.split(" ").indexOf("enable-actions") != -1; - - this._listener = autocompleteListener; - this._autocompleteSearch = autocompleteSearch; - - this._matchBehavior = Prefs.matchBehavior; - // Set the default behavior for this search. - this._behavior = this._searchString ? Prefs.defaultBehavior - : Prefs.emptySearchDefaultBehavior; - // Create a new result to add eventual matches. Note we need a result - // regardless having matches. - let result = Cc["@mozilla.org/autocomplete/simple-result;1"] - .createInstance(Ci.nsIAutoCompleteSimpleResult); - result.setSearchString(searchString); - result.setListener(resultListener); - // Will be set later, if needed. - result.setDefaultIndex(-1); - this._result = result; - - // These are used to avoid adding duplicate entries to the results. - this._usedURLs = new Set(); - this._usedPlaceIds = new Set(); -} - -Search.prototype = { - /** - * Enables the desired AutoComplete behavior. - * - * @param type - * The behavior type to set. - */ - setBehavior: function (type) { - this._behavior |= - Ci.mozIPlacesAutoComplete["BEHAVIOR_" + type.toUpperCase()]; - }, - - /** - * Determines if the specified AutoComplete behavior is set. - * - * @param aType - * The behavior type to test for. - * @return true if the behavior is set, false otherwise. - */ - hasBehavior: function (type) { - return this._behavior & - Ci.mozIPlacesAutoComplete["BEHAVIOR_" + type.toUpperCase()]; - }, - - /** - * Used to delay the most complex queries, to save IO while the user is - * typing. - */ - _sleepDeferred: null, - _sleep: function (aTimeMs) { - // Reuse a single instance to try shaving off some usless work before - // the first query. - if (!this._sleepTimer) - this._sleepTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - this._sleepDeferred = Promise.defer(); - this._sleepTimer.initWithCallback(() => this._sleepDeferred.resolve(), - aTimeMs, Ci.nsITimer.TYPE_ONE_SHOT); - return this._sleepDeferred.promise; - }, - - /** - * Given an array of tokens, this function determines which query should be - * ran. It also removes any special search tokens. - * - * @param tokens - * An array of search tokens. - * @return the filtered list of tokens to search with. - */ - filterTokens: function (tokens) { - // Set the proper behavior while filtering tokens. - for (let i = tokens.length - 1; i >= 0; i--) { - let behavior = Prefs.tokenToBehaviorMap.get(tokens[i]); - // Don't remove the token if it didn't match, or if it's an action but - // actions are not enabled. - if (behavior && (behavior != "openpage" || this._enableActions)) { - this.setBehavior(behavior); - tokens.splice(i, 1); - } - } - - // Set the right JavaScript behavior based on our preference. Note that the - // preference is whether or not we should filter JavaScript, and the - // behavior is if we should search it or not. - if (!Prefs.filterJavaScript) { - this.setBehavior("javascript"); - } - - return tokens; - }, - - /** - * Used to cancel this search, will stop providing results. - */ - cancel: function () { - if (this._sleepTimer) - this._sleepTimer.cancel(); - if (this._sleepDeferred) { - this._sleepDeferred.resolve(); - this._sleepDeferred = null; - } - delete this._pendingQuery; - }, - - /** - * Whether this search is running. - */ - get pending() !!this._pendingQuery, - - /** - * Execute the search and populate results. - * @param conn - * The Sqlite connection. - */ - execute: Task.async(function* (conn) { - this._pendingQuery = true; - TelemetryStopwatch.start(TELEMETRY_1ST_RESULT); - - // For any given search, we run many queries: - // 1) priority domains - // 2) inline completion - // 3) keywords (this._keywordQuery) - // 4) adaptive learning (this._adaptiveQuery) - // 5) open pages not supported by history (this._switchToTabQuery) - // 6) query based on match behavior - // - // (3) only gets ran if we get any filtered tokens, since if there are no - // tokens, there is nothing to match. - - // Get the final query, based on the tokens found in the search string. - let queries = [ this._adaptiveQuery, - this._switchToTabQuery, - this._searchQuery ]; - - if (this._searchTokens.length == 1) { - yield this._matchPriorityUrl(); - } else if (this._searchTokens.length > 1) { - queries.unshift(this._keywordQuery); - } - - if (this._shouldAutofill) { - // Hosts have no "/" in them. - let lastSlashIndex = this._searchString.lastIndexOf("/"); - // Search only URLs if there's a slash in the search string... - if (lastSlashIndex != -1) { - // ...but not if it's exactly at the end of the search string. - if (lastSlashIndex < this._searchString.length - 1) { - queries.unshift(this._urlQuery); - } - } else if (this.pending) { - // The host query is executed immediately, while any other is delayed - // to avoid overloading the connection. - let [ query, params ] = this._hostQuery; - yield conn.executeCached(query, params, this._onResultRow.bind(this)); - } - } - - yield this._sleep(Prefs.delay); - if (!this.pending) - return; - - for (let [query, params] of queries) { - yield conn.executeCached(query, params, this._onResultRow.bind(this)); - if (!this.pending) - return; - } - - // If we do not have enough results, and our match type is - // MATCH_BOUNDARY_ANYWHERE, search again with MATCH_ANYWHERE to get more - // results. - if (this._matchBehavior == MATCH_BOUNDARY_ANYWHERE && - this._result.matchCount < Prefs.maxRichResults) { - this._matchBehavior = MATCH_ANYWHERE; - for (let [query, params] of [ this._adaptiveQuery, - this._searchQuery ]) { - yield conn.executeCached(query, params, this._onResultRow); - if (!this.pending) - return; - } - } - - // If we didn't find enough matches and we have some frecency-driven - // matches, add them. - if (this._frecencyMatches) { - this._frecencyMatches.forEach(this._addMatch, this); - } - }), - - _matchPriorityUrl: function* () { - if (!Prefs.autofillPriority) - return; - let priorityMatch = yield PriorityUrlProvider.getMatch(this._searchString); - if (priorityMatch) { - this._result.setDefaultIndex(0); - this._addFrecencyMatch({ - value: priorityMatch.token, - comment: priorityMatch.title, - icon: priorityMatch.iconUrl, - style: "priority-" + priorityMatch.reason, - finalCompleteValue: priorityMatch.url, - frecency: FRECENCY_PRIORITY_DEFAULT - }); - } - }, - - _onResultRow: function (row) { - TelemetryStopwatch.finish(TELEMETRY_1ST_RESULT); - let queryType = row.getResultByIndex(QUERYINDEX_QUERYTYPE); - let match; - switch (queryType) { - case QUERYTYPE_AUTOFILL_HOST: - this._result.setDefaultIndex(0); - match = this._processHostRow(row); - break; - case QUERYTYPE_AUTOFILL_URL: - this._result.setDefaultIndex(0); - match = this._processUrlRow(row); - break; - case QUERYTYPE_FILTERED: - case QUERYTYPE_KEYWORD: - match = this._processRow(row); - break; - } - this._addMatch(match); - }, - - /** - * These matches should be mixed up with other matches, based on frecency. - */ - _addFrecencyMatch: function (match) { - if (!this._frecencyMatches) - this._frecencyMatches = []; - this._frecencyMatches.push(match); - // We keep this array in reverse order, so we can walk it and remove stuff - // from it in one pass. Notice that for frecency reverse order means from - // lower to higher. - this._frecencyMatches.sort((a, b) => a.frecency - b.frecency); - }, - - _addMatch: function (match) { - let notifyResults = false; - - if (this._frecencyMatches) { - for (let i = this._frecencyMatches.length - 1; i >= 0 ; i--) { - if (this._frecencyMatches[i].frecency > match.frecency) { - this._addMatch(this._frecencyMatches.splice(i, 1)[0]); - } - } - } - - // Must check both id and url, cause keywords dinamically modify the url. - if ((!match.placeId || !this._usedPlaceIds.has(match.placeId)) && - !this._usedURLs.has(stripPrefix(match.value))) { - // Add this to our internal tracker to ensure duplicates do not end up in - // the result. - // Not all entries have a place id, thus we fallback to the url for them. - // We cannot use only the url since keywords entries are modified to - // include the search string, and would be returned multiple times. Ids - // are faster too. - if (match.placeId) - this._usedPlaceIds.add(match.placeId); - this._usedURLs.add(stripPrefix(match.value)); - - this._result.appendMatch(match.value, - match.comment, - match.icon || PlacesUtils.favicons.defaultFavicon.spec, - match.style || "favicon", - match.finalCompleteValue); - notifyResults = true; - } - - if (this._result.matchCount == Prefs.maxRichResults || !this.pending) { - // We have enough results, so stop running our search. - this.cancel(); - // This tells Sqlite.jsm to stop providing us results and cancel the - // underlying query. - throw StopIteration; - } - - if (notifyResults) { - // Notify about results if we've gotten them. - this.notifyResults(true); - } - }, - - _processHostRow: function (row) { - let match = {}; - let trimmedHost = row.getResultByIndex(QUERYINDEX_URL); - let untrimmedHost = row.getResultByIndex(QUERYINDEX_TITLE); - let frecency = row.getResultByIndex(QUERYINDEX_FRECENCY); - // If the untrimmed value doesn't preserve the user's input just - // ignore it and complete to the found host. - if (untrimmedHost && - !untrimmedHost.toLowerCase().contains(this._originalSearchString.toLowerCase())) { - // THIS CAUSES null TO BE SHOWN AS TITLE. - untrimmedHost = null; - } - - match.value = this._strippedPrefix + trimmedHost; - match.comment = trimmedHost; - match.finalCompleteValue = untrimmedHost; - match.frecency = frecency; - return match; - }, - - _processUrlRow: function (row) { - let match = {}; - let value = row.getResultByIndex(QUERYINDEX_URL); - let url = fixupSearchText(value); - let frecency = row.getResultByIndex(QUERYINDEX_FRECENCY); - - let prefix = value.slice(0, value.length - stripPrefix(value).length); - - // We must complete the URL up to the next separator (which is /, ? or #). - let separatorIndex = url.slice(this._searchString.length) - .search(/[\/\?\#]/); - if (separatorIndex != -1) { - separatorIndex += this._searchString.length; - if (url[separatorIndex] == "/") { - separatorIndex++; // Include the "/" separator - } - url = url.slice(0, separatorIndex); - } - - // If the untrimmed value doesn't preserve the user's input just - // ignore it and complete to the found url. - let untrimmedURL = prefix + url; - if (untrimmedURL && - !untrimmedURL.toLowerCase().contains(this._originalSearchString.toLowerCase())) { - // THIS CAUSES null TO BE SHOWN AS TITLE. - untrimmedURL = null; - } - - match.value = this._strippedPrefix + url; - match.comment = url; - match.finalCompleteValue = untrimmedURL; - match.frecency = frecency; - return match; - }, - - _processRow: function (row) { - let match = {}; - match.placeId = row.getResultByIndex(QUERYINDEX_PLACEID); - let queryType = row.getResultByIndex(QUERYINDEX_QUERYTYPE); - let escapedURL = row.getResultByIndex(QUERYINDEX_URL); - let openPageCount = row.getResultByIndex(QUERYINDEX_SWITCHTAB) || 0; - let historyTitle = row.getResultByIndex(QUERYINDEX_TITLE) || ""; - let iconurl = row.getResultByIndex(QUERYINDEX_ICONURL) || ""; - let bookmarked = row.getResultByIndex(QUERYINDEX_BOOKMARKED); - let bookmarkTitle = bookmarked ? - row.getResultByIndex(QUERYINDEX_BOOKMARKTITLE) : null; - let tags = row.getResultByIndex(QUERYINDEX_TAGS) || ""; - let frecency = row.getResultByIndex(QUERYINDEX_FRECENCY); - - // If actions are enabled and the page is open, add only the switch-to-tab - // result. Otherwise, add the normal result. - let [url, action] = this._enableActions && openPageCount > 0 ? - ["moz-action:switchtab," + escapedURL, "action "] : - [escapedURL, ""]; - - // Always prefer the bookmark title unless it is empty - let title = bookmarkTitle || historyTitle; - - if (queryType == QUERYTYPE_KEYWORD) { - // If we do not have a title, then we must have a keyword, so let the UI - // know it is a keyword. Otherwise, we found an exact page match, so just - // show the page like a regular result. Because the page title is likely - // going to be more specific than the bookmark title (keyword title). - if (!historyTitle) { - match.style = "keyword"; - } - else { - title = historyTitle; - } - } - - // We will always prefer to show tags if we have them. - let showTags = !!tags; - - // However, we'll act as if a page is not bookmarked or tagged if the user - // only wants only history and not bookmarks or tags. - if (this.hasBehavior("history") && - !(this.hasBehavior("bookmark") || this.hasBehavior("tag"))) { - showTags = false; - match.style = "favicon"; - } - - // If we have tags and should show them, we need to add them to the title. - if (showTags) { - title += TITLE_TAGS_SEPARATOR + tags; - } - - // We have to determine the right style to display. Tags show the tag icon, - // bookmarks get the bookmark icon, and keywords get the keyword icon. If - // the result does not fall into any of those, it just gets the favicon. - if (!match.style) { - // It is possible that we already have a style set (from a keyword - // search or because of the user's preferences), so only set it if we - // haven't already done so. - if (showTags) { - match.style = "tag"; - } - else if (bookmarked) { - match.style = "bookmark"; - } - } - - match.value = url; - match.comment = title; - if (iconurl) { - match.icon = PlacesUtils.favicons - .getFaviconLinkForIcon(NetUtil.newURI(iconurl)).spec; - } - match.frecency = frecency; - - return match; - }, - - /** - * Obtains the search query to be used based on the previously set search - * behaviors (accessed by this.hasBehavior). - * - * @return an array consisting of the correctly optimized query to search the - * database with and an object containing the params to bound. - */ - get _searchQuery() { - // We use more optimized queries for restricted searches, so we will always - // return the most restrictive one to the least restrictive one if more than - // one token is found. - // Note: "openpages" behavior is supported by the default query. - // _switchToTabQuery instead returns only pages not supported by - // history and it is always executed. - let query = this.hasBehavior("tag") ? SQL_TAGS_QUERY : - this.hasBehavior("bookmark") ? SQL_BOOKMARK_QUERY : - this.hasBehavior("typed") ? SQL_TYPED_QUERY : - this.hasBehavior("history") ? SQL_HISTORY_QUERY : - SQL_DEFAULT_QUERY; - - return [ - query, - { - parent: PlacesUtils.tagsFolderId, - query_type: QUERYTYPE_FILTERED, - matchBehavior: this._matchBehavior, - searchBehavior: this._behavior, - // We only want to search the tokens that we are left with - not the - // original search string. - searchString: this._searchTokens.join(" "), - // Limit the query to the the maximum number of desired results. - // This way we can avoid doing more work than needed. - maxResults: Prefs.maxRichResults - } - ]; - }, - - /** - * Obtains the query to search for keywords. - * - * @return an array consisting of the correctly optimized query to search the - * database with and an object containing the params to bound. - */ - get _keywordQuery() { - // The keyword is the first word in the search string, with the parameters - // following it. - let searchString = this._originalSearchString; - let queryString = ""; - let queryIndex = searchString.indexOf(" "); - if (queryIndex != -1) { - queryString = searchString.substring(queryIndex + 1); - } - // We need to escape the parameters as if they were the query in a URL - queryString = encodeURIComponent(queryString).replace("%20", "+", "g"); - - // The first word could be a keyword, so that's what we'll search. - let keyword = this._searchTokens[0]; - - return [ - SQL_KEYWORD_QUERY, - { - keyword: keyword, - query_string: queryString, - query_type: QUERYTYPE_KEYWORD - } - ]; - }, - - /** - * Obtains the query to search for switch-to-tab entries. - * - * @return an array consisting of the correctly optimized query to search the - * database with and an object containing the params to bound. - */ - get _switchToTabQuery() [ - SQL_SWITCHTAB_QUERY, - { - query_type: QUERYTYPE_FILTERED, - matchBehavior: this._matchBehavior, - searchBehavior: this._behavior, - // We only want to search the tokens that we are left with - not the - // original search string. - searchString: this._searchTokens.join(" "), - maxResults: Prefs.maxRichResults - } - ], - - /** - * Obtains the query to search for adaptive results. - * - * @return an array consisting of the correctly optimized query to search the - * database with and an object containing the params to bound. - */ - get _adaptiveQuery() [ - SQL_ADAPTIVE_QUERY, - { - parent: PlacesUtils.tagsFolderId, - search_string: this._searchString, - query_type: QUERYTYPE_FILTERED, - matchBehavior: this._matchBehavior, - searchBehavior: this._behavior - } - ], - - /** - * Whether we should try to autoFill. - */ - get _shouldAutofill() { - // First of all, check for the autoFill pref. - if (!Prefs.autofill) - return false; - - // Then, we should not try to autofill if the behavior is not the default. - // TODO (bug 751709): Ideally we should have a more fine-grained behavior - // here, but for now it's enough to just check for default behavior. - if (Prefs.defaultBehavior != DEFAULT_BEHAVIOR) - return false; - - // Don't autoFill if the search term is recognized as a keyword, otherwise - // it will override default keywords behavior. Note that keywords are - // hashed on first use, so while the first query may delay a little bit, - // next ones will just hit the memory hash. - if (this._searchString.length == 0 || - PlacesUtils.bookmarks.getURIForKeyword(this._searchString)) { - 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 (/\s/.test(this._searchString)) { - return false; - } - - return true; - }, - - /** - * Obtains the query to search for autoFill host results. - * - * @return an array consisting of the correctly optimized query to search the - * database with and an object containing the params to bound. - */ - get _hostQuery() [ - Prefs.autofillTyped ? SQL_TYPED_HOST_QUERY : SQL_TYPED_QUERY, - { - query_type: QUERYTYPE_AUTOFILL_HOST, - searchString: this._searchString.toLowerCase() - } - ], - - /** - * 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() [ - Prefs.autofillTyped ? SQL_TYPED_HOST_QUERY : SQL_TYPED_QUERY, - { - query_type: QUERYTYPE_AUTOFILL_URL, - searchString: this._autofillUrlSearchString, - matchBehavior: MATCH_BEGINNING_CASE_SENSITIVE, - searchBehavior: Ci.mozIPlacesAutoComplete.BEHAVIOR_URL - } - ], - - /** - * Notifies the listener about results. - * - * @param searchOngoing - * Indicates whether the search is ongoing. - */ - notifyResults: function (searchOngoing) { - let result = this._result; - let resultCode = result.matchCount ? "RESULT_SUCCESS" : "RESULT_NOMATCH"; - if (searchOngoing) { - resultCode += "_ONGOING"; - } - result.setSearchResult(Ci.nsIAutoCompleteResult[resultCode]); - this._listener.onSearchResult(this._autocompleteSearch, result); - }, -} - -//////////////////////////////////////////////////////////////////////////////// -//// UnifiedComplete class -//// component @mozilla.org/autocomplete/search;1?name=unifiedcomplete - -function UnifiedComplete() { - Services.obs.addObserver(this, TOPIC_SHUTDOWN, true); -} - -UnifiedComplete.prototype = { - ////////////////////////////////////////////////////////////////////////////// - //// nsIObserver - - observe: function (subject, topic, data) { - if (topic === TOPIC_SHUTDOWN) { - this.ensureShutdown(); - } - }, - - ////////////////////////////////////////////////////////////////////////////// - //// Database handling - - /** - * Promise resolved when the database initialization has completed, or null - * if it has never been requested. - */ - _promiseDatabase: null, - - /** - * Gets a Sqlite database handle. - * - * @return {Promise} - * @resolves to the Sqlite database handle (according to Sqlite.jsm). - * @rejects javascript exception. - */ - getDatabaseHandle: function () { - if (Prefs.enabled && !this._promiseDatabase) { - this._promiseDatabase = Task.spawn(function* () { - let conn = yield Sqlite.cloneStorageConnection({ - connection: PlacesUtils.history.DBConnection, - readOnly: true - }); - - // Autocomplete often fallbacks to a table scan due to lack of text - // indices. A larger cache helps reducing IO and improving performance. - // The value used here is larger than the default Storage value defined - // as MAX_CACHE_SIZE_BYTES in storage/src/mozStorageConnection.cpp. - yield conn.execute("PRAGMA cache_size = -6144"); // 6MiB - - yield SwitchToTabStorage.initDatabase(conn); - - return conn; - }.bind(this)).then(null, Cu.reportError); - } - return this._promiseDatabase; - }, - - /** - * Used to stop running queries and close the database handle. - */ - ensureShutdown: function () { - if (this._promiseDatabase) { - Task.spawn(function* () { - let conn = yield this.getDatabaseHandle(); - SwitchToTabStorage.shutdown(); - yield conn.close() - }.bind(this)).then(null, Cu.reportError); - this._promiseDatabase = null; - } - }, - - ////////////////////////////////////////////////////////////////////////////// - //// mozIPlacesAutoComplete - - registerOpenPage: function PAC_registerOpenPage(uri) { - SwitchToTabStorage.add(uri); - }, - - unregisterOpenPage: function PAC_unregisterOpenPage(uri) { - SwitchToTabStorage.delete(uri); - }, - - ////////////////////////////////////////////////////////////////////////////// - //// nsIAutoCompleteSearch - - startSearch: function (searchString, searchParam, previousResult, listener) { - // Stop the search in case the controller has not taken care of it. - if (this._currentSearch) { - this.stopSearch(); - } - - // Note: We don't use previousResult to make sure ordering of results are - // consistent. See bug 412730 for more details. - - this._currentSearch = new Search(searchString, searchParam, listener, - this, this); - - // If we are not enabled, we need to return now. Notice we need an empty - // result regardless, so we still create the Search object. - if (!Prefs.enabled) { - this.finishSearch(true); - return; - } - - let search = this._currentSearch; - this.getDatabaseHandle().then(conn => search.execute(conn)) - .then(() => { - if (search == this._currentSearch) { - this.finishSearch(true); - } - }, Cu.reportError); - }, - - stopSearch: function () { - if (this._currentSearch) { - this._currentSearch.cancel(); - } - this.finishSearch(); - }, - - /** - * Properly cleans up when searching is completed. - * - * @param notify [optional] - * Indicates if we should notify the AutoComplete listener about our - * results or not. - */ - finishSearch: function (notify=false) { - // Notify about results if we are supposed to. - if (notify) { - this._currentSearch.notifyResults(false); - } - - // Clear our state - TelemetryStopwatch.cancel(TELEMETRY_1ST_RESULT); - delete this._currentSearch; - }, - - ////////////////////////////////////////////////////////////////////////////// - //// nsIAutoCompleteSimpleResultListener - - onValueRemoved: function (result, spec, removeFromDB) { - if (removeFromDB) { - PlacesUtils.history.removePage(NetUtil.newURI(spec)); - } - }, - - ////////////////////////////////////////////////////////////////////////////// - //// nsIAutoCompleteSearchDescriptor - - get searchType() Ci.nsIAutoCompleteSearchDescriptor.SEARCH_TYPE_IMMEDIATE, - - ////////////////////////////////////////////////////////////////////////////// - //// nsISupports - - classID: Components.ID("f964a319-397a-4d21-8be6-5cdd1ee3e3ae"), - - _xpcom_factory: XPCOMUtils.generateSingletonFactory(UnifiedComplete), - - QueryInterface: XPCOMUtils.generateQI([ - Ci.nsIAutoCompleteSearch, - Ci.nsIAutoCompleteSimpleResultListener, - Ci.mozIPlacesAutoComplete, - Ci.nsIObserver, - Ci.nsISupportsWeakReference - ]) -}; - -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([UnifiedComplete]); diff --git a/toolkit/components/places/UnifiedComplete.manifest b/toolkit/components/places/UnifiedComplete.manifest deleted file mode 100644 index 9ee03b60d6f..00000000000 --- a/toolkit/components/places/UnifiedComplete.manifest +++ /dev/null @@ -1,2 +0,0 @@ -component {f964a319-397a-4d21-8be6-5cdd1ee3e3ae} UnifiedComplete.js -contract @mozilla.org/autocomplete/search;1?name=unifiedcomplete {f964a319-397a-4d21-8be6-5cdd1ee3e3ae} diff --git a/toolkit/components/places/moz.build b/toolkit/components/places/moz.build index 6e9537031ca..9acb3f7d205 100644 --- a/toolkit/components/places/moz.build +++ b/toolkit/components/places/moz.build @@ -87,8 +87,6 @@ if CONFIG['MOZ_PLACES']: EXTRA_COMPONENTS += [ 'nsPlacesAutoComplete.js', 'nsPlacesAutoComplete.manifest', - 'UnifiedComplete.js', - 'UnifiedComplete.manifest', ] FINAL_LIBRARY = 'xul' diff --git a/toolkit/components/places/tests/unit/test_priorityUrlProvider.js b/toolkit/components/places/tests/unit/test_priorityUrlProvider.js index 80cbd515464..40e62260bc5 100644 --- a/toolkit/components/places/tests/unit/test_priorityUrlProvider.js +++ b/toolkit/components/places/tests/unit/test_priorityUrlProvider.js @@ -11,7 +11,7 @@ function run_test() { add_task(function* search_engine_match() { let engine = yield promiseDefaultSearchEngine(); let token = engine.getResultDomain(); - let match = yield PriorityUrlProvider.getMatch(token.substr(0, 1)); + let match = yield PriorityUrlProvider.getMatchingSpec(token.substr(0, 1)); do_check_eq(match.url, engine.searchForm); do_check_eq(match.title, engine.name); do_check_eq(match.iconUrl, engine.iconURI ? engine.iconURI.spec : null); @@ -19,7 +19,7 @@ add_task(function* search_engine_match() { }); add_task(function* no_match() { - do_check_eq(null, yield PriorityUrlProvider.getMatch("test")); + do_check_eq(null, yield PriorityUrlProvider.getMatchingSpec("test")); }); add_task(function* hide_search_engine_nomatch() { @@ -29,16 +29,16 @@ add_task(function* hide_search_engine_nomatch() { Services.search.removeEngine(engine); yield promiseTopic; do_check_true(engine.hidden); - do_check_eq(null, yield PriorityUrlProvider.getMatch(token.substr(0, 1))); + do_check_eq(null, yield PriorityUrlProvider.getMatchingSpec(token.substr(0, 1))); }); add_task(function* add_search_engine_match() { let promiseTopic = promiseSearchTopic("engine-added"); - do_check_eq(null, yield PriorityUrlProvider.getMatch("bacon")); + do_check_eq(null, yield PriorityUrlProvider.getMatchingSpec("bacon")); Services.search.addEngineWithDetails("bacon", "", "bacon", "Search Bacon", "GET", "http://www.bacon.moz/?search={searchTerms}"); yield promiseSearchTopic; - let match = yield PriorityUrlProvider.getMatch("bacon"); + let match = yield PriorityUrlProvider.getMatchingSpec("bacon"); do_check_eq(match.url, "http://www.bacon.moz"); do_check_eq(match.title, "bacon"); do_check_eq(match.iconUrl, null); @@ -50,7 +50,7 @@ add_task(function* remove_search_engine_nomatch() { let promiseTopic = promiseSearchTopic("engine-removed"); Services.search.removeEngine(engine); yield promiseTopic; - do_check_eq(null, yield PriorityUrlProvider.getMatch("bacon")); + do_check_eq(null, yield PriorityUrlProvider.getMatchingSpec("bacon")); }); function promiseDefaultSearchEngine() {