Index: chrome/browser/autocomplete/search_provider.cc |
diff --git a/chrome/browser/autocomplete/search_provider.cc b/chrome/browser/autocomplete/search_provider.cc |
index e93cb02c5b79772f1ef5b90bc03d3ed07f09e5ec..16007c5d68d0d288593ffe5bb8bcd54d2b5c19e4 100644 |
--- a/chrome/browser/autocomplete/search_provider.cc |
+++ b/chrome/browser/autocomplete/search_provider.cc |
@@ -7,42 +7,35 @@ |
#include <algorithm> |
#include <cmath> |
-#include "base/callback.h" |
#include "base/i18n/break_iterator.h" |
-#include "base/i18n/case_conversion.h" |
-#include "base/i18n/icu_string_conversions.h" |
-#include "base/json/json_string_value_serializer.h" |
-#include "base/message_loop/message_loop.h" |
#include "base/metrics/histogram.h" |
#include "base/prefs/pref_service.h" |
#include "base/strings/string16.h" |
#include "base/strings/string_util.h" |
#include "base/strings/utf_string_conversions.h" |
+#include "base/time/time.h" |
+#include "base/values.h" |
#include "chrome/browser/autocomplete/autocomplete_classifier.h" |
#include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" |
+#include "chrome/browser/autocomplete/autocomplete_input.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/base_search_provider.h" |
#include "chrome/browser/autocomplete/keyword_provider.h" |
#include "chrome/browser/autocomplete/url_prefix.h" |
-#include "chrome/browser/google/google_util.h" |
#include "chrome/browser/history/history_service.h" |
#include "chrome/browser/history/history_service_factory.h" |
#include "chrome/browser/history/in_memory_database.h" |
+#include "chrome/browser/history/url_database.h" |
#include "chrome/browser/metrics/variations/variations_http_header_provider.h" |
#include "chrome/browser/omnibox/omnibox_field_trial.h" |
#include "chrome/browser/profiles/profile.h" |
#include "chrome/browser/search/search.h" |
+#include "chrome/browser/search_engines/template_url.h" |
#include "chrome/browser/search_engines/template_url_prepopulate_data.h" |
#include "chrome/browser/search_engines/template_url_service.h" |
#include "chrome/browser/search_engines/template_url_service_factory.h" |
-#include "chrome/browser/sync/profile_sync_service.h" |
-#include "chrome/browser/sync/profile_sync_service_factory.h" |
-#include "chrome/browser/ui/browser.h" |
-#include "chrome/browser/ui/browser_finder.h" |
-#include "chrome/browser/ui/browser_instant_controller.h" |
-#include "chrome/browser/ui/search/instant_controller.h" |
-#include "chrome/common/net/url_fixer_upper.h" |
#include "chrome/common/pref_names.h" |
#include "chrome/common/url_constants.h" |
#include "content/public/browser/user_metrics.h" |
@@ -50,15 +43,11 @@ |
#include "net/base/escape.h" |
#include "net/base/load_flags.h" |
#include "net/base/net_util.h" |
-#include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
#include "net/http/http_request_headers.h" |
-#include "net/http/http_response_headers.h" |
#include "net/url_request/url_fetcher.h" |
-#include "net/url_request/url_request_status.h" |
#include "ui/base/l10n/l10n_util.h" |
#include "url/url_util.h" |
- |
// Helpers -------------------------------------------------------------------- |
namespace { |
@@ -81,8 +70,7 @@ enum SuggestRequestsHistogramValue { |
const int kNonURLVerbatimRelevance = 1300; |
// Increments the appropriate value in the histogram by one. |
-void LogOmniboxSuggestRequest( |
- SuggestRequestsHistogramValue request_value) { |
+void LogOmniboxSuggestRequest(SuggestRequestsHistogramValue request_value) { |
UMA_HISTOGRAM_ENUMERATION("Omnibox.SuggestRequests", request_value, |
MAX_SUGGEST_REQUEST_HISTOGRAM_VALUE); |
} |
@@ -102,76 +90,8 @@ bool HasMultipleWords(const base::string16& text) { |
return false; |
} |
-AutocompleteMatchType::Type GetAutocompleteMatchType(const std::string& type) { |
- if (type == "ENTITY") |
- return AutocompleteMatchType::SEARCH_SUGGEST_ENTITY; |
- if (type == "INFINITE") |
- return AutocompleteMatchType::SEARCH_SUGGEST_INFINITE; |
- if (type == "PERSONALIZED") |
- return AutocompleteMatchType::SEARCH_SUGGEST_PERSONALIZED; |
- if (type == "PROFILE") |
- return AutocompleteMatchType::SEARCH_SUGGEST_PROFILE; |
- return AutocompleteMatchType::SEARCH_SUGGEST; |
-} |
- |
} // namespace |
- |
-// SuggestionDeletionHandler ------------------------------------------------- |
- |
-// This class handles making requests to the server in order to delete |
-// personalized suggestions. |
-class SuggestionDeletionHandler : public net::URLFetcherDelegate { |
- public: |
- typedef base::Callback<void(bool, SuggestionDeletionHandler*)> |
- DeletionCompletedCallback; |
- |
- SuggestionDeletionHandler( |
- const std::string& deletion_url, |
- Profile* profile, |
- const DeletionCompletedCallback& callback); |
- |
- virtual ~SuggestionDeletionHandler(); |
- |
- private: |
- // net::URLFetcherDelegate: |
- virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; |
- |
- scoped_ptr<net::URLFetcher> deletion_fetcher_; |
- DeletionCompletedCallback callback_; |
- |
- DISALLOW_COPY_AND_ASSIGN(SuggestionDeletionHandler); |
-}; |
- |
- |
-SuggestionDeletionHandler::SuggestionDeletionHandler( |
- const std::string& deletion_url, |
- Profile* profile, |
- const DeletionCompletedCallback& callback) : callback_(callback) { |
- GURL url(deletion_url); |
- DCHECK(url.is_valid()); |
- |
- deletion_fetcher_.reset(net::URLFetcher::Create( |
- SearchProvider::kDeletionURLFetcherID, |
- url, |
- net::URLFetcher::GET, |
- this)); |
- deletion_fetcher_->SetRequestContext(profile->GetRequestContext()); |
- deletion_fetcher_->Start(); |
-}; |
- |
-SuggestionDeletionHandler::~SuggestionDeletionHandler() { |
-}; |
- |
-void SuggestionDeletionHandler::OnURLFetchComplete( |
- const net::URLFetcher* source) { |
- DCHECK(source == deletion_fetcher_.get()); |
- callback_.Run( |
- source->GetStatus().is_success() && (source->GetResponseCode() == 200), |
- this); |
-}; |
- |
- |
// SearchProvider::Providers -------------------------------------------------- |
SearchProvider::Providers::Providers(TemplateURLService* template_url_service) |
@@ -179,188 +99,19 @@ SearchProvider::Providers::Providers(TemplateURLService* template_url_service) |
} |
const TemplateURL* SearchProvider::Providers::GetDefaultProviderURL() const { |
- return default_provider_.empty() ? NULL : |
- template_url_service_->GetTemplateURLForKeyword(default_provider_); |
+ return default_provider_.empty() |
+ ? NULL |
+ : template_url_service_->GetTemplateURLForKeyword( |
+ default_provider_); |
} |
const TemplateURL* SearchProvider::Providers::GetKeywordProviderURL() const { |
- return keyword_provider_.empty() ? NULL : |
- template_url_service_->GetTemplateURLForKeyword(keyword_provider_); |
-} |
- |
- |
-// 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; |
+ return keyword_provider_.empty() |
+ ? NULL |
+ : template_url_service_->GetTemplateURLForKeyword( |
+ keyword_provider_); |
} |
-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 { |
@@ -371,182 +122,23 @@ 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 |
const int SearchProvider::kDefaultProviderURLFetcherID = 1; |
const int SearchProvider::kKeywordProviderURLFetcherID = 2; |
-const int SearchProvider::kDeletionURLFetcherID = 3; |
int SearchProvider::kMinimumTimeBetweenSuggestQueriesMs = 100; |
-const char SearchProvider::kRelevanceFromServerKey[] = "relevance_from_server"; |
-const char SearchProvider::kShouldPrefetchKey[] = "should_prefetch"; |
-const char SearchProvider::kSuggestMetadataKey[] = "suggest_metadata"; |
-const char SearchProvider::kDeletionUrlKey[] = "deletion_url"; |
-const char SearchProvider::kTrue[] = "true"; |
-const char SearchProvider::kFalse[] = "false"; |
SearchProvider::SearchProvider(AutocompleteProviderListener* listener, |
Profile* profile) |
- : AutocompleteProvider(listener, profile, |
- AutocompleteProvider::TYPE_SEARCH), |
- providers_(TemplateURLServiceFactory::GetForProfile(profile)), |
- suggest_results_pending_(0), |
- field_trial_triggered_(false), |
- field_trial_triggered_in_session_(false) { |
-} |
- |
-// static |
-AutocompleteMatch SearchProvider::CreateSearchSuggestion( |
- AutocompleteProvider* autocomplete_provider, |
- const AutocompleteInput& input, |
- const base::string16& input_text, |
- const SuggestResult& suggestion, |
- const TemplateURL* template_url, |
- int accepted_suggestion, |
- int omnibox_start_margin, |
- bool append_extra_query_params) { |
- AutocompleteMatch match(autocomplete_provider, suggestion.relevance(), false, |
- suggestion.type()); |
- |
- if (!template_url) |
- return match; |
- match.keyword = template_url->keyword(); |
- match.contents = suggestion.match_contents(); |
- match.contents_class = suggestion.match_contents_class(); |
- |
- if (!suggestion.annotation().empty()) |
- match.description = suggestion.annotation(); |
- |
- match.allowed_to_be_default_match = |
- (input_text == suggestion.match_contents()); |
- |
- // When the user forced a query, we need to make sure all the fill_into_edit |
- // values preserve that property. Otherwise, if the user starts editing a |
- // suggestion, non-Search results will suddenly appear. |
- if (input.type() == AutocompleteInput::FORCED_QUERY) |
- match.fill_into_edit.assign(base::ASCIIToUTF16("?")); |
- if (suggestion.from_keyword_provider()) |
- match.fill_into_edit.append(match.keyword + base::char16(' ')); |
- if (!input.prevent_inline_autocomplete() && |
- StartsWith(suggestion.suggestion(), input_text, false)) { |
- match.inline_autocompletion = |
- suggestion.suggestion().substr(input_text.length()); |
- match.allowed_to_be_default_match = true; |
- } |
- match.fill_into_edit.append(suggestion.suggestion()); |
- |
- const TemplateURLRef& search_url = template_url->url_ref(); |
- DCHECK(search_url.SupportsReplacement()); |
- match.search_terms_args.reset( |
- new TemplateURLRef::SearchTermsArgs(suggestion.suggestion())); |
- match.search_terms_args->original_query = input_text; |
- match.search_terms_args->accepted_suggestion = accepted_suggestion; |
- match.search_terms_args->omnibox_start_margin = omnibox_start_margin; |
- match.search_terms_args->suggest_query_params = |
- suggestion.suggest_query_params(); |
- match.search_terms_args->append_extra_query_params = |
- append_extra_query_params; |
- // This is the destination URL sans assisted query stats. This must be set |
- // so the AutocompleteController can properly de-dupe; the controller will |
- // eventually overwrite it before it reaches the user. |
- match.destination_url = |
- GURL(search_url.ReplaceSearchTerms(*match.search_terms_args.get())); |
- |
- // Search results don't look like URLs. |
- match.transition = suggestion.from_keyword_provider() ? |
- content::PAGE_TRANSITION_KEYWORD : content::PAGE_TRANSITION_GENERATED; |
- |
- return match; |
-} |
- |
-// static |
-bool SearchProvider::ShouldPrefetch(const AutocompleteMatch& match) { |
- return match.GetAdditionalInfo(kShouldPrefetchKey) == kTrue; |
-} |
+ : BaseSearchProvider(listener, profile, AutocompleteProvider::TYPE_SEARCH), |
+ providers_(TemplateURLServiceFactory::GetForProfile(profile)) {} |
// static |
std::string SearchProvider::GetSuggestMetadata(const AutocompleteMatch& match) { |
return match.GetAdditionalInfo(kSuggestMetadataKey); |
} |
-void SearchProvider::AddProviderInfo(ProvidersInfo* provider_info) const { |
- provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo()); |
- metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back(); |
- new_entry.set_provider(AsOmniboxEventProviderType()); |
- new_entry.set_provider_done(done_); |
- std::vector<uint32> field_trial_hashes; |
- OmniboxFieldTrial::GetActiveSuggestFieldTrialHashes(&field_trial_hashes); |
- for (size_t i = 0; i < field_trial_hashes.size(); ++i) { |
- if (field_trial_triggered_) |
- new_entry.mutable_field_trial_triggered()->Add(field_trial_hashes[i]); |
- if (field_trial_triggered_in_session_) { |
- new_entry.mutable_field_trial_triggered_in_session()->Add( |
- field_trial_hashes[i]); |
- } |
- } |
-} |
- |
-void SearchProvider::DeleteMatch(const AutocompleteMatch& match) { |
- DCHECK(match.deletable); |
- |
- deletion_handlers_.push_back(new SuggestionDeletionHandler( |
- match.GetAdditionalInfo(SearchProvider::kDeletionUrlKey), |
- profile_, |
- base::Bind(&SearchProvider::OnDeletionComplete, base::Unretained(this)))); |
- |
- HistoryService* const history_service = |
- HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); |
- TemplateURL* template_url = match.GetTemplateURL(profile_, false); |
- // This may be NULL if the template corresponding to the keyword has been |
- // deleted or there is no keyword set. |
- if (template_url != NULL) { |
- history_service->DeleteMatchingURLsForKeyword(template_url->id(), |
- match.contents); |
- } |
- |
- // Immediately update the list of matches to show the match was deleted, |
- // regardless of whether the server request actually succeeds. |
- DeleteMatchFromMatches(match); |
-} |
- |
void SearchProvider::ResetSession() { |
field_trial_triggered_in_session_ = false; |
} |
@@ -681,10 +273,10 @@ void SearchProvider::Start(const AutocompleteInput& input, |
// If we're still running an old query but have since changed the query text |
// or the providers, abort the query. |
- base::string16 default_provider_keyword(default_provider ? |
- default_provider->keyword() : base::string16()); |
- base::string16 keyword_provider_keyword(keyword_provider ? |
- keyword_provider->keyword() : base::string16()); |
+ base::string16 default_provider_keyword( |
+ default_provider ? default_provider->keyword() : base::string16()); |
+ base::string16 keyword_provider_keyword( |
+ keyword_provider ? keyword_provider->keyword() : base::string16()); |
if (!minimal_changes || |
!providers_.equal(default_provider_keyword, keyword_provider_keyword)) { |
// Cancel any in-flight suggest requests. |
@@ -718,39 +310,29 @@ void SearchProvider::Start(const AutocompleteInput& input, |
UpdateMatches(); |
} |
-void SearchProvider::Stop(bool clear_cached_results) { |
- StopSuggest(); |
- done_ = true; |
+bool SearchProvider::IsKeywordRequest(const net::URLFetcher* source) { |
+ return source == keyword_fetcher_.get(); |
+} |
- if (clear_cached_results) |
- ClearAllResults(); |
+bool SearchProvider::IsRequestSuccessful(const net::URLFetcher* source) { |
+ return BaseSearchProvider::IsRequestSuccessful(source) && |
+ (IsKeywordRequest(source) ? providers_.GetKeywordProviderURL() |
+ : providers_.GetDefaultProviderURL()); |
} |
-void SearchProvider::OnURLFetchComplete(const net::URLFetcher* source) { |
- DCHECK(!done_); |
- suggest_results_pending_--; |
+void SearchProvider::LogFetchComplete(const net::URLFetcher* source) { |
LogOmniboxSuggestRequest(REPLY_RECEIVED); |
- DCHECK_GE(suggest_results_pending_, 0); // Should never go negative. |
- |
- const bool is_keyword = (source == keyword_fetcher_.get()); |
- // Ensure the request succeeded and that the provider used is still available. |
- // A verbatim match cannot be generated without this provider, causing errors. |
- const bool request_succeeded = |
- source->GetStatus().is_success() && (source->GetResponseCode() == 200) && |
- (is_keyword ? |
- providers_.GetKeywordProviderURL() : |
- providers_.GetDefaultProviderURL()); |
// Record response time for suggest requests sent to Google. We care |
// only about the common case: the Google default provider used in |
// non-keyword mode. |
const TemplateURL* default_url = providers_.GetDefaultProviderURL(); |
- if (!is_keyword && default_url && |
+ if (IsKeywordRequest(source) && default_url && |
(TemplateURLPrepopulateData::GetEngineType(*default_url) == |
SEARCH_ENGINE_GOOGLE)) { |
const base::TimeDelta elapsed_time = |
base::TimeTicks::Now() - time_suggest_request_sent_; |
- if (request_succeeded) { |
+ if (IsRequestSuccessful(source)) { |
UMA_HISTOGRAM_TIMES("Omnibox.SuggestRequest.Success.GoogleResponseTime", |
elapsed_time); |
} else { |
@@ -758,48 +340,13 @@ void SearchProvider::OnURLFetchComplete(const net::URLFetcher* source) { |
elapsed_time); |
} |
} |
- |
- bool results_updated = false; |
- if (request_succeeded) { |
- const net::HttpResponseHeaders* const response_headers = |
- source->GetResponseHeaders(); |
- std::string json_data; |
- source->GetResponseAsString(&json_data); |
- |
- // JSON is supposed to be UTF-8, but some suggest service providers send |
- // JSON files in non-UTF-8 encodings. The actual encoding is usually |
- // specified in the Content-Type header field. |
- if (response_headers) { |
- std::string charset; |
- if (response_headers->GetCharset(&charset)) { |
- base::string16 data_16; |
- // TODO(jungshik): Switch to CodePageToUTF8 after it's added. |
- if (base::CodepageToUTF16(json_data, charset.c_str(), |
- base::OnStringConversionError::FAIL, |
- &data_16)) |
- json_data = base::UTF16ToUTF8(data_16); |
- } |
- } |
- |
- scoped_ptr<base::Value> data(DeserializeJsonData(json_data)); |
- results_updated = data.get() && ParseSuggestResults(data.get(), is_keyword); |
- } |
- |
- UpdateMatches(); |
- if (done_ || results_updated) |
- listener_->OnProviderUpdate(results_updated); |
} |
-void SearchProvider::OnDeletionComplete(bool success, |
- SuggestionDeletionHandler* handler) { |
- RecordDeletionResult(success); |
- SuggestionDeletionHandlers::iterator it = std::find( |
- deletion_handlers_.begin(), deletion_handlers_.end(), handler); |
- DCHECK(it != deletion_handlers_.end()); |
- deletion_handlers_.erase(it); |
+bool SearchProvider::IsValidQuery(const base::string16 query, |
+ const net::URLFetcher* source) { |
+ return GetInputText(source) == query; |
} |
- |
void SearchProvider::RecordDeletionResult(bool success) { |
if (success) { |
content::RecordAction( |
@@ -810,19 +357,175 @@ void SearchProvider::RecordDeletionResult(bool success) { |
} |
} |
-void SearchProvider::DeleteMatchFromMatches(const AutocompleteMatch& match) { |
- for (ACMatches::iterator i(matches_.begin()); i != matches_.end(); ++i) { |
- // Find the desired match to delete by checking the type and contents. |
- // We can't check the destination URL, because the autocomplete controller |
- // may have reformulated that. Not that while checking for matching |
- // contents works for personalized suggestions, if more match types gain |
- // deletion support, this algorithm may need to be re-examined. |
- if (i->contents == match.contents && i->type == match.type) { |
- matches_.erase(i); |
- break; |
+void SearchProvider::StopSuggest() { |
+ // Increment the appropriate field in the histogram by the number of |
+ // pending requests that were invalidated. |
+ for (int i = 0; i < suggest_results_pending_; i++) |
+ LogOmniboxSuggestRequest(REQUEST_INVALIDATED); |
+ suggest_results_pending_ = 0; |
+ timer_.Stop(); |
+ // Stop any in-progress URL fetches. |
+ keyword_fetcher_.reset(); |
+ default_fetcher_.reset(); |
+} |
+ |
+void SearchProvider::ClearAllResults() { |
+ keyword_results_.Clear(); |
+ default_results_.Clear(); |
+} |
+ |
+int SearchProvider::GetDefaultRelevance() { return -1; } |
+ |
+const base::string16 SearchProvider::GetInputText( |
+ const net::URLFetcher* source) { |
+ return IsKeywordRequest(source) ? keyword_input_.text() : input_.text(); |
+} |
+ |
+bool SearchProvider::ShouldAllowNavSuggest(const net::URLFetcher* source) { |
+ // Prohibit navsuggest in FORCED_QUERY mode. Users wants queries, not URLs. |
+ return (IsKeywordRequest(source) ? keyword_input_.type() : input_.type()) != |
+ AutocompleteInput::FORCED_QUERY; |
+} |
+ |
+BaseSearchProvider::Results* SearchProvider::GetResultsObjectToFill( |
+ const net::URLFetcher* source) { |
+ return IsKeywordRequest(source) ? &keyword_results_ : &default_results_; |
+} |
+ |
+void SearchProvider::SortResults(const net::URLFetcher* source, |
+ const base::ListValue* relevances, |
+ Results* results) { |
+ // Ignore suggested scores for non-keyword matches in keyword mode; if the |
+ // server is allowed to score these, it could interfere with the user's |
+ // ability to get good keyword results. |
+ const bool abandon_suggested_scores = |
+ !IsKeywordRequest(source) && !providers_.keyword_provider().empty(); |
+ // Apply calculated relevance scores to suggestions if a valid list was |
+ // not provided or we're abandoning suggested scores entirely. |
+ |
+ if (relevances == NULL || abandon_suggested_scores) { |
+ ApplyCalculatedSuggestRelevance(&results->suggest_results); |
+ ApplyCalculatedNavigationRelevance(&results->navigation_results); |
+ // If abandoning scores entirely, also abandon the verbatim score. |
+ if (abandon_suggested_scores) |
+ results->verbatim_relevance = -1; |
+ } |
+ |
+ // Keep the result lists sorted. |
+ const CompareScoredResults comparator = CompareScoredResults(); |
+ std::stable_sort(results->suggest_results.begin(), |
+ results->suggest_results.end(), |
+ comparator); |
+ std::stable_sort(results->navigation_results.begin(), |
+ results->navigation_results.end(), |
+ comparator); |
+} |
+ |
+void SearchProvider::UpdateMatches() { |
+ base::TimeTicks update_matches_start_time(base::TimeTicks::Now()); |
+ ConvertResultsToAutocompleteMatches(); |
+ |
+ // Check constraints that may be violated by suggested relevances. |
+ if (!matches_.empty() && (default_results_.HasServerProvidedScores() || |
+ keyword_results_.HasServerProvidedScores())) { |
+ // These blocks attempt to repair undesirable behavior by suggested |
+ // relevances with minimal impact, preserving other suggested relevances. |
+ |
+ // True if the omnibox will reorder matches as necessary to make the first |
+ // one something that is allowed to be the default match. |
+ const bool omnibox_will_reorder_for_legal_default_match = |
+ OmniboxFieldTrial::ReorderForLegalDefaultMatch( |
+ input_.current_page_classification()); |
+ if (IsTopMatchNavigationInKeywordMode( |
+ omnibox_will_reorder_for_legal_default_match)) { |
+ // Correct the suggested relevance scores if the top match is a |
+ // navigation in keyword mode, since inlining a navigation match |
+ // would break the user out of keyword mode. This will only be |
+ // triggered in regular (non-reorder) mode; in reorder mode, |
+ // navigation matches are marked as not allowed to be the default |
+ // match and hence IsTopMatchNavigation() will always return false. |
+ DCHECK(!omnibox_will_reorder_for_legal_default_match); |
+ DemoteKeywordNavigationMatchesPastTopQuery(); |
+ ConvertResultsToAutocompleteMatches(); |
+ DCHECK(!IsTopMatchNavigationInKeywordMode( |
+ omnibox_will_reorder_for_legal_default_match)); |
+ } |
+ if (!HasKeywordDefaultMatchInKeywordMode()) { |
+ // In keyword mode, disregard the keyword verbatim suggested relevance |
+ // if necessary so there at least one keyword match that's allowed to |
+ // be the default match. |
+ keyword_results_.verbatim_relevance = -1; |
+ ConvertResultsToAutocompleteMatches(); |
+ } |
+ if (IsTopMatchScoreTooLow(omnibox_will_reorder_for_legal_default_match)) { |
+ // Disregard the suggested verbatim relevance if the top score is below |
+ // the usual verbatim value. For example, a BarProvider may rely on |
+ // SearchProvider's verbatim or inlineable matches for input "foo" (all |
+ // allowed to be default match) to always outrank its own lowly-ranked |
+ // "bar" matches that shouldn't be the default match. |
+ default_results_.verbatim_relevance = -1; |
+ keyword_results_.verbatim_relevance = -1; |
+ ConvertResultsToAutocompleteMatches(); |
+ } |
+ if (IsTopMatchSearchWithURLInput( |
+ omnibox_will_reorder_for_legal_default_match)) { |
+ // Disregard the suggested search and verbatim relevances if the input |
+ // type is URL and the top match is a highly-ranked search suggestion. |
+ // For example, prevent a search for "foo.com" from outranking another |
+ // provider's navigation for "foo.com" or "foo.com/url_from_history". |
+ ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results); |
+ ApplyCalculatedSuggestRelevance(&default_results_.suggest_results); |
+ default_results_.verbatim_relevance = -1; |
+ keyword_results_.verbatim_relevance = -1; |
+ ConvertResultsToAutocompleteMatches(); |
+ } |
+ if (!HasValidDefaultMatch(omnibox_will_reorder_for_legal_default_match)) { |
+ // If the omnibox is not going to reorder results to put a legal default |
+ // match at the top, then this provider needs to guarantee that its top |
+ // scoring result is a legal default match (i.e., it's either a verbatim |
+ // match or inlinable). For example, input "foo" should not invoke a |
+ // search for "bar", which would happen if the "bar" search match |
+ // outranked all other matches. On the other hand, if the omnibox will |
+ // reorder matches as necessary to put a legal default match at the top, |
+ // all we need to guarantee is that SearchProvider returns a legal |
+ // default match. (The omnibox always needs at least one legal default |
+ // match, and it relies on SearchProvider to always return one.) |
+ ApplyCalculatedRelevance(); |
+ ConvertResultsToAutocompleteMatches(); |
+ } |
+ DCHECK(!IsTopMatchNavigationInKeywordMode( |
+ omnibox_will_reorder_for_legal_default_match)); |
+ DCHECK(HasKeywordDefaultMatchInKeywordMode()); |
+ DCHECK( |
+ !IsTopMatchScoreTooLow(omnibox_will_reorder_for_legal_default_match)); |
+ DCHECK(!IsTopMatchSearchWithURLInput( |
+ omnibox_will_reorder_for_legal_default_match)); |
+ DCHECK(HasValidDefaultMatch(omnibox_will_reorder_for_legal_default_match)); |
+ } |
+ |
+ const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); |
+ if ((keyword_url != NULL) && HasKeywordDefaultMatchInKeywordMode()) { |
+ // If there is a keyword match that is allowed to be the default match, |
+ // then prohibit default provider matches from being the default match lest |
+ // such matches cause the user to break out of keyword mode. |
+ for (ACMatches::iterator it = matches_.begin(); it != matches_.end(); |
+ ++it) { |
+ if (it->keyword != keyword_url->keyword()) |
+ it->allowed_to_be_default_match = false; |
} |
} |
- listener_->OnProviderUpdate(true); |
+ |
+ base::TimeTicks update_starred_start_time(base::TimeTicks::Now()); |
+ UpdateStarredStateOfMatches(); |
+ UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.UpdateStarredTime", |
+ base::TimeTicks::Now() - update_starred_start_time); |
+ UpdateDone(); |
+ UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.UpdateMatchesTime", |
+ base::TimeTicks::Now() - update_matches_start_time); |
+} |
+ |
+bool SearchProvider::ShouldSendProviderUpdate(bool results_updated) { |
+ return done_ || results_updated; |
} |
void SearchProvider::Run() { |
@@ -830,10 +533,14 @@ void SearchProvider::Run() { |
suggest_results_pending_ = 0; |
time_suggest_request_sent_ = base::TimeTicks::Now(); |
- default_fetcher_.reset(CreateSuggestFetcher(kDefaultProviderURLFetcherID, |
- providers_.GetDefaultProviderURL(), input_)); |
- keyword_fetcher_.reset(CreateSuggestFetcher(kKeywordProviderURLFetcherID, |
- providers_.GetKeywordProviderURL(), keyword_input_)); |
+ default_fetcher_.reset( |
+ CreateSuggestFetcher(kDefaultProviderURLFetcherID, |
+ providers_.GetDefaultProviderURL(), |
+ input_)); |
+ keyword_fetcher_.reset( |
+ CreateSuggestFetcher(kKeywordProviderURLFetcherID, |
+ providers_.GetKeywordProviderURL(), |
+ keyword_input_)); |
// Both the above can fail if the providers have been modified or deleted |
// since the query began. |
@@ -867,8 +574,8 @@ void SearchProvider::DoHistoryQuery(bool minimal_changes) { |
UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.GetHistoryServiceTime", |
now - start_time); |
start_time = now; |
- history::URLDatabase* url_db = history_service ? |
- history_service->InMemoryDatabase() : NULL; |
+ history::URLDatabase* url_db = |
+ history_service ? history_service->InMemoryDatabase() : NULL; |
UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.InMemoryDatabaseTime", |
base::TimeTicks::Now() - start_time); |
if (!url_db) |
@@ -887,8 +594,10 @@ void SearchProvider::DoHistoryQuery(bool minimal_changes) { |
const TemplateURL* default_url = providers_.GetDefaultProviderURL(); |
if (default_url) { |
start_time = base::TimeTicks::Now(); |
- url_db->GetMostRecentKeywordSearchTerms(default_url->id(), input_.text(), |
- num_matches, &default_history_results_); |
+ url_db->GetMostRecentKeywordSearchTerms(default_url->id(), |
+ input_.text(), |
+ num_matches, |
+ &default_history_results_); |
UMA_HISTOGRAM_TIMES( |
"Omnibox.SearchProvider.GetMostRecentKeywordTermsDefaultProviderTime", |
base::TimeTicks::Now() - start_time); |
@@ -896,7 +605,9 @@ void SearchProvider::DoHistoryQuery(bool minimal_changes) { |
const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); |
if (keyword_url) { |
url_db->GetMostRecentKeywordSearchTerms(keyword_url->id(), |
- keyword_input_.text(), num_matches, &keyword_history_results_); |
+ keyword_input_.text(), |
+ num_matches, |
+ &keyword_history_results_); |
} |
UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.DoHistoryQueryTime", |
base::TimeTicks::Now() - do_history_query_start_time); |
@@ -912,13 +623,12 @@ void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) { |
// For the minimal_changes case, if we finished the previous query and still |
// have its results, or are allowed to keep running it, just do that, rather |
// than starting a new query. |
- if (minimal_changes && |
- (!default_results_.suggest_results.empty() || |
- !default_results_.navigation_results.empty() || |
- !keyword_results_.suggest_results.empty() || |
- !keyword_results_.navigation_results.empty() || |
- (!done_ && |
- input_.matches_requested() == AutocompleteInput::ALL_MATCHES))) |
+ if (minimal_changes && (!default_results_.suggest_results.empty() || |
+ !default_results_.navigation_results.empty() || |
+ !keyword_results_.suggest_results.empty() || |
+ !keyword_results_.navigation_results.empty() || |
+ (!done_ && input_.matches_requested() == |
+ AutocompleteInput::ALL_MATCHES))) |
return; |
// We can't keep running any previous query, so halt it. |
@@ -939,7 +649,8 @@ void SearchProvider::StartOrStopSuggestQuery(bool minimal_changes) { |
// To avoid flooding the suggest server, don't send a query until at |
// least 100 ms since the last query. |
- base::TimeTicks next_suggest_time(time_suggest_request_sent_ + |
+ base::TimeTicks next_suggest_time( |
+ time_suggest_request_sent_ + |
base::TimeDelta::FromMilliseconds(kMinimumTimeBetweenSuggestQueriesMs)); |
base::TimeTicks now(base::TimeTicks::Now()); |
if (now >= next_suggest_time) { |
@@ -1008,23 +719,6 @@ bool SearchProvider::IsQuerySuitableForSuggest() const { |
return true; |
} |
-void SearchProvider::StopSuggest() { |
- // Increment the appropriate field in the histogram by the number of |
- // pending requests that were invalidated. |
- for (int i = 0; i < suggest_results_pending_; i++) |
- LogOmniboxSuggestRequest(REQUEST_INVALIDATED); |
- suggest_results_pending_ = 0; |
- timer_.Stop(); |
- // Stop any in-progress URL fetches. |
- keyword_fetcher_.reset(); |
- default_fetcher_.reset(); |
-} |
- |
-void SearchProvider::ClearAllResults() { |
- keyword_results_.Clear(); |
- default_results_.Clear(); |
-} |
- |
void SearchProvider::RemoveAllStaleResults() { |
// We only need to remove stale results (which ensures the top-scoring |
// match is inlineable) if the user is not in reorder mode. In reorder |
@@ -1099,14 +793,17 @@ net::URLFetcher* SearchProvider::CreateSuggestFetcher( |
TemplateURLRef::SearchTermsArgs search_term_args(input.text()); |
search_term_args.cursor_position = input.cursor_position(); |
search_term_args.page_classification = input.current_page_classification(); |
- GURL suggest_url(template_url->suggestions_url_ref().ReplaceSearchTerms( |
- search_term_args)); |
+ GURL suggest_url( |
+ template_url->suggestions_url_ref().ReplaceSearchTerms(search_term_args)); |
if (!suggest_url.is_valid()) |
return NULL; |
// Send the current page URL if user setting and URL requirements are met and |
// the user is in the field trial. |
- if (CanSendURL(current_page_url_, suggest_url, template_url, |
- input.current_page_classification(), profile_) && |
+ if (CanSendURL(current_page_url_, |
+ suggest_url, |
+ template_url, |
+ input.current_page_classification(), |
+ profile_) && |
OmniboxFieldTrial::InZeroSuggestAfterTypingFieldTrial()) { |
search_term_args.current_page_url = current_page_url_.spec(); |
// Create the suggest URL again with the current page URL. |
@@ -1130,177 +827,6 @@ net::URLFetcher* SearchProvider::CreateSuggestFetcher( |
return fetcher; |
} |
-scoped_ptr<base::Value> SearchProvider::DeserializeJsonData( |
- std::string json_data) { |
- // The JSON response should be an array. |
- for (size_t response_start_index = json_data.find("["), i = 0; |
- response_start_index != std::string::npos && i < 5; |
- response_start_index = json_data.find("[", 1), i++) { |
- // Remove any XSSI guards to allow for JSON parsing. |
- if (response_start_index > 0) |
- json_data.erase(0, response_start_index); |
- |
- JSONStringValueSerializer deserializer(json_data); |
- deserializer.set_allow_trailing_comma(true); |
- int error_code = 0; |
- scoped_ptr<base::Value> data(deserializer.Deserialize(&error_code, NULL)); |
- if (error_code == 0) |
- return data.Pass(); |
- } |
- return scoped_ptr<base::Value>(); |
-} |
- |
-bool SearchProvider::ParseSuggestResults(base::Value* root_val, |
- bool is_keyword) { |
- base::string16 query; |
- base::ListValue* root_list = NULL; |
- base::ListValue* results_list = NULL; |
- const base::string16& input_text = |
- is_keyword ? keyword_input_.text() : input_.text(); |
- if (!root_val->GetAsList(&root_list) || !root_list->GetString(0, &query) || |
- (query != input_text) || !root_list->GetList(1, &results_list)) |
- return false; |
- |
- // 3rd element: Description list. |
- base::ListValue* descriptions = NULL; |
- root_list->GetList(2, &descriptions); |
- |
- // 4th element: Disregard the query URL list for now. |
- |
- // Reset suggested relevance information from the default provider. |
- Results* results = is_keyword ? &keyword_results_ : &default_results_; |
- results->verbatim_relevance = -1; |
- |
- // 5th element: Optional key-value pairs from the Suggest server. |
- base::ListValue* types = NULL; |
- base::ListValue* relevances = NULL; |
- base::ListValue* suggestion_details = NULL; |
- base::DictionaryValue* extras = NULL; |
- int prefetch_index = -1; |
- if (root_list->GetDictionary(4, &extras)) { |
- extras->GetList("google:suggesttype", &types); |
- |
- // Discard this list if its size does not match that of the suggestions. |
- if (extras->GetList("google:suggestrelevance", &relevances) && |
- (relevances->GetSize() != results_list->GetSize())) |
- relevances = NULL; |
- extras->GetInteger("google:verbatimrelevance", |
- &results->verbatim_relevance); |
- |
- // Check if the active suggest field trial (if any) has triggered either |
- // for the default provider or keyword provider. |
- bool triggered = false; |
- extras->GetBoolean("google:fieldtrialtriggered", &triggered); |
- field_trial_triggered_ |= triggered; |
- field_trial_triggered_in_session_ |= triggered; |
- |
- base::DictionaryValue* client_data = NULL; |
- if (extras->GetDictionary("google:clientdata", &client_data) && client_data) |
- client_data->GetInteger("phi", &prefetch_index); |
- |
- if (extras->GetList("google:suggestdetail", &suggestion_details) && |
- suggestion_details->GetSize() != results_list->GetSize()) |
- suggestion_details = NULL; |
- |
- // Store the metadata that came with the response in case we need to pass it |
- // along with the prefetch query to Instant. |
- JSONStringValueSerializer json_serializer(&results->metadata); |
- json_serializer.Serialize(*extras); |
- } |
- |
- // Clear the previous results now that new results are available. |
- results->suggest_results.clear(); |
- results->navigation_results.clear(); |
- |
- base::string16 suggestion; |
- std::string type; |
- int relevance = -1; |
- // Prohibit navsuggest in FORCED_QUERY mode. Users wants queries, not URLs. |
- const bool allow_navsuggest = |
- (is_keyword ? keyword_input_.type() : input_.type()) != |
- AutocompleteInput::FORCED_QUERY; |
- const std::string languages( |
- profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); |
- for (size_t index = 0; results_list->GetString(index, &suggestion); ++index) { |
- // Google search may return empty suggestions for weird input characters, |
- // they make no sense at all and can cause problems in our code. |
- if (suggestion.empty()) |
- continue; |
- |
- // Apply valid suggested relevance scores; discard invalid lists. |
- if (relevances != NULL && !relevances->GetInteger(index, &relevance)) |
- relevances = NULL; |
- if (types && types->GetString(index, &type) && (type == "NAVIGATION")) { |
- // Do not blindly trust the URL coming from the server to be valid. |
- GURL url(URLFixerUpper::FixupURL( |
- base::UTF16ToUTF8(suggestion), std::string())); |
- if (url.is_valid() && allow_navsuggest) { |
- base::string16 title; |
- if (descriptions != NULL) |
- descriptions->GetString(index, &title); |
- results->navigation_results.push_back(NavigationResult( |
- *this, url, title, is_keyword, relevance, true, input_text, |
- languages)); |
- } |
- } else { |
- AutocompleteMatchType::Type match_type = GetAutocompleteMatchType(type); |
- bool should_prefetch = static_cast<int>(index) == prefetch_index; |
- base::DictionaryValue* suggestion_detail = NULL; |
- base::string16 match_contents = suggestion; |
- base::string16 annotation; |
- std::string suggest_query_params; |
- std::string deletion_url; |
- |
- if (suggestion_details) { |
- suggestion_details->GetDictionary(index, &suggestion_detail); |
- if (suggestion_detail) { |
- suggestion_detail->GetString("du", &deletion_url); |
- suggestion_detail->GetString("title", &match_contents) || |
- suggestion_detail->GetString("t", &match_contents); |
- // Error correction for bad data from server. |
- if (match_contents.empty()) |
- match_contents = suggestion; |
- suggestion_detail->GetString("annotation", &annotation) || |
- suggestion_detail->GetString("a", &annotation); |
- suggestion_detail->GetString("query_params", &suggest_query_params) || |
- suggestion_detail->GetString("q", &suggest_query_params); |
- } |
- } |
- |
- // TODO(kochi): Improve calculator suggestion presentation. |
- results->suggest_results.push_back(SuggestResult( |
- suggestion, match_type, match_contents, annotation, |
- suggest_query_params, deletion_url, is_keyword, relevance, true, |
- should_prefetch, input_text)); |
- } |
- } |
- |
- // Ignore suggested scores for non-keyword matches in keyword mode; if the |
- // server is allowed to score these, it could interfere with the user's |
- // ability to get good keyword results. |
- const bool abandon_suggested_scores = |
- !is_keyword && !providers_.keyword_provider().empty(); |
- // Apply calculated relevance scores to suggestions if a valid list was |
- // not provided or we're abandoning suggested scores entirely. |
- if ((relevances == NULL) || abandon_suggested_scores) { |
- ApplyCalculatedSuggestRelevance(&results->suggest_results); |
- ApplyCalculatedNavigationRelevance(&results->navigation_results); |
- // If abandoning scores entirely, also abandon the verbatim score. |
- if (abandon_suggested_scores) |
- results->verbatim_relevance = -1; |
- } |
- |
- // Keep the result lists sorted. |
- const CompareScoredResults comparator = CompareScoredResults(); |
- std::stable_sort(results->suggest_results.begin(), |
- results->suggest_results.end(), |
- comparator); |
- std::stable_sort(results->navigation_results.begin(), |
- results->navigation_results.end(), |
- comparator); |
- return true; |
-} |
- |
void SearchProvider::ConvertResultsToAutocompleteMatches() { |
// Convert all the results to matches and add them to a map, so we can keep |
// the most relevant match for each result. |
@@ -1308,23 +834,36 @@ void SearchProvider::ConvertResultsToAutocompleteMatches() { |
MatchMap map; |
const base::Time no_time; |
int did_not_accept_keyword_suggestion = |
- keyword_results_.suggest_results.empty() ? |
- TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : |
- TemplateURLRef::NO_SUGGESTION_CHOSEN; |
+ keyword_results_.suggest_results.empty() |
+ ? TemplateURLRef::NO_SUGGESTIONS_AVAILABLE |
+ : TemplateURLRef::NO_SUGGESTION_CHOSEN; |
bool relevance_from_server; |
int verbatim_relevance = GetVerbatimRelevance(&relevance_from_server); |
int did_not_accept_default_suggestion = |
- default_results_.suggest_results.empty() ? |
- TemplateURLRef::NO_SUGGESTIONS_AVAILABLE : |
- TemplateURLRef::NO_SUGGESTION_CHOSEN; |
+ default_results_.suggest_results.empty() |
+ ? TemplateURLRef::NO_SUGGESTIONS_AVAILABLE |
+ : TemplateURLRef::NO_SUGGESTION_CHOSEN; |
if (verbatim_relevance > 0) { |
- SuggestResult verbatim( |
- input_.text(), AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, |
- input_.text(), base::string16(), std::string(), std::string(), false, |
- verbatim_relevance, relevance_from_server, false, input_.text()); |
- AddMatchToMap(verbatim, input_.text(), std::string(), |
- did_not_accept_default_suggestion, &map); |
+ SuggestResult verbatim(input_.text(), |
+ AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED, |
+ input_.text(), |
+ base::string16(), |
+ std::string(), |
+ std::string(), |
+ false, |
+ verbatim_relevance, |
+ relevance_from_server, |
+ false, |
+ input_.text()); |
+ AddMatchToMap(verbatim, |
+ input_, |
+ input_.text(), |
+ GetTemplateURL(verbatim), |
+ std::string(), |
+ did_not_accept_default_suggestion, |
+ ShouldAppendExtraQueryParams(verbatim), |
+ &map); |
} |
if (!keyword_input_.text().empty()) { |
const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); |
@@ -1340,13 +879,25 @@ void SearchProvider::ConvertResultsToAutocompleteMatches() { |
const int keyword_verbatim_relevance = |
GetKeywordVerbatimRelevance(&keyword_relevance_from_server); |
if (keyword_verbatim_relevance > 0) { |
- SuggestResult verbatim( |
- keyword_input_.text(), AutocompleteMatchType::SEARCH_OTHER_ENGINE, |
- keyword_input_.text(), base::string16(), std::string(), |
- std::string(), true, keyword_verbatim_relevance, |
- keyword_relevance_from_server, false, keyword_input_.text()); |
- AddMatchToMap(verbatim, keyword_input_.text(), std::string(), |
- did_not_accept_keyword_suggestion, &map); |
+ SuggestResult verbatim(keyword_input_.text(), |
+ AutocompleteMatchType::SEARCH_OTHER_ENGINE, |
+ keyword_input_.text(), |
+ base::string16(), |
+ std::string(), |
+ std::string(), |
+ true, |
+ keyword_verbatim_relevance, |
+ keyword_relevance_from_server, |
+ false, |
+ keyword_input_.text()); |
+ AddMatchToMap(verbatim, |
+ keyword_input_, |
+ keyword_input_.text(), |
+ GetTemplateURL(verbatim), |
+ std::string(), |
+ did_not_accept_keyword_suggestion, |
+ ShouldAppendExtraQueryParams(verbatim), |
+ &map); |
} |
} |
} |
@@ -1424,8 +975,8 @@ bool SearchProvider::IsTopMatchNavigationInKeywordMode( |
ACMatches::const_iterator first_match = |
FindTopMatch(autocomplete_result_will_reorder_for_default_match); |
return !providers_.keyword_provider().empty() && |
- (first_match != matches_.end()) && |
- (first_match->type == AutocompleteMatchType::NAVSUGGEST); |
+ (first_match != matches_.end()) && |
+ (first_match->type == AutocompleteMatchType::NAVSUGGEST); |
} |
bool SearchProvider::HasKeywordDefaultMatchInKeywordMode() const { |
@@ -1459,7 +1010,7 @@ bool SearchProvider::IsTopMatchScoreTooLow( |
// that it will always provide an inlineable match with a reasonable |
// score. |
return matches_.front().relevance < |
- CalculateRelevanceForVerbatimIgnoringKeywordModeState(); |
+ CalculateRelevanceForVerbatimIgnoringKeywordModeState(); |
} |
bool SearchProvider::IsTopMatchSearchWithURLInput( |
@@ -1467,9 +1018,9 @@ bool SearchProvider::IsTopMatchSearchWithURLInput( |
ACMatches::const_iterator first_match = |
FindTopMatch(autocomplete_result_will_reorder_for_default_match); |
return (input_.type() == AutocompleteInput::URL) && |
- (first_match != matches_.end()) && |
- (first_match->relevance > CalculateRelevanceForVerbatim()) && |
- (first_match->type != AutocompleteMatchType::NAVSUGGEST); |
+ (first_match != matches_.end()) && |
+ (first_match->relevance > CalculateRelevanceForVerbatim()) && |
+ (first_match->type != AutocompleteMatchType::NAVSUGGEST); |
} |
bool SearchProvider::HasValidDefaultMatch( |
@@ -1489,115 +1040,12 @@ bool SearchProvider::HasValidDefaultMatch( |
return false; |
} |
-void SearchProvider::UpdateMatches() { |
- base::TimeTicks update_matches_start_time(base::TimeTicks::Now()); |
- ConvertResultsToAutocompleteMatches(); |
- |
- // Check constraints that may be violated by suggested relevances. |
- if (!matches_.empty() && |
- (default_results_.HasServerProvidedScores() || |
- keyword_results_.HasServerProvidedScores())) { |
- // These blocks attempt to repair undesirable behavior by suggested |
- // relevances with minimal impact, preserving other suggested relevances. |
- |
- // True if the omnibox will reorder matches as necessary to make the first |
- // one something that is allowed to be the default match. |
- const bool omnibox_will_reorder_for_legal_default_match = |
- OmniboxFieldTrial::ReorderForLegalDefaultMatch( |
- input_.current_page_classification()); |
- if (IsTopMatchNavigationInKeywordMode( |
- omnibox_will_reorder_for_legal_default_match)) { |
- // Correct the suggested relevance scores if the top match is a |
- // navigation in keyword mode, since inlining a navigation match |
- // would break the user out of keyword mode. This will only be |
- // triggered in regular (non-reorder) mode; in reorder mode, |
- // navigation matches are marked as not allowed to be the default |
- // match and hence IsTopMatchNavigation() will always return false. |
- DCHECK(!omnibox_will_reorder_for_legal_default_match); |
- DemoteKeywordNavigationMatchesPastTopQuery(); |
- ConvertResultsToAutocompleteMatches(); |
- DCHECK(!IsTopMatchNavigationInKeywordMode( |
- omnibox_will_reorder_for_legal_default_match)); |
- } |
- if (!HasKeywordDefaultMatchInKeywordMode()) { |
- // In keyword mode, disregard the keyword verbatim suggested relevance |
- // if necessary so there at least one keyword match that's allowed to |
- // be the default match. |
- keyword_results_.verbatim_relevance = -1; |
- ConvertResultsToAutocompleteMatches(); |
- } |
- if (IsTopMatchScoreTooLow(omnibox_will_reorder_for_legal_default_match)) { |
- // Disregard the suggested verbatim relevance if the top score is below |
- // the usual verbatim value. For example, a BarProvider may rely on |
- // SearchProvider's verbatim or inlineable matches for input "foo" (all |
- // allowed to be default match) to always outrank its own lowly-ranked |
- // "bar" matches that shouldn't be the default match. |
- default_results_.verbatim_relevance = -1; |
- keyword_results_.verbatim_relevance = -1; |
- ConvertResultsToAutocompleteMatches(); |
- } |
- if (IsTopMatchSearchWithURLInput( |
- omnibox_will_reorder_for_legal_default_match)) { |
- // Disregard the suggested search and verbatim relevances if the input |
- // type is URL and the top match is a highly-ranked search suggestion. |
- // For example, prevent a search for "foo.com" from outranking another |
- // provider's navigation for "foo.com" or "foo.com/url_from_history". |
- ApplyCalculatedSuggestRelevance(&keyword_results_.suggest_results); |
- ApplyCalculatedSuggestRelevance(&default_results_.suggest_results); |
- default_results_.verbatim_relevance = -1; |
- keyword_results_.verbatim_relevance = -1; |
- ConvertResultsToAutocompleteMatches(); |
- } |
- if (!HasValidDefaultMatch(omnibox_will_reorder_for_legal_default_match)) { |
- // If the omnibox is not going to reorder results to put a legal default |
- // match at the top, then this provider needs to guarantee that its top |
- // scoring result is a legal default match (i.e., it's either a verbatim |
- // match or inlinable). For example, input "foo" should not invoke a |
- // search for "bar", which would happen if the "bar" search match |
- // outranked all other matches. On the other hand, if the omnibox will |
- // reorder matches as necessary to put a legal default match at the top, |
- // all we need to guarantee is that SearchProvider returns a legal |
- // default match. (The omnibox always needs at least one legal default |
- // match, and it relies on SearchProvider to always return one.) |
- ApplyCalculatedRelevance(); |
- ConvertResultsToAutocompleteMatches(); |
- } |
- DCHECK(!IsTopMatchNavigationInKeywordMode( |
- omnibox_will_reorder_for_legal_default_match)); |
- DCHECK(HasKeywordDefaultMatchInKeywordMode()); |
- DCHECK(!IsTopMatchScoreTooLow( |
- omnibox_will_reorder_for_legal_default_match)); |
- DCHECK(!IsTopMatchSearchWithURLInput( |
- omnibox_will_reorder_for_legal_default_match)); |
- DCHECK(HasValidDefaultMatch(omnibox_will_reorder_for_legal_default_match)); |
- } |
- |
- const TemplateURL* keyword_url = providers_.GetKeywordProviderURL(); |
- if ((keyword_url != NULL) && HasKeywordDefaultMatchInKeywordMode()) { |
- // If there is a keyword match that is allowed to be the default match, |
- // then prohibit default provider matches from being the default match lest |
- // such matches cause the user to break out of keyword mode. |
- for (ACMatches::iterator it = matches_.begin(); it != matches_.end(); |
- ++it) { |
- if (it->keyword != keyword_url->keyword()) |
- it->allowed_to_be_default_match = false; |
- } |
- } |
- |
- base::TimeTicks update_starred_start_time(base::TimeTicks::Now()); |
- UpdateStarredStateOfMatches(); |
- UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.UpdateStarredTime", |
- base::TimeTicks::Now() - update_starred_start_time); |
- UpdateDone(); |
- UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.UpdateMatchesTime", |
- base::TimeTicks::Now() - update_matches_start_time); |
-} |
- |
void SearchProvider::AddNavigationResultsToMatches( |
const NavigationResults& navigation_results, |
ACMatches* matches) { |
for (NavigationResults::const_iterator it = navigation_results.begin(); |
- it != navigation_results.end(); ++it) { |
+ it != navigation_results.end(); |
+ ++it) { |
matches->push_back(NavigationToMatch(*it)); |
// In the absence of suggested relevance scores, use only the single |
// highest-scoring result. (The results are already sorted by relevance.) |
@@ -1615,7 +1063,7 @@ void SearchProvider::AddHistoryResultsToMap(const HistoryResults& results, |
base::TimeTicks start_time(base::TimeTicks::Now()); |
bool prevent_inline_autocomplete = input_.prevent_inline_autocomplete() || |
- (input_.type() == AutocompleteInput::URL); |
+ (input_.type() == AutocompleteInput::URL); |
const base::string16& input_text = |
is_keyword ? keyword_input_.text() : input_.text(); |
bool input_multiple_words = HasMultipleWords(input_text); |
@@ -1632,7 +1080,7 @@ void SearchProvider::AddHistoryResultsToMap(const HistoryResults& results, |
scored_results = ScoreHistoryResults(results, prevent_inline_autocomplete, |
false, input_text, is_keyword); |
if ((scored_results.front().relevance() < |
- AutocompleteResult::kLowestDefaultScore) || |
+ AutocompleteResult::kLowestDefaultScore) || |
!HasMultipleWords(scored_results.front().suggestion())) |
scored_results.clear(); // Didn't detect the case above, score normally. |
} |
@@ -1641,9 +1089,18 @@ void SearchProvider::AddHistoryResultsToMap(const HistoryResults& results, |
input_multiple_words, input_text, |
is_keyword); |
for (SuggestResults::const_iterator i(scored_results.begin()); |
- i != scored_results.end(); ++i) { |
- AddMatchToMap(*i, input_text, std::string(), |
- did_not_accept_suggestion, map); |
+ i != scored_results.end(); |
+ ++i) { |
+ AddMatchToMap( |
+ *i, |
+ is_keyword ? keyword_input_ : input_, |
+ input_text, |
+ i->from_keyword_provider() ? providers_.GetKeywordProviderURL() |
+ : providers_.GetDefaultProviderURL(), |
+ std::string(), |
+ did_not_accept_suggestion, |
+ !i->from_keyword_provider() || providers_.default_provider().empty(), |
+ map); |
} |
UMA_HISTOGRAM_TIMES("Omnibox.SearchProvider.AddHistoryResultsTime", |
base::TimeTicks::Now() - start_time); |
@@ -1665,7 +1122,8 @@ SearchProvider::SuggestResults SearchProvider::ScoreHistoryResults( |
++i) { |
// Don't autocomplete multi-word queries that have only been seen once |
// unless the user has typed more than one word. |
- bool prevent_inline_autocomplete = base_prevent_inline_autocomplete || |
+ bool prevent_inline_autocomplete = |
+ base_prevent_inline_autocomplete || |
(!input_multiple_words && (i->visits < 2) && HasMultipleWords(i->term)); |
// Don't autocomplete search terms that would normally be treated as URLs |
@@ -1691,10 +1149,18 @@ SearchProvider::SuggestResults SearchProvider::ScoreHistoryResults( |
int relevance = CalculateRelevanceForHistory( |
i->time, is_keyword, !prevent_inline_autocomplete, |
prevent_search_history_inlining); |
- scored_results.push_back(SuggestResult( |
- i->term, AutocompleteMatchType::SEARCH_HISTORY, i->term, |
- base::string16(), std::string(), std::string(), is_keyword, relevance, |
- false, false, input_text)); |
+ scored_results.push_back( |
+ SuggestResult(i->term, |
+ AutocompleteMatchType::SEARCH_HISTORY, |
+ i->term, |
+ base::string16(), |
+ std::string(), |
+ std::string(), |
+ is_keyword, |
+ relevance, |
+ false, |
+ false, |
+ input_text)); |
} |
// History returns results sorted for us. However, we may have docked some |
@@ -1706,7 +1172,8 @@ SearchProvider::SuggestResults SearchProvider::ScoreHistoryResults( |
CompareScoredResults()); |
int last_relevance = 0; |
for (SuggestResults::iterator i(scored_results.begin()); |
- i != scored_results.end(); ++i) { |
+ i != scored_results.end(); |
+ ++i) { |
if ((i != scored_results.begin()) && (i->relevance() >= last_relevance)) |
i->set_relevance(last_relevance - 1); |
last_relevance = i->relevance(); |
@@ -1720,12 +1187,29 @@ void SearchProvider::AddSuggestResultsToMap(const SuggestResults& results, |
MatchMap* map) { |
for (size_t i = 0; i < results.size(); ++i) { |
const bool is_keyword = results[i].from_keyword_provider(); |
- const base::string16& input = is_keyword ? keyword_input_.text() |
- : input_.text(); |
- AddMatchToMap(results[i], input, metadata, i, map); |
+ const base::string16& input = |
+ is_keyword ? keyword_input_.text() : input_.text(); |
+ AddMatchToMap(results[i], |
+ is_keyword ? keyword_input_ : input_, |
+ input, |
+ GetTemplateURL(results[i]), |
+ metadata, |
+ i, |
+ ShouldAppendExtraQueryParams(results[i]), |
+ map); |
} |
} |
+const TemplateURL* SearchProvider::GetTemplateURL(const SuggestResult& result) { |
+ return result.from_keyword_provider() ? providers_.GetKeywordProviderURL() |
+ : providers_.GetDefaultProviderURL(); |
+} |
+ |
+bool SearchProvider::ShouldAppendExtraQueryParams(const SuggestResult& result) { |
+ return !result.from_keyword_provider() || |
+ providers_.default_provider().empty(); |
+} |
+ |
int SearchProvider::GetVerbatimRelevance(bool* relevance_from_server) const { |
// Use the suggested verbatim relevance score if it is non-negative (valid), |
// if inline autocomplete isn't prevented (always show verbatim on backspace), |
@@ -1735,16 +1219,15 @@ int SearchProvider::GetVerbatimRelevance(bool* relevance_from_server) const { |
// left unable to search using their default provider from the omnibox. |
// Check for results on each verbatim calculation, as results from older |
// queries (on previous input) may be trimmed for failing to inline new input. |
- bool use_server_relevance = |
- (default_results_.verbatim_relevance >= 0) && |
- !input_.prevent_inline_autocomplete() && |
- ((default_results_.verbatim_relevance > 0) || |
- !default_results_.suggest_results.empty() || |
- !default_results_.navigation_results.empty()); |
+ bool use_server_relevance = (default_results_.verbatim_relevance >= 0) && |
+ !input_.prevent_inline_autocomplete() && |
+ ((default_results_.verbatim_relevance > 0) || |
+ !default_results_.suggest_results.empty() || |
+ !default_results_.navigation_results.empty()); |
if (relevance_from_server) |
*relevance_from_server = use_server_relevance; |
- return use_server_relevance ? |
- default_results_.verbatim_relevance : CalculateRelevanceForVerbatim(); |
+ return use_server_relevance ? default_results_.verbatim_relevance |
+ : CalculateRelevanceForVerbatim(); |
} |
int SearchProvider::CalculateRelevanceForVerbatim() const { |
@@ -1753,8 +1236,8 @@ int SearchProvider::CalculateRelevanceForVerbatim() const { |
return CalculateRelevanceForVerbatimIgnoringKeywordModeState(); |
} |
-int SearchProvider:: |
- CalculateRelevanceForVerbatimIgnoringKeywordModeState() const { |
+int SearchProvider::CalculateRelevanceForVerbatimIgnoringKeywordModeState() |
+ const { |
switch (input_.type()) { |
case AutocompleteInput::UNKNOWN: |
case AutocompleteInput::QUERY: |
@@ -1780,18 +1263,17 @@ int SearchProvider::GetKeywordVerbatimRelevance( |
// left unable to search using their keyword provider from the omnibox. |
// Check for results on each verbatim calculation, as results from older |
// queries (on previous input) may be trimmed for failing to inline new input. |
- bool use_server_relevance = |
- (keyword_results_.verbatim_relevance >= 0) && |
- !input_.prevent_inline_autocomplete() && |
- ((keyword_results_.verbatim_relevance > 0) || |
- !keyword_results_.suggest_results.empty() || |
- !keyword_results_.navigation_results.empty()); |
+ bool use_server_relevance = (keyword_results_.verbatim_relevance >= 0) && |
+ !input_.prevent_inline_autocomplete() && |
+ ((keyword_results_.verbatim_relevance > 0) || |
+ !keyword_results_.suggest_results.empty() || |
+ !keyword_results_.navigation_results.empty()); |
if (relevance_from_server) |
*relevance_from_server = use_server_relevance; |
- return use_server_relevance ? |
- keyword_results_.verbatim_relevance : |
- CalculateRelevanceForKeywordVerbatim(keyword_input_.type(), |
- keyword_input_.prefer_keyword()); |
+ return use_server_relevance |
+ ? keyword_results_.verbatim_relevance |
+ : CalculateRelevanceForKeywordVerbatim( |
+ keyword_input_.type(), keyword_input_.prefer_keyword()); |
} |
int SearchProvider::CalculateRelevanceForHistory( |
@@ -1815,8 +1297,9 @@ int SearchProvider::CalculateRelevanceForHistory( |
int max_score = is_keyword ? 1599 : 1399; |
if (prevent_search_history_inlining) |
max_score = 1299; |
- return max_score - static_cast<int>(99 * |
- std::pow(elapsed_time / autocomplete_time, 2.5)); |
+ return max_score - |
+ static_cast<int>(99 * |
+ std::pow(elapsed_time / autocomplete_time, 2.5)); |
} |
elapsed_time -= autocomplete_time; |
} |
@@ -1834,100 +1317,11 @@ int SearchProvider::CalculateRelevanceForHistory( |
return std::max(0, base_score - score_discount); |
} |
-void SearchProvider::AddMatchToMap(const SuggestResult& result, |
- const base::string16& input_text, |
- const std::string& metadata, |
- int accepted_suggestion, |
- MatchMap* map) { |
- // On non-mobile, ask the instant controller for the appropriate start margin. |
- // On mobile the start margin is unused, so leave the value as default there. |
- int omnibox_start_margin = chrome::kDisableStartMargin; |
-#if !defined(OS_ANDROID) && !defined(IOS) |
- if (chrome::IsInstantExtendedAPIEnabled()) { |
- Browser* browser = |
- chrome::FindBrowserWithProfile(profile_, chrome::GetActiveDesktop()); |
- if (browser && browser->instant_controller() && |
- browser->instant_controller()->instant()) { |
- omnibox_start_margin = |
- browser->instant_controller()->instant()->omnibox_bounds().x(); |
- } |
- } |
-#endif // !defined(OS_ANDROID) && !defined(IOS) |
- |
- const TemplateURL* template_url = result.from_keyword_provider() ? |
- providers_.GetKeywordProviderURL() : providers_.GetDefaultProviderURL(); |
- AutocompleteMatch match = CreateSearchSuggestion( |
- this, input_, input_text, result, template_url, accepted_suggestion, |
- omnibox_start_margin, |
- !result.from_keyword_provider() || providers_.default_provider().empty()); |
- if (!match.destination_url.is_valid()) |
- return; |
- match.search_terms_args->bookmark_bar_pinned = |
- profile_->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar); |
- match.RecordAdditionalInfo(kRelevanceFromServerKey, |
- result.relevance_from_server() ? kTrue : kFalse); |
- match.RecordAdditionalInfo(kShouldPrefetchKey, |
- result.should_prefetch() ? kTrue : kFalse); |
- |
- if (!result.deletion_url().empty()) { |
- GURL url(match.destination_url.GetOrigin().Resolve(result.deletion_url())); |
- if (url.is_valid()) { |
- match.RecordAdditionalInfo(kDeletionUrlKey, url.spec()); |
- match.deletable = true; |
- } |
- } |
- |
- // Metadata is needed only for prefetching queries. |
- if (result.should_prefetch()) |
- match.RecordAdditionalInfo(kSuggestMetadataKey, metadata); |
- |
- // 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. |
- MatchKey match_key( |
- std::make_pair(base::i18n::ToLower(result.suggestion()), |
- match.search_terms_args->suggest_query_params)); |
- const std::pair<MatchMap::iterator, bool> i( |
- map->insert(std::make_pair(match_key, match))); |
- |
- bool should_prefetch = result.should_prefetch(); |
- if (!i.second) { |
- // NOTE: We purposefully do a direct relevance comparison here instead of |
- // using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items |
- // added first" rather than "items alphabetically first" when the scores are |
- // equal. The only case this matters is when a user has results with the |
- // same score that differ only by capitalization; because the history system |
- // returns results sorted by recency, this means we'll pick the most |
- // recent such result even if the precision of our relevance score is too |
- // low to distinguish the two. |
- if (match.relevance > i.first->second.relevance) { |
- i.first->second = match; |
- } else if (match.keyword == i.first->second.keyword) { |
- // Old and new matches are from the same search provider. It is okay to |
- // record one match's prefetch data onto a different match (for the same |
- // query string) for the following reasons: |
- // 1. Because the suggest server only sends down a query string from which |
- // we construct a URL, rather than sending a full URL, and because we |
- // construct URLs from query strings in the same way every time, the URLs |
- // for the two matches will be the same. Therefore, we won't end up |
- // prefetching something the server didn't intend. |
- // 2. Presumably the server sets the prefetch bit on a match it things is |
- // sufficiently relevant that the user is likely to choose it. Surely |
- // setting the prefetch bit on a match of even higher relevance won't |
- // violate this assumption. |
- should_prefetch |= ShouldPrefetch(i.first->second); |
- i.first->second.RecordAdditionalInfo(kShouldPrefetchKey, |
- should_prefetch ? kTrue : kFalse); |
- if (should_prefetch) |
- i.first->second.RecordAdditionalInfo(kSuggestMetadataKey, metadata); |
- } |
- } |
-} |
- |
AutocompleteMatch SearchProvider::NavigationToMatch( |
const NavigationResult& navigation) { |
- const base::string16& input = navigation.from_keyword_provider() ? |
- keyword_input_.text() : input_.text(); |
+ const base::string16& input = navigation.from_keyword_provider() |
+ ? keyword_input_.text() |
+ : input_.text(); |
AutocompleteMatch match(this, navigation.relevance(), false, |
AutocompleteMatchType::NAVSUGGEST); |
match.destination_url = navigation.url(); |
@@ -1949,9 +1343,14 @@ AutocompleteMatch SearchProvider::NavigationToMatch( |
size_t inline_autocomplete_offset = (prefix == NULL) ? |
base::string16::npos : (match_start + input.length()); |
match.fill_into_edit += |
- AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(), |
- net::FormatUrl(navigation.url(), languages, format_types, |
- net::UnescapeRule::SPACES, NULL, NULL, |
+ AutocompleteInput::FormattedStringWithEquivalentMeaning( |
+ navigation.url(), |
+ net::FormatUrl(navigation.url(), |
+ languages, |
+ format_types, |
+ net::UnescapeRule::SPACES, |
+ NULL, |
+ NULL, |
&inline_autocomplete_offset)); |
// Preserve the forced query '?' prefix in |match.fill_into_edit|. |
// Otherwise, user edits to a suggestion would show non-Search results. |
@@ -1975,8 +1374,10 @@ AutocompleteMatch SearchProvider::NavigationToMatch( |
match.contents = navigation.match_contents(); |
match.contents_class = navigation.match_contents_class(); |
match.description = navigation.description(); |
- AutocompleteMatch::ClassifyMatchInString(input, match.description, |
- ACMatchClassification::NONE, &match.description_class); |
+ AutocompleteMatch::ClassifyMatchInString(input, |
+ match.description, |
+ ACMatchClassification::NONE, |
+ &match.description_class); |
match.RecordAdditionalInfo( |
kRelevanceFromServerKey, |
@@ -2018,7 +1419,8 @@ void SearchProvider::DemoteKeywordNavigationMatchesPastTopQuery() { |
// Cap the relevance score of all results. |
for (NavigationResults::iterator it = |
keyword_results_.navigation_results.begin(); |
- it != keyword_results_.navigation_results.end(); ++it) { |
+ it != keyword_results_.navigation_results.end(); |
+ ++it) { |
if (it->relevance() < max_query_relevance) |
return; |
max_query_relevance = std::max(max_query_relevance - 1, 0); |
@@ -2033,65 +1435,3 @@ void SearchProvider::UpdateDone() { |
done_ = !timer_.IsRunning() && (suggest_results_pending_ == 0); |
} |
-bool SearchProvider::CanSendURL( |
- const GURL& current_page_url, |
- const GURL& suggest_url, |
- const TemplateURL* template_url, |
- AutocompleteInput::PageClassification page_classification, |
- Profile* profile) { |
- if (!current_page_url.is_valid()) |
- return false; |
- |
- // TODO(hfung): Show Most Visited on NTP with appropriate verbatim |
- // description when the user actively focuses on the omnibox as discussed in |
- // crbug/305366 if Most Visited (or something similar) will launch. |
- if ((page_classification == |
- AutocompleteInput::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS) || |
- (page_classification == |
- AutocompleteInput::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS)) |
- return false; |
- |
- // Only allow HTTP URLs or HTTPS URLs for the same domain as the search |
- // provider. |
- if ((current_page_url.scheme() != content::kHttpScheme) && |
- ((current_page_url.scheme() != content::kHttpsScheme) || |
- !net::registry_controlled_domains::SameDomainOrHost( |
- current_page_url, suggest_url, |
- net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES))) |
- return false; |
- |
- // Make sure we are sending the suggest request through HTTPS to prevent |
- // exposing the current page URL to networks before the search provider. |
- if (!suggest_url.SchemeIs(content::kHttpsScheme)) |
- return false; |
- |
- // Don't run if there's no profile or in incognito mode. |
- if (profile == NULL || profile->IsOffTheRecord()) |
- return false; |
- |
- // Don't run if we can't get preferences or search suggest is not enabled. |
- PrefService* prefs = profile->GetPrefs(); |
- if (!prefs->GetBoolean(prefs::kSearchSuggestEnabled)) |
- return false; |
- |
- // Only make the request if we know that the provider supports zero suggest |
- // (currently only the prepopulated Google provider). |
- if (template_url == NULL || !template_url->SupportsReplacement() || |
- TemplateURLPrepopulateData::GetEngineType(*template_url) != |
- SEARCH_ENGINE_GOOGLE) |
- return false; |
- |
- // Check field trials and settings allow sending the URL on suggest requests. |
- ProfileSyncService* service = |
- ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile); |
- browser_sync::SyncPrefs sync_prefs(prefs); |
- if (!OmniboxFieldTrial::InZeroSuggestFieldTrial() || |
- service == NULL || |
- !service->IsSyncEnabledAndLoggedIn() || |
- !sync_prefs.GetPreferredDataTypes(syncer::UserTypes()).Has( |
- syncer::PROXY_TABS) || |
- service->GetEncryptedDataTypes().Has(syncer::SESSIONS)) |
- return false; |
- |
- return true; |
-} |