| Index: chrome/browser/autocomplete/base_search_provider.cc
|
| diff --git a/chrome/browser/autocomplete/base_search_provider.cc b/chrome/browser/autocomplete/base_search_provider.cc
|
| index bb60179625cf07bff618a609b9f925700fabad17..eabd8a4f4c26c1941721e9db94c1a1cdbbf5da09 100644
|
| --- a/chrome/browser/autocomplete/base_search_provider.cc
|
| +++ b/chrome/browser/autocomplete/base_search_provider.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #include "chrome/browser/autocomplete/base_search_provider.h"
|
|
|
| +#include "base/i18n/case_conversion.h"
|
| #include "base/json/json_string_value_serializer.h"
|
| #include "base/prefs/pref_service.h"
|
| #include "base/strings/string_util.h"
|
| @@ -12,6 +13,9 @@
|
| #include "chrome/browser/autocomplete/url_prefix.h"
|
| #include "chrome/browser/omnibox/omnibox_field_trial.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/browser/search/instant_service.h"
|
| +#include "chrome/browser/search/instant_service_factory.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/sync/profile_sync_service.h"
|
| @@ -33,6 +37,11 @@ BaseSearchProvider::BaseSearchProvider(AutocompleteProviderListener* listener,
|
| field_trial_triggered_(false),
|
| field_trial_triggered_in_session_(false) {}
|
|
|
| +// static
|
| +bool BaseSearchProvider::ShouldPrefetch(const AutocompleteMatch& match) {
|
| + return match.GetAdditionalInfo(kShouldPrefetchKey) == kTrue;
|
| +}
|
| +
|
| void BaseSearchProvider::AddProviderInfo(ProvidersInfo* provider_info) const {
|
| provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo());
|
| metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back();
|
| @@ -50,6 +59,15 @@ void BaseSearchProvider::AddProviderInfo(ProvidersInfo* provider_info) const {
|
| }
|
| }
|
|
|
| +// static
|
| +const char BaseSearchProvider::kRelevanceFromServerKey[] =
|
| + "relevance_from_server";
|
| +const char BaseSearchProvider::kShouldPrefetchKey[] = "should_prefetch";
|
| +const char BaseSearchProvider::kSuggestMetadataKey[] = "suggest_metadata";
|
| +const char BaseSearchProvider::kDeletionUrlKey[] = "deletion_url";
|
| +const char BaseSearchProvider::kTrue[] = "true";
|
| +const char BaseSearchProvider::kFalse[] = "false";
|
| +
|
| BaseSearchProvider::~BaseSearchProvider() {}
|
|
|
| // BaseSearchProvider::Result --------------------------------------------------
|
| @@ -258,7 +276,6 @@ bool BaseSearchProvider::Results::HasServerProvidedScores() const {
|
| AutocompleteMatch BaseSearchProvider::CreateSearchSuggestion(
|
| AutocompleteProvider* autocomplete_provider,
|
| const AutocompleteInput& input,
|
| - const base::string16& input_text,
|
| const SuggestResult& suggestion,
|
| const TemplateURL* template_url,
|
| int accepted_suggestion,
|
| @@ -277,7 +294,7 @@ AutocompleteMatch BaseSearchProvider::CreateSearchSuggestion(
|
| match.description = suggestion.annotation();
|
|
|
| match.allowed_to_be_default_match =
|
| - (input_text == suggestion.match_contents());
|
| + (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
|
| @@ -287,9 +304,9 @@ AutocompleteMatch BaseSearchProvider::CreateSearchSuggestion(
|
| 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)) {
|
| + StartsWith(suggestion.suggestion(), input.text(), false)) {
|
| match.inline_autocompletion =
|
| - suggestion.suggestion().substr(input_text.length());
|
| + suggestion.suggestion().substr(input.text().length());
|
| match.allowed_to_be_default_match = true;
|
| }
|
| match.fill_into_edit.append(suggestion.suggestion());
|
| @@ -298,7 +315,7 @@ AutocompleteMatch BaseSearchProvider::CreateSearchSuggestion(
|
| 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->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 =
|
| @@ -403,3 +420,80 @@ bool BaseSearchProvider::CanSendURL(
|
| return true;
|
| }
|
|
|
| +void BaseSearchProvider::AddMatchToMap(const SuggestResult& result,
|
| + const std::string& metadata,
|
| + int accepted_suggestion,
|
| + MatchMap* map) {
|
| + InstantService* instant_service =
|
| + InstantServiceFactory::GetForProfile(profile_);
|
| + // Android and iOS have no InstantService.
|
| + const int omnibox_start_margin = instant_service ?
|
| + instant_service->omnibox_start_margin() : chrome::kDisableStartMargin;
|
| +
|
| + AutocompleteMatch match = CreateSearchSuggestion(
|
| + this, GetInput(result), result, GetTemplateURL(result),
|
| + accepted_suggestion, omnibox_start_margin,
|
| + ShouldAppendExtraParams(result));
|
| + 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 this suggestion 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);
|
| + }
|
| + }
|
| +}
|
|
|