15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
51320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/omnibox/base_search_provider.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/i18n/case_conversion.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/string_util.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
106d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "components/metrics/proto/omnibox_event.pb.h"
11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/metrics/proto/omnibox_input_type.pb.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/omnibox/autocomplete_provider_client.h"
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/omnibox/autocomplete_provider_listener.h"
146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/omnibox/omnibox_field_trial.h"
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/search_engines/template_url.h"
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/search_engines/template_url_prepopulate_data.h"
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/search_engines/template_url_service.h"
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "net/url_request/url_fetcher.h"
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/url_request/url_fetcher_delegate.h"
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "url/gurl.h"
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)using metrics::OmniboxEventProto;
246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// SuggestionDeletionHandler -------------------------------------------------
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// This class handles making requests to the server in order to delete
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// personalized suggestions.
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class SuggestionDeletionHandler : public net::URLFetcherDelegate {
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  typedef base::Callback<void(bool, SuggestionDeletionHandler*)>
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      DeletionCompletedCallback;
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SuggestionDeletionHandler(
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const std::string& deletion_url,
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      net::URLRequestContextGetter* request_context,
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      const DeletionCompletedCallback& callback);
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual ~SuggestionDeletionHandler();
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private:
42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // net::URLFetcherDelegate:
43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  scoped_ptr<net::URLFetcher> deletion_fetcher_;
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DeletionCompletedCallback callback_;
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SuggestionDeletionHandler);
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)SuggestionDeletionHandler::SuggestionDeletionHandler(
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const std::string& deletion_url,
531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net::URLRequestContextGetter* request_context,
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const DeletionCompletedCallback& callback) : callback_(callback) {
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  GURL url(deletion_url);
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(url.is_valid());
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  deletion_fetcher_.reset(net::URLFetcher::Create(
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      BaseSearchProvider::kDeletionURLFetcherID,
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      url,
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      net::URLFetcher::GET,
62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      this));
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  deletion_fetcher_->SetRequestContext(request_context);
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  deletion_fetcher_->Start();
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)SuggestionDeletionHandler::~SuggestionDeletionHandler() {
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void SuggestionDeletionHandler::OnURLFetchComplete(
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const net::URLFetcher* source) {
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(source == deletion_fetcher_.get());
73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  callback_.Run(
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      source->GetStatus().is_success() && (source->GetResponseCode() == 200),
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      this);
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// BaseSearchProvider ---------------------------------------------------------
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int BaseSearchProvider::kDefaultProviderURLFetcherID = 1;
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int BaseSearchProvider::kKeywordProviderURLFetcherID = 2;
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const int BaseSearchProvider::kDeletionURLFetcherID = 3;
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBaseSearchProvider::BaseSearchProvider(
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    TemplateURLService* template_url_service,
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<AutocompleteProviderClient> client,
881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AutocompleteProvider::Type type)
89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    : AutocompleteProvider(type),
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      template_url_service_(template_url_service),
911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      client_(client.Pass()),
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      field_trial_triggered_(false),
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      field_trial_triggered_in_session_(false) {
9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool BaseSearchProvider::ShouldPrefetch(const AutocompleteMatch& match) {
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return match.GetAdditionalInfo(kShouldPrefetchKey) == kTrue;
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
101effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// static
102effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochAutocompleteMatch BaseSearchProvider::CreateSearchSuggestion(
103effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    const base::string16& suggestion,
104effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    AutocompleteMatchType::Type type,
105effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    bool from_keyword_provider,
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const TemplateURL* template_url,
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const SearchTermsData& search_terms_data) {
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // These calls use a number of default values.  For instance, they assume
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // that if this match is from a keyword provider, then the user is in keyword
1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // mode.  They also assume the caller knows what it's doing and we set
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // this match to look as if it was received/created synchronously.
1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  SearchSuggestionParser::SuggestResult suggest_result(
1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      suggestion, type, suggestion, base::string16(), base::string16(),
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::string16(), base::string16(), std::string(), std::string(),
1151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      from_keyword_provider, 0, false, false, base::string16());
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  suggest_result.set_received_after_last_keystroke(false);
117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  return CreateSearchSuggestion(
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      NULL, AutocompleteInput(), from_keyword_provider, suggest_result,
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      template_url, search_terms_data, 0, false);
120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BaseSearchProvider::DeleteMatch(const AutocompleteMatch& match) {
123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(match.deletable);
124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (!match.GetAdditionalInfo(BaseSearchProvider::kDeletionUrlKey).empty()) {
125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    deletion_handlers_.push_back(new SuggestionDeletionHandler(
126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        match.GetAdditionalInfo(BaseSearchProvider::kDeletionUrlKey),
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        client_->RequestContext(),
128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::Bind(&BaseSearchProvider::OnDeletionComplete,
129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                   base::Unretained(this))));
130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TemplateURL* template_url =
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      match.GetTemplateURL(template_url_service_, false);
134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // This may be NULL if the template corresponding to the keyword has been
135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // deleted or there is no keyword set.
136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (template_url != NULL) {
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    client_->DeleteMatchingURLsForKeywordFromHistory(template_url->id(),
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                                     match.contents);
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // Immediately update the list of matches to show the match was deleted,
142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  // regardless of whether the server request actually succeeds.
143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DeleteMatchFromMatches(match);
144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void BaseSearchProvider::AddProviderInfo(ProvidersInfo* provider_info) const {
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo());
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back();
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  new_entry.set_provider(AsOmniboxEventProviderType());
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  new_entry.set_provider_done(done_);
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<uint32> field_trial_hashes;
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  OmniboxFieldTrial::GetActiveSuggestFieldTrialHashes(&field_trial_hashes);
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < field_trial_hashes.size(); ++i) {
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (field_trial_triggered_)
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new_entry.mutable_field_trial_triggered()->Add(field_trial_hashes[i]);
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (field_trial_triggered_in_session_) {
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new_entry.mutable_field_trial_triggered_in_session()->Add(
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          field_trial_hashes[i]);
159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char BaseSearchProvider::kRelevanceFromServerKey[] =
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    "relevance_from_server";
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char BaseSearchProvider::kShouldPrefetchKey[] = "should_prefetch";
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char BaseSearchProvider::kSuggestMetadataKey[] = "suggest_metadata";
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char BaseSearchProvider::kDeletionUrlKey[] = "deletion_url";
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char BaseSearchProvider::kTrue[] = "true";
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char BaseSearchProvider::kFalse[] = "false";
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)BaseSearchProvider::~BaseSearchProvider() {}
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
174010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void BaseSearchProvider::SetDeletionURL(const std::string& deletion_url,
175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                        AutocompleteMatch* match) {
176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (deletion_url.empty())
177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!template_url_service_)
179010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GURL url =
1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      template_url_service_->GetDefaultSearchProvider()->GenerateSearchURL(
1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          template_url_service_->search_terms_data());
183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  url = url.GetOrigin().Resolve(deletion_url);
184010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (url.is_valid()) {
185010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    match->RecordAdditionalInfo(BaseSearchProvider::kDeletionUrlKey,
186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        url.spec());
187010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    match->deletable = true;
188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
189010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
190010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)AutocompleteMatch BaseSearchProvider::CreateSearchSuggestion(
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    AutocompleteProvider* autocomplete_provider,
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const AutocompleteInput& input,
1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const bool in_keyword_mode,
1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const SearchSuggestionParser::SuggestResult& suggestion,
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const TemplateURL* template_url,
198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const SearchTermsData& search_terms_data,
1995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int accepted_suggestion,
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool append_extra_query_params) {
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AutocompleteMatch match(autocomplete_provider, suggestion.relevance(), false,
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          suggestion.type());
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!template_url)
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return match;
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  match.keyword = template_url->keyword();
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  match.contents = suggestion.match_contents();
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  match.contents_class = suggestion.match_contents_class();
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  match.answer_contents = suggestion.answer_contents();
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  match.answer_type = suggestion.answer_type();
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (suggestion.type() == AutocompleteMatchType::SEARCH_SUGGEST_INFINITE) {
212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    match.RecordAdditionalInfo(
213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        kACMatchPropertyInputText, base::UTF16ToUTF8(input.text()));
214effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    match.RecordAdditionalInfo(
215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        kACMatchPropertyContentsPrefix,
216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::UTF16ToUTF8(suggestion.match_contents_prefix()));
217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    match.RecordAdditionalInfo(
218effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        kACMatchPropertyContentsStartIndex,
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        static_cast<int>(
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            suggestion.suggestion().length() - match.contents.length()));
221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!suggestion.annotation().empty())
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    match.description = suggestion.annotation();
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
226effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // suggestion.match_contents() should have already been collapsed.
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  match.allowed_to_be_default_match =
2286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      (!in_keyword_mode || suggestion.from_keyword_provider()) &&
229effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      (base::CollapseWhitespace(input.text(), false) ==
230effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch       suggestion.match_contents());
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // When the user forced a query, we need to make sure all the fill_into_edit
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // values preserve that property.  Otherwise, if the user starts editing a
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // suggestion, non-Search results will suddenly appear.
235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (input.type() == metrics::OmniboxInputType::FORCED_QUERY)
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    match.fill_into_edit.assign(base::ASCIIToUTF16("?"));
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (suggestion.from_keyword_provider())
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    match.fill_into_edit.append(match.keyword + base::char16(' '));
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // We only allow inlinable navsuggestions that were received before the
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // last keystroke because we don't want asynchronous inline autocompletions.
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!input.prevent_inline_autocomplete() &&
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      !suggestion.received_after_last_keystroke() &&
2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      (!in_keyword_mode || suggestion.from_keyword_provider()) &&
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      StartsWith(suggestion.suggestion(), input.text(), false)) {
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    match.inline_autocompletion =
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        suggestion.suggestion().substr(input.text().length());
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    match.allowed_to_be_default_match = true;
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  match.fill_into_edit.append(suggestion.suggestion());
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const TemplateURLRef& search_url = template_url->url_ref();
252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  DCHECK(search_url.SupportsReplacement(search_terms_data));
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  match.search_terms_args.reset(
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new TemplateURLRef::SearchTermsArgs(suggestion.suggestion()));
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  match.search_terms_args->original_query = input.text();
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  match.search_terms_args->accepted_suggestion = accepted_suggestion;
2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  match.search_terms_args->enable_omnibox_start_margin = true;
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  match.search_terms_args->suggest_query_params =
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      suggestion.suggest_query_params();
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  match.search_terms_args->append_extra_query_params =
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      append_extra_query_params;
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // This is the destination URL sans assisted query stats.  This must be set
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // so the AutocompleteController can properly de-dupe; the controller will
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // eventually overwrite it before it reaches the user.
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  match.destination_url =
266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      GURL(search_url.ReplaceSearchTerms(*match.search_terms_args.get(),
267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                         search_terms_data));
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Search results don't look like URLs.
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  match.transition = suggestion.from_keyword_provider() ?
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ui::PAGE_TRANSITION_KEYWORD : ui::PAGE_TRANSITION_GENERATED;
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return match;
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
27723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool BaseSearchProvider::ZeroSuggestEnabled(
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const GURL& suggest_url,
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const TemplateURL* template_url,
2806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    OmniboxEventProto::PageClassification page_classification,
2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const SearchTermsData& search_terms_data,
2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AutocompleteProviderClient* client) {
28323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!OmniboxFieldTrial::InZeroSuggestFieldTrial())
28423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return false;
28523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
28623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Make sure we are sending the suggest request through HTTPS to prevent
28723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // exposing the current page URL or personalized results without encryption.
288010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!suggest_url.SchemeIs(url::kHttpsScheme))
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
29123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Don't show zero suggest on the NTP.
29223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // TODO(hfung): Experiment with showing MostVisited zero suggest on NTP
29323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // under the conditions described in crbug.com/305366.
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if ((page_classification ==
2956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)       OmniboxEventProto::INSTANT_NTP_WITH_FAKEBOX_AS_STARTING_FOCUS) ||
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (page_classification ==
2976d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)       OmniboxEventProto::INSTANT_NTP_WITH_OMNIBOX_AS_STARTING_FOCUS))
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Don't run if in incognito mode.
3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (client->IsOffTheRecord())
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Don't run if we can't get preferences or search suggest is not enabled.
3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!client->SearchSuggestEnabled())
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Only make the request if we know that the provider supports zero suggest
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // (currently only the prepopulated Google provider).
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (template_url == NULL ||
311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      !template_url->SupportsReplacement(search_terms_data) ||
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      TemplateURLPrepopulateData::GetEngineType(
313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          *template_url, search_terms_data) != SEARCH_ENGINE_GOOGLE)
3145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
3155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
31623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return true;
31723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
31823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
31923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// static
32023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool BaseSearchProvider::CanSendURL(
32123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const GURL& current_page_url,
32223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const GURL& suggest_url,
32323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const TemplateURL* template_url,
3246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    OmniboxEventProto::PageClassification page_classification,
3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const SearchTermsData& search_terms_data,
3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AutocompleteProviderClient* client) {
32723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!ZeroSuggestEnabled(suggest_url, template_url, page_classification,
3281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          search_terms_data, client))
32923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return false;
33023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
33123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!current_page_url.is_valid())
33223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return false;
33323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
33423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Only allow HTTP URLs or HTTPS URLs for the same domain as the search
33523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // provider.
336010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if ((current_page_url.scheme() != url::kHttpScheme) &&
337010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ((current_page_url.scheme() != url::kHttpsScheme) ||
33823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)       !net::registry_controlled_domains::SameDomainOrHost(
33923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)           current_page_url, suggest_url,
34023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)           net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES)))
34123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return false;
34223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!client->TabSyncEnabledAndUnencrypted())
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void BaseSearchProvider::AddMatchToMap(
3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const SearchSuggestionParser::SuggestResult& result,
3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const std::string& metadata,
3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    int accepted_suggestion,
3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool mark_as_deletable,
3546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    bool in_keyword_mode,
3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    MatchMap* map) {
3565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AutocompleteMatch match = CreateSearchSuggestion(
3576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      this, GetInput(result.from_keyword_provider()), in_keyword_mode, result,
358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      GetTemplateURL(result.from_keyword_provider()),
3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      template_url_service_->search_terms_data(), accepted_suggestion,
3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ShouldAppendExtraParams(result));
3615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!match.destination_url.is_valid())
3625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  match.search_terms_args->bookmark_bar_pinned = client_->ShowBookmarkBar();
3645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  match.RecordAdditionalInfo(kRelevanceFromServerKey,
3655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             result.relevance_from_server() ? kTrue : kFalse);
3665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  match.RecordAdditionalInfo(kShouldPrefetchKey,
3675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             result.should_prefetch() ? kTrue : kFalse);
368010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  SetDeletionURL(result.deletion_url(), &match);
369010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (mark_as_deletable)
370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    match.deletable = true;
3715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Metadata is needed only for prefetching queries.
3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (result.should_prefetch())
3735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    match.RecordAdditionalInfo(kSuggestMetadataKey, metadata);
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Try to add |match| to |map|.  If a match for this suggestion is
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // already in |map|, replace it if |match| is more relevant.
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // NOTE: Keep this ToLower() call in sync with url_database.cc.
3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MatchKey match_key(
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::make_pair(base::i18n::ToLower(result.suggestion()),
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     match.search_terms_args->suggest_query_params));
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const std::pair<MatchMap::iterator, bool> i(
3825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       map->insert(std::make_pair(match_key, match)));
3835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool should_prefetch = result.should_prefetch();
3855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!i.second) {
3865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // NOTE: We purposefully do a direct relevance comparison here instead of
3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items
3885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // added first" rather than "items alphabetically first" when the scores
3895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // are equal. The only case this matters is when a user has results with
3905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // the same score that differ only by capitalization; because the history
3915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // system returns results sorted by recency, this means we'll pick the most
3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // recent such result even if the precision of our relevance score is too
3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // low to distinguish the two.
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (match.relevance > i.first->second.relevance) {
395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      match.duplicate_matches.insert(match.duplicate_matches.end(),
396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     i.first->second.duplicate_matches.begin(),
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     i.first->second.duplicate_matches.end());
398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      i.first->second.duplicate_matches.clear();
399a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      match.duplicate_matches.push_back(i.first->second);
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      i.first->second = match;
401a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    } else {
402a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      i.first->second.duplicate_matches.push_back(match);
403a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      if (match.keyword == i.first->second.keyword) {
404a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // Old and new matches are from the same search provider. It is okay to
405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // record one match's prefetch data onto a different match (for the same
406a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // query string) for the following reasons:
407a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // 1. Because the suggest server only sends down a query string from
408a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // which we construct a URL, rather than sending a full URL, and because
409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // we construct URLs from query strings in the same way every time, the
410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // URLs for the two matches will be the same. Therefore, we won't end up
411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // prefetching something the server didn't intend.
412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // 2. Presumably the server sets the prefetch bit on a match it things
413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // is sufficiently relevant that the user is likely to choose it.
414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // Surely setting the prefetch bit on a match of even higher relevance
415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // won't violate this assumption.
416a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        should_prefetch |= ShouldPrefetch(i.first->second);
417a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        i.first->second.RecordAdditionalInfo(kShouldPrefetchKey,
418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                             should_prefetch ? kTrue : kFalse);
419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if (should_prefetch)
420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          i.first->second.RecordAdditionalInfo(kSuggestMetadataKey, metadata);
421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      }
422a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
4231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // Copy over answer data from lower-ranking item, if necessary.
4241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // This depends on the lower-ranking item always being added last - see
4251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // use of push_back above.
4261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AutocompleteMatch& more_relevant_match = i.first->second;
4271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const AutocompleteMatch& less_relevant_match =
4281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        more_relevant_match.duplicate_matches.back();
4291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!less_relevant_match.answer_type.empty() &&
4301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        more_relevant_match.answer_type.empty()) {
4311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      more_relevant_match.answer_type = less_relevant_match.answer_type;
4321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      more_relevant_match.answer_contents = less_relevant_match.answer_contents;
4331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
434a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
435a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
436a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool BaseSearchProvider::ParseSuggestResults(
4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const base::Value& root_val,
4396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    int default_result_relevance,
4405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    bool is_keyword_result,
4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SearchSuggestionParser::Results* results) {
4425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!SearchSuggestionParser::ParseSuggestResults(
4435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      root_val, GetInput(is_keyword_result),
4441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      client_->SchemeClassifier(), default_result_relevance,
4451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      client_->AcceptLanguages(), is_keyword_result, results))
446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    return false;
447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (std::vector<GURL>::const_iterator it =
4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)           results->answers_image_urls.begin();
4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       it != results->answers_image_urls.end(); ++it)
4511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    client_->PrefetchImage(*it);
4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  field_trial_triggered_ |= results->field_trial_triggered;
4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  field_trial_triggered_in_session_ |= results->field_trial_triggered;
4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return true;
4566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
4576d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)
458a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BaseSearchProvider::DeleteMatchFromMatches(
459a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const AutocompleteMatch& match) {
460a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (ACMatches::iterator i(matches_.begin()); i != matches_.end(); ++i) {
461a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Find the desired match to delete by checking the type and contents.
462a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // We can't check the destination URL, because the autocomplete controller
463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // may have reformulated that. Not that while checking for matching
464a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // contents works for personalized suggestions, if more match types gain
465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // deletion support, this algorithm may need to be re-examined.
466a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (i->contents == match.contents && i->type == match.type) {
467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      matches_.erase(i);
468a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      break;
469a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
470a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  }
471a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
472a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
473a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BaseSearchProvider::OnDeletionComplete(
474a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    bool success, SuggestionDeletionHandler* handler) {
475a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  RecordDeletionResult(success);
476a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  SuggestionDeletionHandlers::iterator it = std::find(
477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      deletion_handlers_.begin(), deletion_handlers_.end(), handler);
478a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  DCHECK(it != deletion_handlers_.end());
479a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  deletion_handlers_.erase(it);
4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
481