Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(186)

Unified Diff: chrome/browser/autocomplete/base_search_provider.cc

Issue 489353004: Componentize SearchProvider (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/autocomplete/base_search_provider.h ('k') | chrome/browser/autocomplete/search_provider.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
deleted file mode 100644
index 71a7049af8c21744fdcd2e55b9e3f581494bf4dc..0000000000000000000000000000000000000000
--- a/chrome/browser/autocomplete/base_search_provider.cc
+++ /dev/null
@@ -1,463 +0,0 @@
-// 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/i18n/case_conversion.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "components/metrics/proto/omnibox_event.pb.h"
-#include "components/metrics/proto/omnibox_input_type.pb.h"
-#include "components/omnibox/autocomplete_provider_delegate.h"
-#include "components/omnibox/autocomplete_provider_listener.h"
-#include "components/omnibox/omnibox_field_trial.h"
-#include "components/search_engines/template_url.h"
-#include "components/search_engines/template_url_prepopulate_data.h"
-#include "components/search_engines/template_url_service.h"
-#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_fetcher_delegate.h"
-#include "url/gurl.h"
-
-using metrics::OmniboxEventProto;
-
-// 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,
- net::URLRequestContextGetter* request_context,
- 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,
- net::URLRequestContextGetter* request_context,
- const DeletionCompletedCallback& callback) : callback_(callback) {
- GURL url(deletion_url);
- DCHECK(url.is_valid());
-
- deletion_fetcher_.reset(net::URLFetcher::Create(
- BaseSearchProvider::kDeletionURLFetcherID,
- url,
- net::URLFetcher::GET,
- this));
- deletion_fetcher_->SetRequestContext(request_context);
- 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);
-}
-
-// BaseSearchProvider ---------------------------------------------------------
-
-// static
-const int BaseSearchProvider::kDefaultProviderURLFetcherID = 1;
-const int BaseSearchProvider::kKeywordProviderURLFetcherID = 2;
-const int BaseSearchProvider::kDeletionURLFetcherID = 3;
-
-BaseSearchProvider::BaseSearchProvider(
- TemplateURLService* template_url_service,
- scoped_ptr<AutocompleteProviderDelegate> delegate,
- AutocompleteProvider::Type type)
- : AutocompleteProvider(type),
- template_url_service_(template_url_service),
- delegate_(delegate.Pass()),
- field_trial_triggered_(false),
- field_trial_triggered_in_session_(false) {
-}
-
-// static
-bool BaseSearchProvider::ShouldPrefetch(const AutocompleteMatch& match) {
- return match.GetAdditionalInfo(kShouldPrefetchKey) == kTrue;
-}
-
-// static
-AutocompleteMatch BaseSearchProvider::CreateSearchSuggestion(
- const base::string16& suggestion,
- AutocompleteMatchType::Type type,
- bool from_keyword_provider,
- const TemplateURL* template_url,
- const SearchTermsData& search_terms_data) {
- // This call uses a number of default values. For instance, it assumes that
- // if this match is from a keyword provider than the user is in keyword mode.
- return CreateSearchSuggestion(
- NULL, AutocompleteInput(), from_keyword_provider,
- SearchSuggestionParser::SuggestResult(
- suggestion, type, suggestion, base::string16(), base::string16(),
- base::string16(), base::string16(), std::string(), std::string(),
- from_keyword_provider, 0, false, false, base::string16()),
- template_url, search_terms_data, 0, false);
-}
-
-void BaseSearchProvider::DeleteMatch(const AutocompleteMatch& match) {
- DCHECK(match.deletable);
- if (!match.GetAdditionalInfo(BaseSearchProvider::kDeletionUrlKey).empty()) {
- deletion_handlers_.push_back(new SuggestionDeletionHandler(
- match.GetAdditionalInfo(BaseSearchProvider::kDeletionUrlKey),
- delegate_->RequestContext(),
- base::Bind(&BaseSearchProvider::OnDeletionComplete,
- base::Unretained(this))));
- }
-
- TemplateURL* template_url =
- match.GetTemplateURL(template_url_service_, 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) {
- delegate_->DeleteMatchingURLsForKeywordFromHistory(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 BaseSearchProvider::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]);
- }
- }
-}
-
-// 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() {}
-
-void BaseSearchProvider::SetDeletionURL(const std::string& deletion_url,
- AutocompleteMatch* match) {
- if (deletion_url.empty())
- return;
- if (!template_url_service_)
- return;
- GURL url =
- template_url_service_->GetDefaultSearchProvider()->GenerateSearchURL(
- template_url_service_->search_terms_data());
- url = url.GetOrigin().Resolve(deletion_url);
- if (url.is_valid()) {
- match->RecordAdditionalInfo(BaseSearchProvider::kDeletionUrlKey,
- url.spec());
- match->deletable = true;
- }
-}
-
-// static
-AutocompleteMatch BaseSearchProvider::CreateSearchSuggestion(
- AutocompleteProvider* autocomplete_provider,
- const AutocompleteInput& input,
- const bool in_keyword_mode,
- const SearchSuggestionParser::SuggestResult& suggestion,
- const TemplateURL* template_url,
- const SearchTermsData& search_terms_data,
- int accepted_suggestion,
- 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();
- match.answer_contents = suggestion.answer_contents();
- match.answer_type = suggestion.answer_type();
- if (suggestion.type() == AutocompleteMatchType::SEARCH_SUGGEST_INFINITE) {
- match.RecordAdditionalInfo(
- kACMatchPropertyInputText, base::UTF16ToUTF8(input.text()));
- match.RecordAdditionalInfo(
- kACMatchPropertyContentsPrefix,
- base::UTF16ToUTF8(suggestion.match_contents_prefix()));
- match.RecordAdditionalInfo(
- kACMatchPropertyContentsStartIndex,
- static_cast<int>(
- suggestion.suggestion().length() - match.contents.length()));
- }
-
- if (!suggestion.annotation().empty())
- match.description = suggestion.annotation();
-
- // suggestion.match_contents() should have already been collapsed.
- match.allowed_to_be_default_match =
- (!in_keyword_mode || suggestion.from_keyword_provider()) &&
- (base::CollapseWhitespace(input.text(), false) ==
- 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() == metrics::OmniboxInputType::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() &&
- (!in_keyword_mode || suggestion.from_keyword_provider()) &&
- 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(search_terms_data));
- 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->enable_omnibox_start_margin = true;
- 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_terms_data));
-
- // 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 BaseSearchProvider::ZeroSuggestEnabled(
- const GURL& suggest_url,
- const TemplateURL* template_url,
- OmniboxEventProto::PageClassification page_classification,
- const SearchTermsData& search_terms_data,
- AutocompleteProviderDelegate* delegate) {
- if (!OmniboxFieldTrial::InZeroSuggestFieldTrial())
- return false;
-
- // Make sure we are sending the suggest request through HTTPS to prevent
- // exposing the current page URL or personalized results without encryption.
- if (!suggest_url.SchemeIs(url::kHttpsScheme))
- return false;
-
- // Don't show zero suggest on the NTP.
- // TODO(hfung): Experiment with showing MostVisited zero suggest on NTP
- // under the conditions described in crbug.com/305366.
- if ((page_classification ==
- OmniboxEventProto::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS) ||
- (page_classification ==
- OmniboxEventProto::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS))
- return false;
-
- // Don't run if in incognito mode.
- if (delegate->IsOffTheRecord())
- return false;
-
- // Don't run if we can't get preferences or search suggest is not enabled.
- if (!delegate->SearchSuggestEnabled())
- 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(search_terms_data) ||
- TemplateURLPrepopulateData::GetEngineType(
- *template_url, search_terms_data) != SEARCH_ENGINE_GOOGLE)
- return false;
-
- return true;
-}
-
-// static
-bool BaseSearchProvider::CanSendURL(
- const GURL& current_page_url,
- const GURL& suggest_url,
- const TemplateURL* template_url,
- OmniboxEventProto::PageClassification page_classification,
- const SearchTermsData& search_terms_data,
- AutocompleteProviderDelegate* delegate) {
- if (!ZeroSuggestEnabled(suggest_url, template_url, page_classification,
- search_terms_data, delegate))
- return false;
-
- if (!current_page_url.is_valid())
- return false;
-
- // Only allow HTTP URLs or HTTPS URLs for the same domain as the search
- // provider.
- if ((current_page_url.scheme() != url::kHttpScheme) &&
- ((current_page_url.scheme() != url::kHttpsScheme) ||
- !net::registry_controlled_domains::SameDomainOrHost(
- current_page_url, suggest_url,
- net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES)))
- return false;
-
- if (!delegate->TabSyncEnabledAndUnencrypted())
- return false;
-
- return true;
-}
-
-void BaseSearchProvider::AddMatchToMap(
- const SearchSuggestionParser::SuggestResult& result,
- const std::string& metadata,
- int accepted_suggestion,
- bool mark_as_deletable,
- bool in_keyword_mode,
- MatchMap* map) {
- AutocompleteMatch match = CreateSearchSuggestion(
- this, GetInput(result.from_keyword_provider()), in_keyword_mode, result,
- GetTemplateURL(result.from_keyword_provider()),
- template_url_service_->search_terms_data(), accepted_suggestion,
- ShouldAppendExtraParams(result));
- if (!match.destination_url.is_valid())
- return;
- match.search_terms_args->bookmark_bar_pinned = delegate_->ShowBookmarkBar();
- match.RecordAdditionalInfo(kRelevanceFromServerKey,
- result.relevance_from_server() ? kTrue : kFalse);
- match.RecordAdditionalInfo(kShouldPrefetchKey,
- result.should_prefetch() ? kTrue : kFalse);
- SetDeletionURL(result.deletion_url(), &match);
- if (mark_as_deletable)
- 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) {
- match.duplicate_matches.insert(match.duplicate_matches.end(),
- i.first->second.duplicate_matches.begin(),
- i.first->second.duplicate_matches.end());
- i.first->second.duplicate_matches.clear();
- match.duplicate_matches.push_back(i.first->second);
- i.first->second = match;
- } else {
- i.first->second.duplicate_matches.push_back(match);
- 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);
- }
- }
- }
-}
-
-bool BaseSearchProvider::ParseSuggestResults(
- const base::Value& root_val,
- int default_result_relevance,
- bool is_keyword_result,
- SearchSuggestionParser::Results* results) {
- if (!SearchSuggestionParser::ParseSuggestResults(
- root_val, GetInput(is_keyword_result),
- delegate_->SchemeClassifier(), default_result_relevance,
- delegate_->AcceptLanguages(), is_keyword_result, results))
- return false;
-
- for (std::vector<GURL>::const_iterator it =
- results->answers_image_urls.begin();
- it != results->answers_image_urls.end(); ++it)
- delegate_->PrefetchImage(*it);
-
- field_trial_triggered_ |= results->field_trial_triggered;
- field_trial_triggered_in_session_ |= results->field_trial_triggered;
- return true;
-}
-
-void BaseSearchProvider::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 BaseSearchProvider::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);
-}
« no previous file with comments | « chrome/browser/autocomplete/base_search_provider.h ('k') | chrome/browser/autocomplete/search_provider.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698