diff options
author | mariakhomenko@chromium.org <mariakhomenko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-05 05:18:30 +0000 |
---|---|---|
committer | mariakhomenko@chromium.org <mariakhomenko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-05 05:18:30 +0000 |
commit | 0234620fafba7155110789b53e95b3134266fa89 (patch) | |
tree | 91537494e063ab402ecc863f67586106fbb73150 | |
parent | c717454fadee4ae4d4767f5b89243de146036bf4 (diff) | |
download | chromium_src-0234620fafba7155110789b53e95b3134266fa89.zip chromium_src-0234620fafba7155110789b53e95b3134266fa89.tar.gz chromium_src-0234620fafba7155110789b53e95b3134266fa89.tar.bz2 |
Part 1 of search provider refactoring.
Creates a base class shared by zero_suggest_provider and search_provider
which will contain common implementation pieces for both classes.
Moves Result, NavigationsResults, SuggestResult, Results objects into
the base class without any changes to the implementation. These objects
are used by both classes.
Moves common typedefs up: MatchKey, MatchMap, NavigationResults,
SuggestResults.
BUG=338955
TBR=mpearson@chromium.org
Review URL: https://codereview.chromium.org/131003011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@248856 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/autocomplete/base_search_provider.cc | 222 | ||||
-rw-r--r-- | chrome/browser/autocomplete/base_search_provider.h | 249 | ||||
-rw-r--r-- | chrome/browser/autocomplete/search_provider.cc | 216 | ||||
-rw-r--r-- | chrome/browser/autocomplete/search_provider.h | 212 | ||||
-rw-r--r-- | chrome/browser/autocomplete/zero_suggest_provider.cc | 42 | ||||
-rw-r--r-- | chrome/browser/autocomplete/zero_suggest_provider.h | 26 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 2 |
7 files changed, 507 insertions, 462 deletions
diff --git a/chrome/browser/autocomplete/base_search_provider.cc b/chrome/browser/autocomplete/base_search_provider.cc new file mode 100644 index 0000000..adc68ed --- /dev/null +++ b/chrome/browser/autocomplete/base_search_provider.cc @@ -0,0 +1,222 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/autocomplete/base_search_provider.h" + +#include "base/strings/string_util.h" +#include "chrome/browser/autocomplete/autocomplete_provider_listener.h" +#include "chrome/browser/autocomplete/url_prefix.h" +#include "chrome/browser/profiles/profile.h" +#include "net/base/escape.h" +#include "net/base/net_util.h" + +// BaseSearchProvider --------------------------------------------------------- + +BaseSearchProvider::BaseSearchProvider(AutocompleteProviderListener* listener, + Profile* profile, + AutocompleteProvider::Type type) + : AutocompleteProvider(listener, profile, type) {} + +BaseSearchProvider::~BaseSearchProvider() {} + +// BaseSearchProvider::Result -------------------------------------------------- + +BaseSearchProvider::Result::Result(bool from_keyword_provider, + int relevance, + bool relevance_from_server) + : from_keyword_provider_(from_keyword_provider), + relevance_(relevance), + relevance_from_server_(relevance_from_server) {} + +BaseSearchProvider::Result::~Result() {} + +// BaseSearchProvider::SuggestResult ------------------------------------------- + +BaseSearchProvider::SuggestResult::SuggestResult( + const base::string16& suggestion, + AutocompleteMatchType::Type type, + const base::string16& match_contents, + const base::string16& annotation, + const std::string& suggest_query_params, + const std::string& deletion_url, + bool from_keyword_provider, + int relevance, + bool relevance_from_server, + bool should_prefetch, + const base::string16& input_text) + : Result(from_keyword_provider, relevance, relevance_from_server), + suggestion_(suggestion), + type_(type), + annotation_(annotation), + suggest_query_params_(suggest_query_params), + deletion_url_(deletion_url), + should_prefetch_(should_prefetch) { + match_contents_ = match_contents; + DCHECK(!match_contents_.empty()); + ClassifyMatchContents(true, input_text); +} + +BaseSearchProvider::SuggestResult::~SuggestResult() {} + +void BaseSearchProvider::SuggestResult::ClassifyMatchContents( + const bool allow_bolding_all, + const base::string16& input_text) { + size_t input_position = match_contents_.find(input_text); + if (!allow_bolding_all && (input_position == base::string16::npos)) { + // Bail if the code below to update the bolding would bold the whole + // string. Note that the string may already be entirely bolded; if + // so, leave it as is. + return; + } + match_contents_class_.clear(); + // We do intra-string highlighting for suggestions - the suggested segment + // will be highlighted, e.g. for input_text = "you" the suggestion may be + // "youtube", so we'll bold the "tube" section: you*tube*. + if (input_text != match_contents_) { + if (input_position == base::string16::npos) { + // The input text is not a substring of the query string, e.g. input + // text is "slasdot" and the query string is "slashdot", so we bold the + // whole thing. + match_contents_class_.push_back( + ACMatchClassification(0, ACMatchClassification::MATCH)); + } else { + // We don't iterate over the string here annotating all matches because + // it looks odd to have every occurrence of a substring that may be as + // short as a single character highlighted in a query suggestion result, + // e.g. for input text "s" and query string "southwest airlines", it + // looks odd if both the first and last s are highlighted. + if (input_position != 0) { + match_contents_class_.push_back( + ACMatchClassification(0, ACMatchClassification::MATCH)); + } + match_contents_class_.push_back( + ACMatchClassification(input_position, ACMatchClassification::NONE)); + size_t next_fragment_position = input_position + input_text.length(); + if (next_fragment_position < match_contents_.length()) { + match_contents_class_.push_back(ACMatchClassification( + next_fragment_position, ACMatchClassification::MATCH)); + } + } + } else { + // Otherwise, match_contents_ is a verbatim (what-you-typed) match, either + // for the default provider or a keyword search provider. + match_contents_class_.push_back( + ACMatchClassification(0, ACMatchClassification::NONE)); + } +} + +bool BaseSearchProvider::SuggestResult::IsInlineable( + const base::string16& input) const { + return StartsWith(suggestion_, input, false); +} + +int BaseSearchProvider::SuggestResult::CalculateRelevance( + const AutocompleteInput& input, + bool keyword_provider_requested) const { + if (!from_keyword_provider_ && keyword_provider_requested) + return 100; + return ((input.type() == AutocompleteInput::URL) ? 300 : 600); +} + +// BaseSearchProvider::NavigationResult ---------------------------------------- + +BaseSearchProvider::NavigationResult::NavigationResult( + const AutocompleteProvider& provider, + const GURL& url, + const base::string16& description, + bool from_keyword_provider, + int relevance, + bool relevance_from_server, + const base::string16& input_text, + const std::string& languages) + : Result(from_keyword_provider, relevance, relevance_from_server), + url_(url), + formatted_url_(AutocompleteInput::FormattedStringWithEquivalentMeaning( + url, + provider.StringForURLDisplay(url, true, false))), + description_(description) { + DCHECK(url_.is_valid()); + CalculateAndClassifyMatchContents(true, input_text, languages); +} + +BaseSearchProvider::NavigationResult::~NavigationResult() {} + +void BaseSearchProvider::NavigationResult::CalculateAndClassifyMatchContents( + const bool allow_bolding_nothing, + const base::string16& input_text, + const std::string& languages) { + // First look for the user's input inside the formatted url as it would be + // without trimming the scheme, so we can find matches at the beginning of the + // scheme. + const URLPrefix* prefix = + URLPrefix::BestURLPrefix(formatted_url_, input_text); + size_t match_start = (prefix == NULL) ? formatted_url_.find(input_text) + : prefix->prefix.length(); + bool trim_http = !AutocompleteInput::HasHTTPScheme(input_text) && + (!prefix || (match_start != 0)); + const net::FormatUrlTypes format_types = + net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP); + + base::string16 match_contents = net::FormatUrl(url_, languages, format_types, + net::UnescapeRule::SPACES, NULL, NULL, &match_start); + // If the first match in the untrimmed string was inside a scheme that we + // trimmed, look for a subsequent match. + if (match_start == base::string16::npos) + match_start = match_contents.find(input_text); + // Update |match_contents_| and |match_contents_class_| if it's allowed. + if (allow_bolding_nothing || (match_start != base::string16::npos)) { + match_contents_ = match_contents; + // Safe if |match_start| is npos; also safe if the input is longer than the + // remaining contents after |match_start|. + AutocompleteMatch::ClassifyLocationInString(match_start, + input_text.length(), match_contents_.length(), + ACMatchClassification::URL, &match_contents_class_); + } +} + +bool BaseSearchProvider::NavigationResult::IsInlineable( + const base::string16& input) const { + return URLPrefix::BestURLPrefix(formatted_url_, input) != NULL; +} + +int BaseSearchProvider::NavigationResult::CalculateRelevance( + const AutocompleteInput& input, + bool keyword_provider_requested) const { + return (from_keyword_provider_ || !keyword_provider_requested) ? 800 : 150; +} + +// BaseSearchProvider::Results ------------------------------------------------- + +BaseSearchProvider::Results::Results() : verbatim_relevance(-1) {} + +BaseSearchProvider::Results::~Results() {} + +void BaseSearchProvider::Results::Clear() { + suggest_results.clear(); + navigation_results.clear(); + verbatim_relevance = -1; + metadata.clear(); +} + +bool BaseSearchProvider::Results::HasServerProvidedScores() const { + if (verbatim_relevance >= 0) + return true; + + // Right now either all results of one type will be server-scored or they will + // all be locally scored, but in case we change this later, we'll just check + // them all. + for (SuggestResults::const_iterator i(suggest_results.begin()); + i != suggest_results.end(); ++i) { + if (i->relevance_from_server()) + return true; + } + for (NavigationResults::const_iterator i(navigation_results.begin()); + i != navigation_results.end(); ++i) { + if (i->relevance_from_server()) + return true; + } + + return false; +} + diff --git a/chrome/browser/autocomplete/base_search_provider.h b/chrome/browser/autocomplete/base_search_provider.h new file mode 100644 index 0000000..afdd948 --- /dev/null +++ b/chrome/browser/autocomplete/base_search_provider.h @@ -0,0 +1,249 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// This class contains common functionality for search-based autocomplete +// providers. Search provider and zero suggest provider both use it for common +// functionality. + +#ifndef CHROME_BROWSER_AUTOCOMPLETE_BASE_SEARCH_PROVIDER_H_ +#define CHROME_BROWSER_AUTOCOMPLETE_BASE_SEARCH_PROVIDER_H_ + +#include <map> +#include <string> +#include <utility> +#include <vector> + +#include "base/strings/string16.h" +#include "chrome/browser/autocomplete/autocomplete_input.h" +#include "chrome/browser/autocomplete/autocomplete_match.h" +#include "chrome/browser/autocomplete/autocomplete_provider.h" +#include "net/url_request/url_fetcher_delegate.h" + +class AutocompleteProviderListener; +class GURL; +class Profile; + +// Base functionality for receiving suggestions from a search engine. +// This class is abstract and should only be used as a base for other +// autocomplete providers utilizing its functionality. +class BaseSearchProvider : public AutocompleteProvider, + public net::URLFetcherDelegate { + public: + BaseSearchProvider(AutocompleteProviderListener* listener, + Profile* profile, + AutocompleteProvider::Type type); + + protected: + virtual ~BaseSearchProvider(); + + // The Result classes are intermediate representations of AutocompleteMatches, + // simply containing relevance-ranked search and navigation suggestions. + // They may be cached to provide some synchronous matches while requests for + // new suggestions from updated input are in flight. + // TODO(msw) Extend these classes to generate their corresponding matches and + // other requisite data, in order to consolidate and simplify the + // highly fragmented SearchProvider logic for each Result type. + class Result { + public: + Result(bool from_keyword_provider, + int relevance, + bool relevance_from_server); + virtual ~Result(); + + bool from_keyword_provider() const { return from_keyword_provider_; } + + const base::string16& match_contents() const { return match_contents_; } + const ACMatchClassifications& match_contents_class() const { + return match_contents_class_; + } + + int relevance() const { return relevance_; } + void set_relevance(int relevance) { relevance_ = relevance; } + + bool relevance_from_server() const { return relevance_from_server_; } + void set_relevance_from_server(bool relevance_from_server) { + relevance_from_server_ = relevance_from_server; + } + + // Returns if this result is inlineable against the current input |input|. + // Non-inlineable results are stale. + virtual bool IsInlineable(const base::string16& input) const = 0; + + // Returns the default relevance value for this result (which may + // be left over from a previous omnibox input) given the current + // input and whether the current input caused a keyword provider + // to be active. + virtual int CalculateRelevance(const AutocompleteInput& input, + bool keyword_provider_requested) const = 0; + + protected: + // The contents to be displayed and its style info. + base::string16 match_contents_; + ACMatchClassifications match_contents_class_; + + // True if the result came from the keyword provider. + bool from_keyword_provider_; + + // The relevance score. + int relevance_; + + private: + // Whether this result's relevance score was fully or partly calculated + // based on server information, and thus is assumed to be more accurate. + // This is ultimately used in + // SearchProvider::ConvertResultsToAutocompleteMatches(), see comments + // there. + bool relevance_from_server_; + }; + + class SuggestResult : public Result { + public: + SuggestResult(const base::string16& suggestion, + AutocompleteMatchType::Type type, + const base::string16& match_contents, + const base::string16& annotation, + const std::string& suggest_query_params, + const std::string& deletion_url, + bool from_keyword_provider, + int relevance, + bool relevance_from_server, + bool should_prefetch, + const base::string16& input_text); + virtual ~SuggestResult(); + + const base::string16& suggestion() const { return suggestion_; } + AutocompleteMatchType::Type type() const { return type_; } + const base::string16& annotation() const { return annotation_; } + const std::string& suggest_query_params() const { + return suggest_query_params_; + } + const std::string& deletion_url() const { return deletion_url_; } + bool should_prefetch() const { return should_prefetch_; } + + // Fills in |match_contents_class_| to reflect how |match_contents_| should + // be displayed and bolded against the current |input_text|. If + // |allow_bolding_all| is false and |match_contents_class_| would have all + // of |match_contents_| bolded, do nothing. + void ClassifyMatchContents(const bool allow_bolding_all, + const base::string16& input_text); + + // Result: + virtual bool IsInlineable(const base::string16& input) const OVERRIDE; + virtual int CalculateRelevance( + const AutocompleteInput& input, + bool keyword_provider_requested) const OVERRIDE; + + private: + // The search terms to be used for this suggestion. + base::string16 suggestion_; + + AutocompleteMatchType::Type type_; + + // Optional annotation for the |match_contents_| for disambiguation. + // This may be displayed in the autocomplete match contents, but is defined + // separately to facilitate different formatting. + base::string16 annotation_; + + // Optional additional parameters to be added to the search URL. + std::string suggest_query_params_; + + // Optional deletion URL provided with suggestions. Fetching this URL + // should result in some reasonable deletion behaviour on the server, + // e.g. deleting this term out of a user's server-side search history. + std::string deletion_url_; + + // Should this result be prefetched? + bool should_prefetch_; + }; + + class NavigationResult : public Result { + public: + // |provider| is necessary to use StringForURLDisplay() in order to + // compute |formatted_url_|. + NavigationResult(const AutocompleteProvider& provider, + const GURL& url, + const base::string16& description, + bool from_keyword_provider, + int relevance, + bool relevance_from_server, + const base::string16& input_text, + const std::string& languages); + virtual ~NavigationResult(); + + const GURL& url() const { return url_; } + const base::string16& description() const { return description_; } + const base::string16& formatted_url() const { return formatted_url_; } + + // Fills in |match_contents_| and |match_contents_class_| to reflect how + // the URL should be displayed and bolded against the current |input_text| + // and user |languages|. If |allow_bolding_nothing| is false and + // |match_contents_class_| would result in an entirely unbolded + // |match_contents_|, do nothing. + void CalculateAndClassifyMatchContents(const bool allow_bolding_nothing, + const base::string16& input_text, + const std::string& languages); + + // Result: + virtual bool IsInlineable(const base::string16& input) const OVERRIDE; + virtual int CalculateRelevance( + const AutocompleteInput& input, + bool keyword_provider_requested) const OVERRIDE; + + private: + // The suggested url for navigation. + GURL url_; + + // The properly formatted ("fixed up") URL string with equivalent meaning + // to the one in |url_|. + base::string16 formatted_url_; + + // The suggested navigational result description; generally the site name. + base::string16 description_; + }; + + typedef std::vector<SuggestResult> SuggestResults; + typedef std::vector<NavigationResult> NavigationResults; + typedef std::pair<base::string16, std::string> MatchKey; + typedef std::map<MatchKey, AutocompleteMatch> MatchMap; + + // A simple structure bundling most of the information (including + // both SuggestResults and NavigationResults) returned by a call to + // the suggest server. + // + // This has to be declared after the typedefs since it relies on some of them. + struct Results { + Results(); + ~Results(); + + // Clears |suggest_results| and |navigation_results| and resets + // |verbatim_relevance| to -1 (implies unset). + void Clear(); + + // Returns whether any of the results (including verbatim) have + // server-provided scores. + bool HasServerProvidedScores() const; + + // Query suggestions sorted by relevance score. + SuggestResults suggest_results; + + // Navigational suggestions sorted by relevance score. + NavigationResults navigation_results; + + // The server supplied verbatim relevance scores. Negative values + // indicate that there is no suggested score; a value of 0 + // suppresses the verbatim result. + int verbatim_relevance; + + // The JSON metadata associated with this server response. + std::string metadata; + + private: + DISALLOW_COPY_AND_ASSIGN(Results); + }; + + private: + DISALLOW_COPY_AND_ASSIGN(BaseSearchProvider); +}; + +#endif // CHROME_BROWSER_AUTOCOMPLETE_BASE_SEARCH_PROVIDER_H_ diff --git a/chrome/browser/autocomplete/search_provider.cc b/chrome/browser/autocomplete/search_provider.cc index e93cb02..c93833c 100644 --- a/chrome/browser/autocomplete/search_provider.cc +++ b/chrome/browser/autocomplete/search_provider.cc @@ -20,7 +20,6 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/browser/autocomplete/autocomplete_classifier.h" #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" -#include "chrome/browser/autocomplete/autocomplete_match.h" #include "chrome/browser/autocomplete/autocomplete_provider_listener.h" #include "chrome/browser/autocomplete/autocomplete_result.h" #include "chrome/browser/autocomplete/keyword_provider.h" @@ -175,8 +174,7 @@ void SuggestionDeletionHandler::OnURLFetchComplete( // SearchProvider::Providers -------------------------------------------------- SearchProvider::Providers::Providers(TemplateURLService* template_url_service) - : template_url_service_(template_url_service) { -} + : template_url_service_(template_url_service) {} const TemplateURL* SearchProvider::Providers::GetDefaultProviderURL() const { return default_provider_.empty() ? NULL : @@ -189,178 +187,6 @@ const TemplateURL* SearchProvider::Providers::GetKeywordProviderURL() const { } -// SearchProvider::Result ----------------------------------------------------- - -SearchProvider::Result::Result(bool from_keyword_provider, - int relevance, - bool relevance_from_server) - : from_keyword_provider_(from_keyword_provider), - relevance_(relevance), - relevance_from_server_(relevance_from_server) { -} - -SearchProvider::Result::~Result() { -} - - -// SearchProvider::SuggestResult ---------------------------------------------- - -SearchProvider::SuggestResult::SuggestResult( - const base::string16& suggestion, - AutocompleteMatchType::Type type, - const base::string16& match_contents, - const base::string16& annotation, - const std::string& suggest_query_params, - const std::string& deletion_url, - bool from_keyword_provider, - int relevance, - bool relevance_from_server, - bool should_prefetch, - const base::string16& input_text) - : Result(from_keyword_provider, relevance, relevance_from_server), - suggestion_(suggestion), - type_(type), - annotation_(annotation), - suggest_query_params_(suggest_query_params), - deletion_url_(deletion_url), - should_prefetch_(should_prefetch) { - match_contents_ = match_contents; - DCHECK(!match_contents_.empty()); - ClassifyMatchContents(true, input_text); -} - -SearchProvider::SuggestResult::~SuggestResult() { -} - -void SearchProvider::SuggestResult::ClassifyMatchContents( - const bool allow_bolding_all, - const base::string16& input_text) { - size_t input_position = match_contents_.find(input_text); - if (!allow_bolding_all && (input_position == base::string16::npos)) { - // Bail if the code below to update the bolding would bold the whole - // string. Note that the string may already be entirely bolded; if - // so, leave it as is. - return; - } - match_contents_class_.clear(); - // We do intra-string highlighting for suggestions - the suggested segment - // will be highlighted, e.g. for input_text = "you" the suggestion may be - // "youtube", so we'll bold the "tube" section: you*tube*. - if (input_text != match_contents_) { - if (input_position == base::string16::npos) { - // The input text is not a substring of the query string, e.g. input - // text is "slasdot" and the query string is "slashdot", so we bold the - // whole thing. - match_contents_class_.push_back(ACMatchClassification( - 0, ACMatchClassification::MATCH)); - } else { - // We don't iterate over the string here annotating all matches because - // it looks odd to have every occurrence of a substring that may be as - // short as a single character highlighted in a query suggestion result, - // e.g. for input text "s" and query string "southwest airlines", it - // looks odd if both the first and last s are highlighted. - if (input_position != 0) { - match_contents_class_.push_back(ACMatchClassification( - 0, ACMatchClassification::MATCH)); - } - match_contents_class_.push_back( - ACMatchClassification(input_position, ACMatchClassification::NONE)); - size_t next_fragment_position = input_position + input_text.length(); - if (next_fragment_position < match_contents_.length()) { - match_contents_class_.push_back(ACMatchClassification( - next_fragment_position, ACMatchClassification::MATCH)); - } - } - } else { - // Otherwise, match_contents_ is a verbatim (what-you-typed) match, either - // for the default provider or a keyword search provider. - match_contents_class_.push_back(ACMatchClassification( - 0, ACMatchClassification::NONE)); - } -} - -bool SearchProvider::SuggestResult::IsInlineable( - const base::string16& input) const { - return StartsWith(suggestion_, input, false); -} - -int SearchProvider::SuggestResult::CalculateRelevance( - const AutocompleteInput& input, - bool keyword_provider_requested) const { - if (!from_keyword_provider_ && keyword_provider_requested) - return 100; - return ((input.type() == AutocompleteInput::URL) ? 300 : 600); -} - - -// SearchProvider::NavigationResult ------------------------------------------- - -SearchProvider::NavigationResult::NavigationResult( - const AutocompleteProvider& provider, - const GURL& url, - const base::string16& description, - bool from_keyword_provider, - int relevance, - bool relevance_from_server, - const base::string16& input_text, - const std::string& languages) - : Result(from_keyword_provider, relevance, relevance_from_server), - url_(url), - formatted_url_(AutocompleteInput::FormattedStringWithEquivalentMeaning( - url, provider.StringForURLDisplay(url, true, false))), - description_(description) { - DCHECK(url_.is_valid()); - CalculateAndClassifyMatchContents(true, input_text, languages); -} - -SearchProvider::NavigationResult::~NavigationResult() { -} - -void SearchProvider::NavigationResult::CalculateAndClassifyMatchContents( - const bool allow_bolding_nothing, - const base::string16& input_text, - const std::string& languages) { - // First look for the user's input inside the formatted url as it would be - // without trimming the scheme, so we can find matches at the beginning of the - // scheme. - const URLPrefix* prefix = - URLPrefix::BestURLPrefix(formatted_url_, input_text); - size_t match_start = (prefix == NULL) ? - formatted_url_.find(input_text) : prefix->prefix.length(); - bool trim_http = !AutocompleteInput::HasHTTPScheme(input_text) && - (!prefix || (match_start != 0)); - const net::FormatUrlTypes format_types = - net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP); - - base::string16 match_contents = net::FormatUrl(url_, languages, format_types, - net::UnescapeRule::SPACES, NULL, NULL, &match_start); - // If the first match in the untrimmed string was inside a scheme that we - // trimmed, look for a subsequent match. - if (match_start == base::string16::npos) - match_start = match_contents.find(input_text); - // Update |match_contents_| and |match_contents_class_| if it's allowed. - if (allow_bolding_nothing || (match_start != base::string16::npos)) { - match_contents_ = match_contents; - // Safe if |match_start| is npos; also safe if the input is longer than the - // remaining contents after |match_start|. - AutocompleteMatch::ClassifyLocationInString(match_start, - input_text.length(), match_contents_.length(), - ACMatchClassification::URL, &match_contents_class_); - } -} - -bool SearchProvider::NavigationResult::IsInlineable( - const base::string16& input) const { - return URLPrefix::BestURLPrefix(formatted_url_, input) != NULL; -} - -int SearchProvider::NavigationResult::CalculateRelevance( - const AutocompleteInput& input, - bool keyword_provider_requested) const { - return (from_keyword_provider_ || !keyword_provider_requested) ? 800 : 150; -} - - // SearchProvider::CompareScoredResults --------------------------------------- class SearchProvider::CompareScoredResults { @@ -372,43 +198,6 @@ class SearchProvider::CompareScoredResults { }; -// SearchProvider::Results ---------------------------------------------------- - -SearchProvider::Results::Results() : verbatim_relevance(-1) { -} - -SearchProvider::Results::~Results() { -} - -void SearchProvider::Results::Clear() { - suggest_results.clear(); - navigation_results.clear(); - verbatim_relevance = -1; - metadata.clear(); -} - -bool SearchProvider::Results::HasServerProvidedScores() const { - if (verbatim_relevance >= 0) - return true; - - // Right now either all results of one type will be server-scored or they will - // all be locally scored, but in case we change this later, we'll just check - // them all. - for (SuggestResults::const_iterator i(suggest_results.begin()); - i != suggest_results.end(); ++i) { - if (i->relevance_from_server()) - return true; - } - for (NavigationResults::const_iterator i(navigation_results.begin()); - i != navigation_results.end(); ++i) { - if (i->relevance_from_server()) - return true; - } - - return false; -} - - // SearchProvider ------------------------------------------------------------- // static @@ -425,8 +214,7 @@ const char SearchProvider::kFalse[] = "false"; SearchProvider::SearchProvider(AutocompleteProviderListener* listener, Profile* profile) - : AutocompleteProvider(listener, profile, - AutocompleteProvider::TYPE_SEARCH), + : BaseSearchProvider(listener, profile, AutocompleteProvider::TYPE_SEARCH), providers_(TemplateURLServiceFactory::GetForProfile(profile)), suggest_results_pending_(0), field_trial_triggered_(false), diff --git a/chrome/browser/autocomplete/search_provider.h b/chrome/browser/autocomplete/search_provider.h index a995c86..a6399aa 100644 --- a/chrome/browser/autocomplete/search_provider.h +++ b/chrome/browser/autocomplete/search_provider.h @@ -21,12 +21,9 @@ #include "base/memory/scoped_vector.h" #include "base/time/time.h" #include "base/timer/timer.h" -#include "chrome/browser/autocomplete/autocomplete_input.h" -#include "chrome/browser/autocomplete/autocomplete_match.h" -#include "chrome/browser/autocomplete/autocomplete_provider.h" +#include "chrome/browser/autocomplete/base_search_provider.h" #include "chrome/browser/history/history_types.h" #include "chrome/browser/search_engines/template_url.h" -#include "net/url_request/url_fetcher_delegate.h" class Profile; class SearchProviderTest; @@ -51,8 +48,7 @@ class URLFetcher; // text. It also starts a task to query the Suggest servers. When that data // comes back, the provider creates and returns matches for the best // suggestions. -class SearchProvider : public AutocompleteProvider, - public net::URLFetcherDelegate { +class SearchProvider : public BaseSearchProvider { public: // ID used in creating URLFetcher for default provider's suggest results. static const int kDefaultProviderURLFetcherID; @@ -153,215 +149,11 @@ class SearchProvider : public AutocompleteProvider, DISALLOW_COPY_AND_ASSIGN(Providers); }; - // The Result classes are intermediate representations of AutocompleteMatches, - // simply containing relevance-ranked search and navigation suggestions. - // They may be cached to provide some synchronous matches while requests for - // new suggestions from updated input are in flight. - // TODO(msw) Extend these classes to generate their corresponding matches and - // other requisite data, in order to consolidate and simplify the - // highly fragmented SearchProvider logic for each Result type. - class Result { - public: - Result(bool from_keyword_provider, - int relevance, - bool relevance_from_server); - virtual ~Result(); - - bool from_keyword_provider() const { return from_keyword_provider_; } - - const base::string16& match_contents() const { return match_contents_; } - const ACMatchClassifications& match_contents_class() const { - return match_contents_class_; - } - - int relevance() const { return relevance_; } - void set_relevance(int relevance) { relevance_ = relevance; } - - bool relevance_from_server() const { return relevance_from_server_; } - void set_relevance_from_server(bool relevance_from_server) { - relevance_from_server_ = relevance_from_server; - } - - // Returns if this result is inlineable against the current input |input|. - // Non-inlineable results are stale. - virtual bool IsInlineable(const base::string16& input) const = 0; - - // Returns the default relevance value for this result (which may - // be left over from a previous omnibox input) given the current - // input and whether the current input caused a keyword provider - // to be active. - virtual int CalculateRelevance(const AutocompleteInput& input, - bool keyword_provider_requested) const = 0; - - protected: - // The contents to be displayed and its style info. - base::string16 match_contents_; - ACMatchClassifications match_contents_class_; - - // True if the result came from the keyword provider. - bool from_keyword_provider_; - - // The relevance score. - int relevance_; - - private: - // Whether this result's relevance score was fully or partly calculated - // based on server information, and thus is assumed to be more accurate. - // This is ultimately used in - // SearchProvider::ConvertResultsToAutocompleteMatches(), see comments - // there. - bool relevance_from_server_; - }; - - class SuggestResult : public Result { - public: - SuggestResult(const base::string16& suggestion, - AutocompleteMatchType::Type type, - const base::string16& match_contents, - const base::string16& annotation, - const std::string& suggest_query_params, - const std::string& deletion_url, - bool from_keyword_provider, - int relevance, - bool relevance_from_server, - bool should_prefetch, - const base::string16& input_text); - virtual ~SuggestResult(); - - const base::string16& suggestion() const { return suggestion_; } - AutocompleteMatchType::Type type() const { return type_; } - const base::string16& annotation() const { return annotation_; } - const std::string& suggest_query_params() const { - return suggest_query_params_; - } - const std::string& deletion_url() const { return deletion_url_; } - bool should_prefetch() const { return should_prefetch_; } - - // Fills in |match_contents_class_| to reflect how |match_contents_| should - // be displayed and bolded against the current |input_text|. If - // |allow_bolding_all| is false and |match_contents_class_| would have all - // of |match_contents_| bolded, do nothing. - void ClassifyMatchContents(const bool allow_bolding_all, - const base::string16& input_text); - - // Result: - virtual bool IsInlineable(const base::string16& input) const OVERRIDE; - virtual int CalculateRelevance( - const AutocompleteInput& input, - bool keyword_provider_requested) const OVERRIDE; - - private: - // The search terms to be used for this suggestion. - base::string16 suggestion_; - - AutocompleteMatchType::Type type_; - - // Optional annotation for the |match_contents_| for disambiguation. - // This may be displayed in the autocomplete match contents, but is defined - // separately to facilitate different formatting. - base::string16 annotation_; - - // Optional additional parameters to be added to the search URL. - std::string suggest_query_params_; - - // Optional deletion URL provided with suggestions. Fetching this URL - // should result in some reasonable deletion behaviour on the server, - // e.g. deleting this term out of a user's server-side search history. - std::string deletion_url_; - - // Should this result be prefetched? - bool should_prefetch_; - }; - - class NavigationResult : public Result { - public: - // |provider| is necessary to use StringForURLDisplay() in order to - // compute |formatted_url_|. - NavigationResult(const AutocompleteProvider& provider, - const GURL& url, - const base::string16& description, - bool from_keyword_provider, - int relevance, - bool relevance_from_server, - const base::string16& input_text, - const std::string& languages); - virtual ~NavigationResult(); - - const GURL& url() const { return url_; } - const base::string16& description() const { return description_; } - const base::string16& formatted_url() const { return formatted_url_; } - - // Fills in |match_contents_| and |match_contents_class_| to reflect how - // the URL should be displayed and bolded against the current |input_text| - // and user |languages|. If |allow_bolding_nothing| is false and - // |match_contents_class_| would result in an entirely unbolded - // |match_contents_|, do nothing. - void CalculateAndClassifyMatchContents(const bool allow_bolding_nothing, - const base::string16& input_text, - const std::string& languages); - - // Result: - virtual bool IsInlineable(const base::string16& input) const OVERRIDE; - virtual int CalculateRelevance( - const AutocompleteInput& input, - bool keyword_provider_requested) const OVERRIDE; - - private: - // The suggested url for navigation. - GURL url_; - - // The properly formatted ("fixed up") URL string with equivalent meaning - // to the one in |url_|. - base::string16 formatted_url_; - - // The suggested navigational result description; generally the site name. - base::string16 description_; - }; - class CompareScoredResults; - typedef std::vector<SuggestResult> SuggestResults; - typedef std::vector<NavigationResult> NavigationResults; typedef std::vector<history::KeywordSearchTermVisit> HistoryResults; - typedef std::pair<base::string16, std::string> MatchKey; - typedef std::map<MatchKey, AutocompleteMatch> MatchMap; typedef ScopedVector<SuggestionDeletionHandler> SuggestionDeletionHandlers; - // A simple structure bundling most of the information (including - // both SuggestResults and NavigationResults) returned by a call to - // the suggest server. - // - // This has to be declared after the typedefs since it relies on some of them. - struct Results { - Results(); - ~Results(); - - // Clears |suggest_results| and |navigation_results| and resets - // |verbatim_relevance| to -1 (implies unset). - void Clear(); - - // Returns whether any of the results (including verbatim) have - // server-provided scores. - bool HasServerProvidedScores() const; - - // Query suggestions sorted by relevance score. - SuggestResults suggest_results; - - // Navigational suggestions sorted by relevance score. - NavigationResults navigation_results; - - // The server supplied verbatim relevance scores. Negative values - // indicate that there is no suggested score; a value of 0 - // suppresses the verbatim result. - int verbatim_relevance; - - // The JSON metadata associated with this server response. - std::string metadata; - - private: - DISALLOW_COPY_AND_ASSIGN(Results); - }; - // Returns an AutocompleteMatch with the given |autocomplete_provider| // for the search |suggestion|, which represents a search via |template_url|. // If |template_url| is NULL, returns a match with an invalid destination URL. diff --git a/chrome/browser/autocomplete/zero_suggest_provider.cc b/chrome/browser/autocomplete/zero_suggest_provider.cc index 62db13a..1547bbe 100644 --- a/chrome/browser/autocomplete/zero_suggest_provider.cc +++ b/chrome/browser/autocomplete/zero_suggest_provider.cc @@ -183,8 +183,8 @@ void ZeroSuggestProvider::StartZeroSuggest( ZeroSuggestProvider::ZeroSuggestProvider( AutocompleteProviderListener* listener, Profile* profile) - : AutocompleteProvider(listener, profile, - AutocompleteProvider::TYPE_ZERO_SUGGEST), + : BaseSearchProvider(listener, profile, + AutocompleteProvider::TYPE_ZERO_SUGGEST), template_url_service_(TemplateURLServiceFactory::GetForProfile(profile)), have_pending_request_(false), verbatim_relevance_(kDefaultVerbatimZeroSuggestRelevance), @@ -196,11 +196,10 @@ ZeroSuggestProvider::ZeroSuggestProvider( ZeroSuggestProvider::~ZeroSuggestProvider() { } -void ZeroSuggestProvider::FillResults( - const base::Value& root_val, - int* verbatim_relevance, - SearchProvider::SuggestResults* suggest_results, - SearchProvider::NavigationResults* navigation_results) { +void ZeroSuggestProvider::FillResults(const base::Value& root_val, + int* verbatim_relevance, + SuggestResults* suggest_results, + NavigationResults* navigation_results) { base::string16 query; const base::ListValue* root_list = NULL; const base::ListValue* results = NULL; @@ -267,12 +266,12 @@ void ZeroSuggestProvider::FillResults( if (url.is_valid()) { if (descriptions != NULL) descriptions->GetString(index, &title); - navigation_results->push_back(SearchProvider::NavigationResult( + navigation_results->push_back(NavigationResult( *this, url, title, false, relevance, relevances != NULL, current_query_string16, languages)); } } else { - suggest_results->push_back(SearchProvider::SuggestResult( + suggest_results->push_back(SuggestResult( result, AutocompleteMatchType::SEARCH_SUGGEST, result, base::string16(), std::string(), std::string(), false, relevance, relevances != NULL, false, current_query_string16)); @@ -281,9 +280,9 @@ void ZeroSuggestProvider::FillResults( } void ZeroSuggestProvider::AddSuggestResultsToMap( - const SearchProvider::SuggestResults& results, + const SuggestResults& results, const TemplateURL* template_url, - SearchProvider::MatchMap* map) { + MatchMap* map) { for (size_t i = 0; i < results.size(); ++i) { AddMatchToMap(results[i].relevance(), AutocompleteMatchType::SEARCH_SUGGEST, template_url, results[i].suggestion(), i, map); @@ -295,9 +294,9 @@ void ZeroSuggestProvider::AddMatchToMap(int relevance, const TemplateURL* template_url, const base::string16& query_string, int accepted_suggestion, - SearchProvider::MatchMap* map) { + MatchMap* map) { // Pass in query_string as the input_text to avoid bolding. - SearchProvider::SuggestResult suggestion( + SuggestResult suggestion( query_string, type, query_string, base::string16(), std::string(), std::string(), false, relevance, true, false, query_string); // TODO(samarth|melevin): use the actual omnibox margin here as well instead @@ -311,9 +310,9 @@ void ZeroSuggestProvider::AddMatchToMap(int relevance, // Try to add |match| to |map|. If a match for |query_string| is already in // |map|, replace it if |match| is more relevant. // NOTE: Keep this ToLower() call in sync with url_database.cc. - SearchProvider::MatchKey match_key( + MatchKey match_key( std::make_pair(base::i18n::ToLower(query_string), std::string())); - const std::pair<SearchProvider::MatchMap::iterator, bool> i(map->insert( + const std::pair<MatchMap::iterator, bool> i(map->insert( std::make_pair(match_key, match))); // NOTE: We purposefully do a direct relevance comparison here instead of // using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items added @@ -328,7 +327,7 @@ void ZeroSuggestProvider::AddMatchToMap(int relevance, } AutocompleteMatch ZeroSuggestProvider::NavigationToMatch( - const SearchProvider::NavigationResult& navigation) { + const NavigationResult& navigation) { AutocompleteMatch match(this, navigation.relevance(), false, AutocompleteMatchType::NAVSUGGEST); match.destination_url = navigation.url(); @@ -385,7 +384,7 @@ void ZeroSuggestProvider::Run(const GURL& suggest_url) { } void ZeroSuggestProvider::ParseSuggestResults(const base::Value& root_val) { - SearchProvider::SuggestResults suggest_results; + SuggestResults suggest_results; FillResults(root_val, &verbatim_relevance_, &suggest_results, &navigation_results_); @@ -433,8 +432,7 @@ void ZeroSuggestProvider::ConvertResultsToAutocompleteMatches() { profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); for (size_t i = 0; i < most_visited_urls_.size(); i++) { const history::MostVisitedURL& url = most_visited_urls_[i]; - SearchProvider::NavigationResult nav( - *this, url.url, url.title, false, relevance, true, + NavigationResult nav(*this, url.url, url.title, false, relevance, true, current_query_string16, languages); matches_.push_back(NavigationToMatch(nav)); --relevance; @@ -449,12 +447,12 @@ void ZeroSuggestProvider::ConvertResultsToAutocompleteMatches() { // current typing in the omnibox. matches_.push_back(current_url_match_); - for (SearchProvider::MatchMap::const_iterator it(query_matches_map_.begin()); + for (MatchMap::const_iterator it(query_matches_map_.begin()); it != query_matches_map_.end(); ++it) matches_.push_back(it->second); - for (SearchProvider::NavigationResults::const_iterator it( - navigation_results_.begin()); it != navigation_results_.end(); ++it) + for (NavigationResults::const_iterator it(navigation_results_.begin()); + it != navigation_results_.end(); ++it) matches_.push_back(NavigationToMatch(*it)); } diff --git a/chrome/browser/autocomplete/zero_suggest_provider.h b/chrome/browser/autocomplete/zero_suggest_provider.h index 41d6b04..699e185 100644 --- a/chrome/browser/autocomplete/zero_suggest_provider.h +++ b/chrome/browser/autocomplete/zero_suggest_provider.h @@ -21,13 +21,9 @@ #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" -#include "base/strings/string16.h" -#include "chrome/browser/autocomplete/autocomplete_provider.h" +#include "chrome/browser/autocomplete/base_search_provider.h" #include "chrome/browser/autocomplete/search_provider.h" -#include "net/url_request/url_fetcher_delegate.h" -class AutocompleteInput; -class GURL; class TemplateURLService; namespace base { @@ -49,8 +45,7 @@ class URLFetcher; // TODO(jered): Consider deleting this class and building this functionality // into SearchProvider after dogfood and after we break the association between // omnibox text and suggestions. -class ZeroSuggestProvider : public AutocompleteProvider, - public net::URLFetcherDelegate { +class ZeroSuggestProvider : public BaseSearchProvider { public: // Creates and returns an instance of this provider. static ZeroSuggestProvider* Create(AutocompleteProviderListener* listener, @@ -99,14 +94,14 @@ class ZeroSuggestProvider : public AutocompleteProvider, // |verbatim_relevance|. void FillResults(const base::Value& root_val, int* verbatim_relevance, - SearchProvider::SuggestResults* suggest_results, - SearchProvider::NavigationResults* navigation_results); + SuggestResults* suggest_results, + NavigationResults* navigation_results); // Creates AutocompleteMatches to search |template_url| for "<suggestion>" for // all suggestions in |results|, and adds them to |map|. - void AddSuggestResultsToMap(const SearchProvider::SuggestResults& results, + void AddSuggestResultsToMap(const SuggestResults& results, const TemplateURL* template_url, - SearchProvider::MatchMap* map); + MatchMap* map); // Creates an AutocompleteMatch with the provided |relevance| and |type| to // search |template_url| for |query_string|. |accepted_suggestion| will be @@ -119,11 +114,10 @@ class ZeroSuggestProvider : public AutocompleteProvider, const TemplateURL* template_url, const base::string16& query_string, int accepted_suggestion, - SearchProvider::MatchMap* map); + MatchMap* map); // Returns an AutocompleteMatch for a navigational suggestion |navigation|. - AutocompleteMatch NavigationToMatch( - const SearchProvider::NavigationResult& navigation); + AutocompleteMatch NavigationToMatch(const NavigationResult& navigation); // Fetches zero-suggest suggestions by sending a request using |suggest_url|. void Run(const GURL& suggest_url); @@ -167,9 +161,9 @@ class ZeroSuggestProvider : public AutocompleteProvider, // Suggestion for the current URL. AutocompleteMatch current_url_match_; // Navigation suggestions for the most recent ZeroSuggest input URL. - SearchProvider::NavigationResults navigation_results_; + NavigationResults navigation_results_; // Query suggestions for the most recent ZeroSuggest input URL. - SearchProvider::MatchMap query_matches_map_; + MatchMap query_matches_map_; // The relevance score for the URL of the current page. int verbatim_relevance_; diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index e44aa68..7279ed6 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -192,6 +192,8 @@ 'browser/autocomplete/autocomplete_provider_listener.h', 'browser/autocomplete/autocomplete_result.cc', 'browser/autocomplete/autocomplete_result.h', + 'browser/autocomplete/base_search_provider.cc', + 'browser/autocomplete/base_search_provider.h', 'browser/autocomplete/bookmark_provider.cc', 'browser/autocomplete/bookmark_provider.h', 'browser/autocomplete/builtin_provider.cc', |