15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/autocomplete/zero_suggest_provider.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/callback.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/i18n/case_conversion.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_string_value_serializer.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/metrics/histogram.h"
116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/metrics/user_metrics.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h"
14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
16eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chrome/browser/autocomplete/autocomplete_classifier.h"
18424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h"
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/browser/autocomplete/chrome_autocomplete_scheme_classifier.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/browser/autocomplete/history_url_provider.h"
22d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/browser/history/top_sites.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/history/core/browser/history_types.h"
26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "components/metrics/proto/omnibox_input_type.pb.h"
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/omnibox/autocomplete_input.h"
285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/omnibox/autocomplete_match.h"
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/omnibox/autocomplete_provider_listener.h"
306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "components/omnibox/omnibox_field_trial.h"
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "components/omnibox/search_provider.h"
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h"
33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/search_engines/template_url_service.h"
34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/variations/variations_http_header_provider.h"
35868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/base/escape.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_flags.h"
37868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/base/net_util.h"
38868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "net/http/http_request_headers.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_status.h"
41eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "url/gurl.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
45868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// TODO(hfung): The histogram code was copied and modified from
46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// search_provider.cc.  Refactor and consolidate the code.
47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// We keep track in a histogram how many suggest requests we send, how
48868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// many suggest requests we invalidate (e.g., due to a user typing
49868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// another character), and how many replies we receive.
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// *** ADD NEW ENUMS AFTER ALL PREVIOUSLY DEFINED ONES! ***
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//     (excluding the end-of-list enum value)
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// We do not want values of existing enums to change or else it screws
53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// up the statistics.
54868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)enum ZeroSuggestRequestsHistogramValue {
55868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ZERO_SUGGEST_REQUEST_SENT = 1,
56868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ZERO_SUGGEST_REQUEST_INVALIDATED,
57868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ZERO_SUGGEST_REPLY_RECEIVED,
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void LogOmniboxZeroSuggestRequest(
62868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ZeroSuggestRequestsHistogramValue request_value) {
63868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("Omnibox.ZeroSuggestRequests", request_value,
64868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                            ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE);
65868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
67868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// The maximum relevance of the top match from this provider.
68868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const int kDefaultVerbatimZeroSuggestRelevance = 1300;
69868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
70868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Relevance value to use if it was not set explicitly by the server.
71868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const int kDefaultZeroSuggestRelevance = 100;
72868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ZeroSuggestProvider* ZeroSuggestProvider::Create(
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AutocompleteProviderListener* listener,
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    TemplateURLService* template_url_service,
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile) {
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return new ZeroSuggestProvider(listener, template_url_service, profile);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ZeroSuggestProvider::RegisterProfilePrefs(
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    user_prefs::PrefRegistrySyncable* registry) {
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  registry->RegisterStringPref(
87010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      prefs::kZeroSuggestCachedResults,
88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      std::string(),
89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
90010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ZeroSuggestProvider::Start(const AutocompleteInput& input,
93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                bool minimal_changes) {
94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  matches_.clear();
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (input.type() == metrics::OmniboxInputType::INVALID)
96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
98868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Stop(true);
99868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  field_trial_triggered_ = false;
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  field_trial_triggered_in_session_ = false;
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  results_from_cache_ = false;
102effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  permanent_text_ = input.text();
103effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  current_query_ = input.current_url().spec();
104effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  current_page_classification_ = input.current_page_classification();
105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  current_url_match_ = MatchForCurrentURL();
106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const TemplateURL* default_provider =
108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)     template_url_service_->GetDefaultSearchProvider();
109f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (default_provider == NULL)
110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
11123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 prefix;
113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TemplateURLRef::SearchTermsArgs search_term_args(prefix);
11423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  GURL suggest_url(default_provider->suggestions_url_ref().ReplaceSearchTerms(
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      search_term_args, template_url_service_->search_terms_data()));
11623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!suggest_url.is_valid())
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
11823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
11923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // No need to send the current page URL in personalized suggest field trial.
120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (CanSendURL(input.current_url(), suggest_url, default_provider,
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                 current_page_classification_,
1221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 template_url_service_->search_terms_data(), client_.get()) &&
12323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      !OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial()) {
12423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    // Update suggest_url to include the current_page_url.
12523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    search_term_args.current_page_url = current_query_;
12623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    suggest_url = GURL(default_provider->suggestions_url_ref().
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       ReplaceSearchTerms(
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                           search_term_args,
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                           template_url_service_->search_terms_data()));
13023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  } else if (!CanShowZeroSuggestWithoutSendingURL(suggest_url,
131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                                  input.current_url())) {
13223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return;
13323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  }
13423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  done_ = false;
136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jered): Consider adding locally-sourced zero-suggestions here too.
137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // These may be useful on the NTP or more relevant to the user than server
138868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // suggestions, if based on local browsing history.
139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  MaybeUseCachedSuggestions();
140f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Run(suggest_url);
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void ZeroSuggestProvider::Stop(bool clear_cached_results) {
14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (fetcher_)
14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_INVALIDATED);
14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  fetcher_.reset();
14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  done_ = true;
14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (clear_cached_results) {
15003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // We do not call Clear() on |results_| to retain |verbatim_relevance|
15103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // value in the |results_| object. |verbatim_relevance| is used at the
15203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // beginning of the next StartZeroSuggest() call to determine the current
15303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    // url match relevance.
15403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    results_.suggest_results.clear();
15503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    results_.navigation_results.clear();
15603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    current_query_.clear();
15703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
15803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
15903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
160010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ZeroSuggestProvider::DeleteMatch(const AutocompleteMatch& match) {
161010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial()) {
162010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // Remove the deleted match from the cache, so it is not shown to the user
163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // again. Since we cannot remove just one result, blow away the cache.
164010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    profile_->GetPrefs()->SetString(prefs::kZeroSuggestCachedResults,
165010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                    std::string());
166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
167010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  BaseSearchProvider::DeleteMatch(match);
168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
17003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void ZeroSuggestProvider::AddProviderInfo(ProvidersInfo* provider_info) const {
17103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  BaseSearchProvider::AddProviderInfo(provider_info);
17203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  if (!results_.suggest_results.empty() || !results_.navigation_results.empty())
17303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    provider_info->back().set_times_returned_results_in_session(1);
17403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
17503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
176effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid ZeroSuggestProvider::ResetSession() {
177effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // The user has started editing in the omnibox, so leave
178effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // |field_trial_triggered_in_session_| unchanged and set
179effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // |field_trial_triggered_| to false since zero suggest is inactive now.
180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  field_trial_triggered_ = false;
181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ZeroSuggestProvider::ZeroSuggestProvider(
184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AutocompleteProviderListener* listener,
1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TemplateURLService* template_url_service,
186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  Profile* profile)
1871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : BaseSearchProvider(template_url_service,
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                         scoped_ptr<AutocompleteProviderClient>(
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                             new ChromeAutocompleteProviderClient(profile)),
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                         AutocompleteProvider::TYPE_ZERO_SUGGEST),
1916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      listener_(listener),
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      profile_(profile),
193010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      results_from_cache_(false),
194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      weak_ptr_factory_(this) {
195868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
196868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ZeroSuggestProvider::~ZeroSuggestProvider() {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)const TemplateURL* ZeroSuggestProvider::GetTemplateURL(bool is_keyword) const {
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Zero suggest provider should not receive keyword results.
20223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  DCHECK(!is_keyword);
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return template_url_service_->GetDefaultSearchProvider();
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const AutocompleteInput ZeroSuggestProvider::GetInput(bool is_keyword) const {
207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return AutocompleteInput(
208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::string16(), base::string16::npos, base::string16(),
209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      GURL(current_query_), current_page_classification_, true, false, false,
210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      true, ChromeAutocompleteSchemeClassifier(profile_));
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ZeroSuggestProvider::ShouldAppendExtraParams(
2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      const SearchSuggestionParser::SuggestResult& result) const {
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // We always use the default provider for search, so append the params.
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ZeroSuggestProvider::RecordDeletionResult(bool success) {
220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (success) {
2216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    base::RecordAction(
222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::UserMetricsAction("Omnibox.ZeroSuggestDelete.Success"));
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  } else {
2246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    base::RecordAction(
225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        base::UserMetricsAction("Omnibox.ZeroSuggestDelete.Failure"));
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ZeroSuggestProvider::OnURLFetchComplete(const net::URLFetcher* source) {
2306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(!done_);
2316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK_EQ(fetcher_.get(), source);
23223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REPLY_RECEIVED);
23423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
2356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  bool results_updated = false;
2366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (source->GetStatus().is_success() && source->GetResponseCode() == 200) {
2376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    std::string json_data = SearchSuggestionParser::ExtractJsonData(source);
2386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    scoped_ptr<base::Value> data(
2396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        SearchSuggestionParser::DeserializeJsonData(json_data));
2406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (data) {
2416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (StoreSuggestionResponse(json_data, *data))
2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        return;
2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      results_updated = ParseSuggestResults(
2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          *data, kDefaultZeroSuggestRelevance, false, &results_);
2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
2466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  fetcher_.reset();
24823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  done_ = true;
24923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  ConvertResultsToAutocompleteMatches();
2506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  listener_->OnProviderUpdate(results_updated);
2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool ZeroSuggestProvider::StoreSuggestionResponse(
2546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const std::string& json_data,
2556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    const base::Value& parsed_data) {
2566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() ||
2576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      json_data.empty())
2586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return false;
2596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  profile_->GetPrefs()->SetString(prefs::kZeroSuggestCachedResults, json_data);
2606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // If we received an empty result list, we should update the display, as it
2626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // may be showing cached results that should not be shown.
2636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const base::ListValue* root_list = NULL;
2646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const base::ListValue* results_list = NULL;
2656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (parsed_data.GetAsList(&root_list) &&
2666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      root_list->GetList(1, &results_list) &&
2676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      results_list->empty())
2686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return false;
2696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // We are finished with the request and want to bail early.
2716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (results_from_cache_)
2726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    done_ = true;
2736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return results_from_cache_;
27523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
27623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void ZeroSuggestProvider::AddSuggestResultsToMap(
2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const SearchSuggestionParser::SuggestResults& results,
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MatchMap* map) {
280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (size_t i = 0; i < results.size(); ++i)
2816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    AddMatchToMap(results[i], std::string(), i, false, false, map);
282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
283868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AutocompleteMatch ZeroSuggestProvider::NavigationToMatch(
2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const SearchSuggestionParser::NavigationResult& navigation) {
286868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AutocompleteMatch match(this, navigation.relevance(), false,
287010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                          navigation.type());
288868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  match.destination_url = navigation.url();
289868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Zero suggest results should always omit protocols and never appear bold.
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const std::string languages(
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  match.contents = net::FormatUrl(navigation.url(), languages,
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      net::kFormatUrlOmitAll, net::UnescapeRule::SPACES, NULL, NULL, NULL);
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  match.fill_into_edit +=
296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(),
297116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          match.contents, ChromeAutocompleteSchemeClassifier(profile_));
298868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AutocompleteMatch::ClassifyLocationInString(base::string16::npos, 0,
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      match.contents.length(), ACMatchClassification::URL,
301868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      &match.contents_class);
302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  match.description =
304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      AutocompleteMatch::SanitizeString(navigation.description());
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  AutocompleteMatch::ClassifyLocationInString(base::string16::npos, 0,
306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      match.description.length(), ACMatchClassification::NONE,
307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      &match.description_class);
308868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return match;
309868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ZeroSuggestProvider::Run(const GURL& suggest_url) {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kFetcherID = 1;
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher_.reset(
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::URLFetcher::Create(kFetcherID,
315868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          suggest_url,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          net::URLFetcher::GET, this));
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher_->SetRequestContext(profile_->GetRequestContext());
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Add Chrome experiment state to the request headers.
320868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  net::HttpRequestHeaders headers;
321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders(
322868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      fetcher_->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers);
323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  fetcher_->SetExtraRequestHeaders(headers.ToString());
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fetcher_->Start();
325d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
326d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) {
327d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    most_visited_urls_.clear();
328d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    history::TopSites* ts = profile_->GetTopSites();
329d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (ts) {
330d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      ts->GetMostVisitedURLs(
331d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          base::Bind(&ZeroSuggestProvider::OnMostVisitedUrlsAvailable,
332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()), false);
333d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
334d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_SENT);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
338d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void ZeroSuggestProvider::OnMostVisitedUrlsAvailable(
339d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const history::MostVisitedURLList& urls) {
340d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  most_visited_urls_ = urls;
341d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
342d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid ZeroSuggestProvider::ConvertResultsToAutocompleteMatches() {
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  matches_.clear();
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const TemplateURL* default_provider =
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      template_url_service_->GetDefaultSearchProvider();
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fail if we can't set the clickthrough URL for query suggestions.
349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (default_provider == NULL || !default_provider->SupportsReplacement(
350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          template_url_service_->search_terms_data()))
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
353a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  MatchMap map;
354a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  AddSuggestResultsToMap(results_.suggest_results, &map);
355a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
356a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const int num_query_results = map.size();
357a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  const int num_nav_results = results_.navigation_results.size();
358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  const int num_results = num_query_results + num_nav_results;
359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UMA_HISTOGRAM_COUNTS("ZeroSuggest.QueryResults", num_query_results);
360010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  UMA_HISTOGRAM_COUNTS("ZeroSuggest.URLResults", num_nav_results);
361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  UMA_HISTOGRAM_COUNTS("ZeroSuggest.AllResults", num_results);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
363d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Show Most Visited results after ZeroSuggest response is received.
364d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) {
3654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!current_url_match_.destination_url.is_valid())
3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return;
367d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    matches_.push_back(current_url_match_);
368d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    int relevance = 600;
369d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    if (num_results > 0) {
370d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      UMA_HISTOGRAM_COUNTS(
371d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          "Omnibox.ZeroSuggest.MostVisitedResultsCounterfactual",
372d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)          most_visited_urls_.size());
373d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
3745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const base::string16 current_query_string16(
3755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::ASCIIToUTF16(current_query_));
3765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string languages(
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
378d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    for (size_t i = 0; i < most_visited_urls_.size(); i++) {
379d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      const history::MostVisitedURL& url = most_visited_urls_[i];
3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      SearchSuggestionParser::NavigationResult nav(
381116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          ChromeAutocompleteSchemeClassifier(profile_), url.url,
382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          AutocompleteMatchType::NAVSUGGEST, url.title, std::string(), false,
383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          relevance, true, current_query_string16, languages);
384d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      matches_.push_back(NavigationToMatch(nav));
385d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      --relevance;
386d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    }
387d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return;
388d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  }
389d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (num_results == 0)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
392868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(jered): Rip this out once the first match is decoupled from the
394868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // current typing in the omnibox.
395868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  matches_.push_back(current_url_match_);
396868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  for (MatchMap::const_iterator it(map.begin()); it != map.end(); ++it)
398868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    matches_.push_back(it->second);
399868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const SearchSuggestionParser::NavigationResults& nav_results(
4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      results_.navigation_results);
4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (SearchSuggestionParser::NavigationResults::const_iterator it(
4035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)           nav_results.begin()); it != nav_results.end(); ++it)
404868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    matches_.push_back(NavigationToMatch(*it));
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
407868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)AutocompleteMatch ZeroSuggestProvider::MatchForCurrentURL() {
408424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  AutocompleteMatch match;
409424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  AutocompleteClassifierFactory::GetForProfile(profile_)->Classify(
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      permanent_text_, false, true, current_page_classification_, &match, NULL);
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  match.is_history_what_you_typed_match = false;
412c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  match.allowed_to_be_default_match = true;
413868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
414868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // The placeholder suggestion for the current URL has high relevance so
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // that it is in the first suggestion slot and inline autocompleted. It
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // gets dropped as soon as the user types something.
417a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  match.relevance = GetVerbatimRelevance();
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return match;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
422a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)int ZeroSuggestProvider::GetVerbatimRelevance() const {
423a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  return results_.verbatim_relevance >= 0 ?
424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      results_.verbatim_relevance : kDefaultVerbatimZeroSuggestRelevance;
425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
42623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
42723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)bool ZeroSuggestProvider::CanShowZeroSuggestWithoutSendingURL(
42823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const GURL& suggest_url,
42923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    const GURL& current_page_url) const {
43023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!ZeroSuggestEnabled(suggest_url,
43123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                          template_url_service_->GetDefaultSearchProvider(),
4325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          current_page_classification_,
4331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          template_url_service_->search_terms_data(),
4341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          client_.get()))
43523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return false;
43623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
43723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // If we cannot send URLs, then only the MostVisited and Personalized
43823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // variations can be shown.
43923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial() &&
44023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      !OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial())
44123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return false;
44223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
44323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // Only show zero suggest for HTTP[S] pages.
44423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // TODO(mariakhomenko): We may be able to expand this set to include pages
44523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // with other schemes (e.g. chrome://). That may require improvements to
44623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  // the formatting of the verbatim result returned by MatchForCurrentURL().
44723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  if (!current_page_url.is_valid() ||
448010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ((current_page_url.scheme() != url::kHttpScheme) &&
449010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      (current_page_url.scheme() != url::kHttpsScheme)))
45023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    return false;
45123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
45223730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return true;
45323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)}
454010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
455010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void ZeroSuggestProvider::MaybeUseCachedSuggestions() {
456010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial())
457010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
458010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
459010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  std::string json_data = profile_->GetPrefs()->GetString(
460010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      prefs::kZeroSuggestCachedResults);
461010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (!json_data.empty()) {
4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_ptr<base::Value> data(
4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        SearchSuggestionParser::DeserializeJsonData(json_data));
4646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (data && ParseSuggestResults(
4656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            *data, kDefaultZeroSuggestRelevance, false, &results_)) {
466010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      ConvertResultsToAutocompleteMatches();
467010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      results_from_cache_ = !matches_.empty();
468010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
469010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
470010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
471