blob: 860fb139d7935001c90c5b91df57f342468dcc5f [file] [log] [blame]
[email protected]6ce7f612012-09-05 23:53:071// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/autocomplete/zero_suggest_provider.h"
6
7#include "base/callback.h"
[email protected]bb1fb2b2013-05-31 00:21:018#include "base/i18n/case_conversion.h"
[email protected]6ce7f612012-09-05 23:53:079#include "base/json/json_string_value_serializer.h"
[email protected]bb1fb2b2013-05-31 00:21:0110#include "base/metrics/histogram.h"
[email protected]3853a4c2013-02-11 17:15:5711#include "base/prefs/pref_service.h"
[email protected]98570e12013-06-10 19:54:2212#include "base/strings/string16.h"
13#include "base/strings/string_util.h"
[email protected]135cb802013-06-09 16:44:2014#include "base/strings/utf_string_conversions.h"
[email protected]4dcb7972013-06-28 15:15:4115#include "base/time/time.h"
[email protected]2d915782013-08-29 09:50:2116#include "chrome/browser/autocomplete/autocomplete_classifier.h"
17#include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
[email protected]6ce7f612012-09-05 23:53:0718#include "chrome/browser/autocomplete/autocomplete_input.h"
19#include "chrome/browser/autocomplete/autocomplete_match.h"
20#include "chrome/browser/autocomplete/autocomplete_provider_listener.h"
[email protected]bb1fb2b2013-05-31 00:21:0121#include "chrome/browser/autocomplete/history_url_provider.h"
22#include "chrome/browser/autocomplete/search_provider.h"
23#include "chrome/browser/autocomplete/url_prefix.h"
[email protected]8f064e52013-09-18 01:17:1424#include "chrome/browser/history/history_types.h"
25#include "chrome/browser/history/top_sites.h"
[email protected]bb1fb2b2013-05-31 00:21:0126#include "chrome/browser/metrics/variations/variations_http_header_provider.h"
[email protected]bb1fb2b2013-05-31 00:21:0127#include "chrome/browser/omnibox/omnibox_field_trial.h"
[email protected]6ce7f612012-09-05 23:53:0728#include "chrome/browser/profiles/profile.h"
[email protected]bb1fb2b2013-05-31 00:21:0129#include "chrome/browser/search/search.h"
[email protected]6ce7f612012-09-05 23:53:0730#include "chrome/browser/search_engines/template_url_service.h"
31#include "chrome/browser/search_engines/template_url_service_factory.h"
[email protected]4f3b4462013-07-27 19:20:1832#include "chrome/common/net/url_fixer_upper.h"
[email protected]a00008d42012-09-15 05:07:5833#include "chrome/common/pref_names.h"
[email protected]6ce7f612012-09-05 23:53:0734#include "chrome/common/url_constants.h"
[email protected]bb1fb2b2013-05-31 00:21:0135#include "net/base/escape.h"
[email protected]6ce7f612012-09-05 23:53:0736#include "net/base/load_flags.h"
[email protected]bb1fb2b2013-05-31 00:21:0137#include "net/base/net_util.h"
38#include "net/http/http_request_headers.h"
[email protected]6ce7f612012-09-05 23:53:0739#include "net/http/http_response_headers.h"
40#include "net/url_request/url_fetcher.h"
41#include "net/url_request/url_request_status.h"
[email protected]761fa4702013-07-02 15:25:1542#include "url/gurl.h"
[email protected]6ce7f612012-09-05 23:53:0743
44namespace {
[email protected]bb1fb2b2013-05-31 00:21:0145
46// TODO(hfung): The histogram code was copied and modified from
47// search_provider.cc. Refactor and consolidate the code.
48// We keep track in a histogram how many suggest requests we send, how
49// many suggest requests we invalidate (e.g., due to a user typing
50// another character), and how many replies we receive.
51// *** ADD NEW ENUMS AFTER ALL PREVIOUSLY DEFINED ONES! ***
52// (excluding the end-of-list enum value)
53// We do not want values of existing enums to change or else it screws
54// up the statistics.
55enum ZeroSuggestRequestsHistogramValue {
56 ZERO_SUGGEST_REQUEST_SENT = 1,
57 ZERO_SUGGEST_REQUEST_INVALIDATED,
58 ZERO_SUGGEST_REPLY_RECEIVED,
59 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE
60};
61
62void LogOmniboxZeroSuggestRequest(
63 ZeroSuggestRequestsHistogramValue request_value) {
64 UMA_HISTOGRAM_ENUMERATION("Omnibox.ZeroSuggestRequests", request_value,
65 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE);
66}
67
68// The maximum relevance of the top match from this provider.
69const int kDefaultVerbatimZeroSuggestRelevance = 1300;
70
71// Relevance value to use if it was not set explicitly by the server.
72const int kDefaultZeroSuggestRelevance = 100;
73
[email protected]6ce7f612012-09-05 23:53:0774} // namespace
75
[email protected]a00008d42012-09-15 05:07:5876// static
77ZeroSuggestProvider* ZeroSuggestProvider::Create(
78 AutocompleteProviderListener* listener,
79 Profile* profile) {
[email protected]bb1fb2b2013-05-31 00:21:0180 return new ZeroSuggestProvider(listener, profile);
[email protected]6ce7f612012-09-05 23:53:0781}
82
[email protected]6ce7f612012-09-05 23:53:0783void ZeroSuggestProvider::Start(const AutocompleteInput& input,
84 bool /*minimal_changes*/) {
[email protected]bb1fb2b2013-05-31 00:21:0185}
86
87void ZeroSuggestProvider::Stop(bool clear_cached_results) {
88 if (have_pending_request_)
89 LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_INVALIDATED);
90 have_pending_request_ = false;
91 fetcher_.reset();
92 done_ = true;
93 if (clear_cached_results) {
94 query_matches_map_.clear();
95 navigation_results_.clear();
96 current_query_.clear();
97 matches_.clear();
98 }
99}
100
[email protected]bb1fb2b2013-05-31 00:21:01101void ZeroSuggestProvider::ResetSession() {
102 // The user has started editing in the omnibox, so leave
103 // |field_trial_triggered_in_session_| unchanged and set
104 // |field_trial_triggered_| to false since zero suggest is inactive now.
105 field_trial_triggered_ = false;
[email protected]9c97f89c2013-06-25 03:12:16106 Stop(true);
[email protected]bb1fb2b2013-05-31 00:21:01107}
108
109void ZeroSuggestProvider::OnURLFetchComplete(const net::URLFetcher* source) {
110 have_pending_request_ = false;
111 LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REPLY_RECEIVED);
112
113 std::string json_data;
114 source->GetResponseAsString(&json_data);
115 const bool request_succeeded =
116 source->GetStatus().is_success() && source->GetResponseCode() == 200;
117
[email protected]bb1fb2b2013-05-31 00:21:01118 if (request_succeeded) {
[email protected]843e4afb2014-02-07 23:11:03119 scoped_ptr<base::Value> data(DeserializeJsonData(json_data));
[email protected]8f064e52013-09-18 01:17:14120 if (data.get())
[email protected]bb1fb2b2013-05-31 00:21:01121 ParseSuggestResults(*data.get());
[email protected]bb1fb2b2013-05-31 00:21:01122 }
123 done_ = true;
124
[email protected]8f064e52013-09-18 01:17:14125 ConvertResultsToAutocompleteMatches();
126 if (!matches_.empty())
[email protected]bb1fb2b2013-05-31 00:21:01127 listener_->OnProviderUpdate(true);
[email protected]6ce7f612012-09-05 23:53:07128}
129
[email protected]25d7e742013-07-30 17:31:06130void ZeroSuggestProvider::StartZeroSuggest(
[email protected]9b9fa672013-11-07 06:04:52131 const GURL& current_page_url,
[email protected]25d7e742013-07-30 17:31:06132 AutocompleteInput::PageClassification page_classification,
[email protected]96920152013-12-04 21:00:16133 const base::string16& permanent_text) {
[email protected]bb1fb2b2013-05-31 00:21:01134 Stop(true);
135 field_trial_triggered_ = false;
136 field_trial_triggered_in_session_ = false;
[email protected]9b9fa672013-11-07 06:04:52137 permanent_text_ = permanent_text;
138 current_query_ = current_page_url.spec();
139 current_page_classification_ = page_classification;
140 current_url_match_ = MatchForCurrentURL();
141
142 const TemplateURL* default_provider =
143 template_url_service_->GetDefaultSearchProvider();
144 if (default_provider == NULL)
145 return;
[email protected]96920152013-12-04 21:00:16146 base::string16 prefix;
[email protected]9b9fa672013-11-07 06:04:52147 TemplateURLRef::SearchTermsArgs search_term_args(prefix);
148 search_term_args.current_page_url = current_query_;
149 GURL suggest_url(default_provider->suggestions_url_ref().
150 ReplaceSearchTerms(search_term_args));
[email protected]843e4afb2014-02-07 23:11:03151 if (!CanSendURL(current_page_url, suggest_url,
[email protected]9b9fa672013-11-07 06:04:52152 template_url_service_->GetDefaultSearchProvider(),
153 page_classification, profile_) ||
154 !OmniboxFieldTrial::InZeroSuggestFieldTrial())
[email protected]6ce7f612012-09-05 23:53:07155 return;
[email protected]bb1fb2b2013-05-31 00:21:01156 verbatim_relevance_ = kDefaultVerbatimZeroSuggestRelevance;
[email protected]6ce7f612012-09-05 23:53:07157 done_ = false;
[email protected]6ce7f612012-09-05 23:53:07158 // TODO(jered): Consider adding locally-sourced zero-suggestions here too.
159 // These may be useful on the NTP or more relevant to the user than server
160 // suggestions, if based on local browsing history.
[email protected]9b9fa672013-11-07 06:04:52161 Run(suggest_url);
[email protected]6ce7f612012-09-05 23:53:07162}
163
[email protected]bb1fb2b2013-05-31 00:21:01164ZeroSuggestProvider::ZeroSuggestProvider(
165 AutocompleteProviderListener* listener,
166 Profile* profile)
[email protected]02346202014-02-05 05:18:30167 : BaseSearchProvider(listener, profile,
168 AutocompleteProvider::TYPE_ZERO_SUGGEST),
[email protected]bb1fb2b2013-05-31 00:21:01169 template_url_service_(TemplateURLServiceFactory::GetForProfile(profile)),
[email protected]bb1fb2b2013-05-31 00:21:01170 have_pending_request_(false),
171 verbatim_relevance_(kDefaultVerbatimZeroSuggestRelevance),
[email protected]8f064e52013-09-18 01:17:14172 weak_ptr_factory_(this) {
[email protected]6ce7f612012-09-05 23:53:07173}
174
175ZeroSuggestProvider::~ZeroSuggestProvider() {
176}
177
[email protected]02346202014-02-05 05:18:30178void ZeroSuggestProvider::FillResults(const base::Value& root_val,
179 int* verbatim_relevance,
180 SuggestResults* suggest_results,
181 NavigationResults* navigation_results) {
[email protected]96920152013-12-04 21:00:16182 base::string16 query;
[email protected]5bcdd99d2013-12-23 18:28:30183 const base::ListValue* root_list = NULL;
184 const base::ListValue* results = NULL;
185 const base::ListValue* relevances = NULL;
[email protected]bb1fb2b2013-05-31 00:21:01186 // The response includes the query, which should be empty for ZeroSuggest
187 // responses.
188 if (!root_val.GetAsList(&root_list) || !root_list->GetString(0, &query) ||
189 (!query.empty()) || !root_list->GetList(1, &results))
190 return;
191
192 // 3rd element: Description list.
[email protected]5bcdd99d2013-12-23 18:28:30193 const base::ListValue* descriptions = NULL;
[email protected]bb1fb2b2013-05-31 00:21:01194 root_list->GetList(2, &descriptions);
195
196 // 4th element: Disregard the query URL list for now.
197
198 // Reset suggested relevance information from the provider.
199 *verbatim_relevance = kDefaultVerbatimZeroSuggestRelevance;
200
201 // 5th element: Optional key-value pairs from the Suggest server.
[email protected]5bcdd99d2013-12-23 18:28:30202 const base::ListValue* types = NULL;
203 const base::DictionaryValue* extras = NULL;
[email protected]bb1fb2b2013-05-31 00:21:01204 if (root_list->GetDictionary(4, &extras)) {
205 extras->GetList("google:suggesttype", &types);
206
207 // Discard this list if its size does not match that of the suggestions.
208 if (extras->GetList("google:suggestrelevance", &relevances) &&
209 relevances->GetSize() != results->GetSize())
210 relevances = NULL;
211 extras->GetInteger("google:verbatimrelevance", verbatim_relevance);
212
213 // Check if the active suggest field trial (if any) has triggered.
214 bool triggered = false;
215 extras->GetBoolean("google:fieldtrialtriggered", &triggered);
216 field_trial_triggered_ |= triggered;
217 field_trial_triggered_in_session_ |= triggered;
218 }
219
220 // Clear the previous results now that new results are available.
221 suggest_results->clear();
222 navigation_results->clear();
223
[email protected]96920152013-12-04 21:00:16224 base::string16 result, title;
[email protected]bb1fb2b2013-05-31 00:21:01225 std::string type;
[email protected]ee6110b2014-01-09 22:26:31226 const base::string16 current_query_string16 =
227 base::ASCIIToUTF16(current_query_);
[email protected]23db6492014-01-16 02:35:30228 const std::string languages(
229 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
[email protected]bb1fb2b2013-05-31 00:21:01230 for (size_t index = 0; results->GetString(index, &result); ++index) {
231 // Google search may return empty suggestions for weird input characters,
232 // they make no sense at all and can cause problems in our code.
233 if (result.empty())
234 continue;
235
236 int relevance = kDefaultZeroSuggestRelevance;
237
238 // Apply valid suggested relevance scores; discard invalid lists.
239 if (relevances != NULL && !relevances->GetInteger(index, &relevance))
240 relevances = NULL;
241 if (types && types->GetString(index, &type) && (type == "NAVIGATION")) {
242 // Do not blindly trust the URL coming from the server to be valid.
[email protected]670d3232013-12-24 17:58:58243 GURL url(URLFixerUpper::FixupURL(
244 base::UTF16ToUTF8(result), std::string()));
[email protected]bb1fb2b2013-05-31 00:21:01245 if (url.is_valid()) {
246 if (descriptions != NULL)
247 descriptions->GetString(index, &title);
[email protected]02346202014-02-05 05:18:30248 navigation_results->push_back(NavigationResult(
[email protected]23db6492014-01-16 02:35:30249 *this, url, title, false, relevance, relevances != NULL,
250 current_query_string16, languages));
[email protected]bb1fb2b2013-05-31 00:21:01251 }
252 } else {
[email protected]02346202014-02-05 05:18:30253 suggest_results->push_back(SuggestResult(
[email protected]2c03c06b2013-12-11 20:45:02254 result, AutocompleteMatchType::SEARCH_SUGGEST, result,
255 base::string16(), std::string(), std::string(), false, relevance,
[email protected]ee6110b2014-01-09 22:26:31256 relevances != NULL, false, current_query_string16));
[email protected]bb1fb2b2013-05-31 00:21:01257 }
258 }
259}
260
261void ZeroSuggestProvider::AddSuggestResultsToMap(
[email protected]02346202014-02-05 05:18:30262 const SuggestResults& results,
[email protected]bba9e632013-06-28 22:52:19263 const TemplateURL* template_url,
[email protected]02346202014-02-05 05:18:30264 MatchMap* map) {
[email protected]bb1fb2b2013-05-31 00:21:01265 for (size_t i = 0; i < results.size(); ++i) {
[email protected]bba9e632013-06-28 22:52:19266 AddMatchToMap(results[i].relevance(), AutocompleteMatchType::SEARCH_SUGGEST,
267 template_url, results[i].suggestion(), i, map);
[email protected]bb1fb2b2013-05-31 00:21:01268 }
269}
270
[email protected]bba9e632013-06-28 22:52:19271void ZeroSuggestProvider::AddMatchToMap(int relevance,
[email protected]bb1fb2b2013-05-31 00:21:01272 AutocompleteMatch::Type type,
[email protected]bba9e632013-06-28 22:52:19273 const TemplateURL* template_url,
[email protected]96920152013-12-04 21:00:16274 const base::string16& query_string,
[email protected]bb1fb2b2013-05-31 00:21:01275 int accepted_suggestion,
[email protected]02346202014-02-05 05:18:30276 MatchMap* map) {
[email protected]ee6110b2014-01-09 22:26:31277 // Pass in query_string as the input_text to avoid bolding.
[email protected]02346202014-02-05 05:18:30278 SuggestResult suggestion(
[email protected]575b2122014-01-03 20:35:33279 query_string, type, query_string, base::string16(), std::string(),
[email protected]ee6110b2014-01-09 22:26:31280 std::string(), false, relevance, true, false, query_string);
[email protected]f3e46eec2013-06-11 14:46:28281 // TODO(samarth|melevin): use the actual omnibox margin here as well instead
282 // of passing in -1.
[email protected]843e4afb2014-02-07 23:11:03283 AutocompleteMatch match = CreateSearchSuggestion(this, AutocompleteInput(),
284 query_string, suggestion, template_url, accepted_suggestion, -1, true);
[email protected]bb1fb2b2013-05-31 00:21:01285 if (!match.destination_url.is_valid())
286 return;
287
288 // Try to add |match| to |map|. If a match for |query_string| is already in
289 // |map|, replace it if |match| is more relevant.
290 // NOTE: Keep this ToLower() call in sync with url_database.cc.
[email protected]02346202014-02-05 05:18:30291 MatchKey match_key(
[email protected]621ade062013-10-28 06:27:43292 std::make_pair(base::i18n::ToLower(query_string), std::string()));
[email protected]02346202014-02-05 05:18:30293 const std::pair<MatchMap::iterator, bool> i(map->insert(
[email protected]621ade062013-10-28 06:27:43294 std::make_pair(match_key, match)));
[email protected]bb1fb2b2013-05-31 00:21:01295 // NOTE: We purposefully do a direct relevance comparison here instead of
296 // using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items added
297 // first" rather than "items alphabetically first" when the scores are equal.
298 // The only case this matters is when a user has results with the same score
299 // that differ only by capitalization; because the history system returns
300 // results sorted by recency, this means we'll pick the most recent such
301 // result even if the precision of our relevance score is too low to
302 // distinguish the two.
303 if (!i.second && (match.relevance > i.first->second.relevance))
304 i.first->second = match;
305}
306
307AutocompleteMatch ZeroSuggestProvider::NavigationToMatch(
[email protected]02346202014-02-05 05:18:30308 const NavigationResult& navigation) {
[email protected]bb1fb2b2013-05-31 00:21:01309 AutocompleteMatch match(this, navigation.relevance(), false,
310 AutocompleteMatchType::NAVSUGGEST);
311 match.destination_url = navigation.url();
312
[email protected]23db6492014-01-16 02:35:30313 // Zero suggest results should always omit protocols and never appear bold.
[email protected]bb1fb2b2013-05-31 00:21:01314 const std::string languages(
315 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
316 match.contents = net::FormatUrl(navigation.url(), languages,
317 net::kFormatUrlOmitAll, net::UnescapeRule::SPACES, NULL, NULL, NULL);
318 match.fill_into_edit +=
319 AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(),
320 match.contents);
[email protected]bb1fb2b2013-05-31 00:21:01321
[email protected]b959d7d42013-12-13 17:26:37322 AutocompleteMatch::ClassifyLocationInString(base::string16::npos, 0,
[email protected]bb1fb2b2013-05-31 00:21:01323 match.contents.length(), ACMatchClassification::URL,
324 &match.contents_class);
[email protected]9c97f89c2013-06-25 03:12:16325
326 match.description =
327 AutocompleteMatch::SanitizeString(navigation.description());
[email protected]b959d7d42013-12-13 17:26:37328 AutocompleteMatch::ClassifyLocationInString(base::string16::npos, 0,
[email protected]9c97f89c2013-06-25 03:12:16329 match.description.length(), ACMatchClassification::NONE,
330 &match.description_class);
[email protected]bb1fb2b2013-05-31 00:21:01331 return match;
332}
333
[email protected]9b9fa672013-11-07 06:04:52334void ZeroSuggestProvider::Run(const GURL& suggest_url) {
[email protected]bb1fb2b2013-05-31 00:21:01335 have_pending_request_ = false;
336 const int kFetcherID = 1;
[email protected]bb1fb2b2013-05-31 00:21:01337 fetcher_.reset(
338 net::URLFetcher::Create(kFetcherID,
339 suggest_url,
340 net::URLFetcher::GET, this));
341 fetcher_->SetRequestContext(profile_->GetRequestContext());
342 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
343 // Add Chrome experiment state to the request headers.
344 net::HttpRequestHeaders headers;
345 chrome_variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders(
346 fetcher_->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers);
347 fetcher_->SetExtraRequestHeaders(headers.ToString());
348
349 fetcher_->Start();
[email protected]8f064e52013-09-18 01:17:14350
351 if (OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) {
352 most_visited_urls_.clear();
353 history::TopSites* ts = profile_->GetTopSites();
354 if (ts) {
355 ts->GetMostVisitedURLs(
356 base::Bind(&ZeroSuggestProvider::OnMostVisitedUrlsAvailable,
[email protected]ce767ab22013-11-12 03:50:09357 weak_ptr_factory_.GetWeakPtr()), false);
[email protected]8f064e52013-09-18 01:17:14358 }
359 }
[email protected]bb1fb2b2013-05-31 00:21:01360 have_pending_request_ = true;
361 LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_SENT);
362}
363
[email protected]5bcdd99d2013-12-23 18:28:30364void ZeroSuggestProvider::ParseSuggestResults(const base::Value& root_val) {
[email protected]02346202014-02-05 05:18:30365 SuggestResults suggest_results;
[email protected]bb1fb2b2013-05-31 00:21:01366 FillResults(root_val, &verbatim_relevance_,
367 &suggest_results, &navigation_results_);
368
369 query_matches_map_.clear();
[email protected]bba9e632013-06-28 22:52:19370 AddSuggestResultsToMap(suggest_results,
371 template_url_service_->GetDefaultSearchProvider(),
[email protected]bb1fb2b2013-05-31 00:21:01372 &query_matches_map_);
373}
374
[email protected]8f064e52013-09-18 01:17:14375void ZeroSuggestProvider::OnMostVisitedUrlsAvailable(
376 const history::MostVisitedURLList& urls) {
377 most_visited_urls_ = urls;
378}
379
[email protected]9c97f89c2013-06-25 03:12:16380void ZeroSuggestProvider::ConvertResultsToAutocompleteMatches() {
[email protected]bb1fb2b2013-05-31 00:21:01381 matches_.clear();
382
383 const TemplateURL* default_provider =
[email protected]6ce7f612012-09-05 23:53:07384 template_url_service_->GetDefaultSearchProvider();
385 // Fail if we can't set the clickthrough URL for query suggestions.
[email protected]bb1fb2b2013-05-31 00:21:01386 if (default_provider == NULL || !default_provider->SupportsReplacement())
[email protected]6ce7f612012-09-05 23:53:07387 return;
[email protected]6ce7f612012-09-05 23:53:07388
[email protected]bb1fb2b2013-05-31 00:21:01389 const int num_query_results = query_matches_map_.size();
390 const int num_nav_results = navigation_results_.size();
391 const int num_results = num_query_results + num_nav_results;
[email protected]9c97f89c2013-06-25 03:12:16392 UMA_HISTOGRAM_COUNTS("ZeroSuggest.QueryResults", num_query_results);
393 UMA_HISTOGRAM_COUNTS("ZeroSuggest.URLResults", num_nav_results);
394 UMA_HISTOGRAM_COUNTS("ZeroSuggest.AllResults", num_results);
[email protected]bb1fb2b2013-05-31 00:21:01395
[email protected]8f064e52013-09-18 01:17:14396 // Show Most Visited results after ZeroSuggest response is received.
397 if (OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) {
[email protected]3feb8b002013-10-14 23:50:13398 if (!current_url_match_.destination_url.is_valid())
399 return;
[email protected]8f064e52013-09-18 01:17:14400 matches_.push_back(current_url_match_);
401 int relevance = 600;
402 if (num_results > 0) {
403 UMA_HISTOGRAM_COUNTS(
404 "Omnibox.ZeroSuggest.MostVisitedResultsCounterfactual",
405 most_visited_urls_.size());
406 }
[email protected]23db6492014-01-16 02:35:30407 const base::string16 current_query_string16(
408 base::ASCIIToUTF16(current_query_));
409 const std::string languages(
410 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages));
[email protected]8f064e52013-09-18 01:17:14411 for (size_t i = 0; i < most_visited_urls_.size(); i++) {
412 const history::MostVisitedURL& url = most_visited_urls_[i];
[email protected]02346202014-02-05 05:18:30413 NavigationResult nav(*this, url.url, url.title, false, relevance, true,
[email protected]23db6492014-01-16 02:35:30414 current_query_string16, languages);
[email protected]8f064e52013-09-18 01:17:14415 matches_.push_back(NavigationToMatch(nav));
416 --relevance;
417 }
418 return;
419 }
420
[email protected]9c97f89c2013-06-25 03:12:16421 if (num_results == 0)
[email protected]bb1fb2b2013-05-31 00:21:01422 return;
423
424 // TODO(jered): Rip this out once the first match is decoupled from the
425 // current typing in the omnibox.
[email protected]bb1fb2b2013-05-31 00:21:01426 matches_.push_back(current_url_match_);
427
[email protected]02346202014-02-05 05:18:30428 for (MatchMap::const_iterator it(query_matches_map_.begin());
[email protected]bc8bb0cd2013-06-24 21:50:23429 it != query_matches_map_.end(); ++it)
[email protected]bb1fb2b2013-05-31 00:21:01430 matches_.push_back(it->second);
[email protected]bb1fb2b2013-05-31 00:21:01431
[email protected]02346202014-02-05 05:18:30432 for (NavigationResults::const_iterator it(navigation_results_.begin());
433 it != navigation_results_.end(); ++it)
[email protected]bb1fb2b2013-05-31 00:21:01434 matches_.push_back(NavigationToMatch(*it));
[email protected]6ce7f612012-09-05 23:53:07435}
436
[email protected]bb1fb2b2013-05-31 00:21:01437AutocompleteMatch ZeroSuggestProvider::MatchForCurrentURL() {
[email protected]96920152013-12-04 21:00:16438 AutocompleteInput input(permanent_text_, base::string16::npos, base::string16(),
[email protected]25d7e742013-07-30 17:31:06439 GURL(current_query_), current_page_classification_,
[email protected]bb1fb2b2013-05-31 00:21:01440 false, false, true, AutocompleteInput::ALL_MATCHES);
[email protected]6ce7f612012-09-05 23:53:07441
[email protected]2d915782013-08-29 09:50:21442 AutocompleteMatch match;
443 AutocompleteClassifierFactory::GetForProfile(profile_)->Classify(
444 permanent_text_, false, true, &match, NULL);
[email protected]bb1fb2b2013-05-31 00:21:01445 match.is_history_what_you_typed_match = false;
[email protected]45f89a92013-08-12 13:41:36446 match.allowed_to_be_default_match = true;
[email protected]6ce7f612012-09-05 23:53:07447
[email protected]bb1fb2b2013-05-31 00:21:01448 // The placeholder suggestion for the current URL has high relevance so
449 // that it is in the first suggestion slot and inline autocompleted. It
450 // gets dropped as soon as the user types something.
451 match.relevance = verbatim_relevance_;
[email protected]6ce7f612012-09-05 23:53:07452
[email protected]bb1fb2b2013-05-31 00:21:01453 return match;
[email protected]6ce7f612012-09-05 23:53:07454}