zero_suggest_provider.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
1cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// Use of this source code is governed by a BSD-style license that can be 3cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// found in the LICENSE file. 4cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 5cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "chrome/browser/autocomplete/zero_suggest_provider.h" 6cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 7cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "base/callback.h" 8cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "base/i18n/case_conversion.h" 9cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "base/json/json_string_value_serializer.h" 10cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "base/metrics/histogram.h" 11cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "base/prefs/pref_service.h" 12cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "base/strings/string16.h" 13cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "base/strings/string_util.h" 14cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "base/strings/utf_string_conversions.h" 15cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "base/time/time.h" 168051db16aa9513333062ab3145f038429f66780fPeter Collingbourne#include "chrome/browser/autocomplete/autocomplete_input.h" 17cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "chrome/browser/autocomplete/autocomplete_match.h" 18cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "chrome/browser/autocomplete/autocomplete_provider_listener.h" 19cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "chrome/browser/autocomplete/history_url_provider.h" 208051db16aa9513333062ab3145f038429f66780fPeter Collingbourne#include "chrome/browser/autocomplete/search_provider.h" 21cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "chrome/browser/autocomplete/url_prefix.h" 22cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "chrome/browser/metrics/variations/variations_http_header_provider.h" 23cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "chrome/browser/net/url_fixer_upper.h" 2455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "chrome/browser/omnibox/omnibox_field_trial.h" 2555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "chrome/browser/profiles/profile.h" 2601b8ca52fe94f53461de34e191935b74cecd02dbNAKAMURA Takumi#include "chrome/browser/search/search.h" 27ef8225444452a1486bd721f3285301fe84643b00Stephen Hines#include "chrome/browser/search_engines/template_url_service.h" 28b1e25a1bc03292dc538d336573e0be1490223171Reid Kleckner#include "chrome/browser/search_engines/template_url_service_factory.h" 29ad7e160e36a5010358ef33c4c81904297d62b9b2Edwin Vane#include "chrome/browser/sync/profile_sync_service.h" 30b175d0f054e2173d51eba046434410c90b4a5c61NAKAMURA Takumi#include "chrome/browser/sync/profile_sync_service_factory.h" 3101b8ca52fe94f53461de34e191935b74cecd02dbNAKAMURA Takumi#include "chrome/common/pref_names.h" 3201b8ca52fe94f53461de34e191935b74cecd02dbNAKAMURA Takumi#include "chrome/common/url_constants.h" 33cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek#include "net/base/escape.h" 343b6e319c05a3f9858cbc1ceb68fd1b1895b6d2dcManuel Klimek#include "net/base/load_flags.h" 35651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "net/base/net_util.h" 363b6e319c05a3f9858cbc1ceb68fd1b1895b6d2dcManuel Klimek#include "net/http/http_request_headers.h" 37ed5ee48872118ba3e8f747c7133d7adcacb73850Manuel Klimek#include "net/http/http_response_headers.h" 38ed5ee48872118ba3e8f747c7133d7adcacb73850Manuel Klimek#include "net/url_request/url_fetcher.h" 393b6e319c05a3f9858cbc1ceb68fd1b1895b6d2dcManuel Klimek#include "net/url_request/url_request_status.h" 403b6e319c05a3f9858cbc1ceb68fd1b1895b6d2dcManuel Klimek#include "url/gurl.h" 416bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 426bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesnamespace { 43cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 44cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// TODO(hfung): The histogram code was copied and modified from 45cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// search_provider.cc. Refactor and consolidate the code. 468051db16aa9513333062ab3145f038429f66780fPeter Collingbourne// We keep track in a histogram how many suggest requests we send, how 478051db16aa9513333062ab3145f038429f66780fPeter Collingbourne// many suggest requests we invalidate (e.g., due to a user typing 48cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// another character), and how many replies we receive. 49cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// *** ADD NEW ENUMS AFTER ALL PREVIOUSLY DEFINED ONES! *** 50cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// (excluding the end-of-list enum value) 51cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// We do not want values of existing enums to change or else it screws 52cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// up the statistics. 53cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimekenum ZeroSuggestRequestsHistogramValue { 54cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek ZERO_SUGGEST_REQUEST_SENT = 1, 55cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek ZERO_SUGGEST_REQUEST_INVALIDATED, 56cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek ZERO_SUGGEST_REPLY_RECEIVED, 57cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE 586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines}; 59cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 60cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimekvoid LogOmniboxZeroSuggestRequest( 61cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek ZeroSuggestRequestsHistogramValue request_value) { 62cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek UMA_HISTOGRAM_ENUMERATION("Omnibox.ZeroSuggestRequests", request_value, 63cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE); 64cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} 65cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 66b1e25a1bc03292dc538d336573e0be1490223171Reid Kleckner// The maximum relevance of the top match from this provider. 67cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimekconst int kDefaultVerbatimZeroSuggestRelevance = 1300; 68cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 69cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// Relevance value to use if it was not set explicitly by the server. 70cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimekconst int kDefaultZeroSuggestRelevance = 100; 71cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 72cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} // namespace 73cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko 74cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek// static 75fc3389701ead32709ba84825e4c06651065da2c0Hans WennborgZeroSuggestProvider* ZeroSuggestProvider::Create( 76cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek AutocompleteProviderListener* listener, 77cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek Profile* profile) { 786bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return new ZeroSuggestProvider(listener, profile); 79cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} 80cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 81cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimekvoid ZeroSuggestProvider::Start(const AutocompleteInput& input, 82cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek bool /*minimal_changes*/) { 83cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} 84cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 85cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimekvoid ZeroSuggestProvider::Stop(bool clear_cached_results) { 866bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (have_pending_request_) 87cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_INVALIDATED); 88cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek have_pending_request_ = false; 89cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek fetcher_.reset(); 90cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek done_ = true; 91cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek if (clear_cached_results) { 92cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek query_matches_map_.clear(); 93cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek navigation_results_.clear(); 94cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek current_query_.clear(); 95b1e25a1bc03292dc538d336573e0be1490223171Reid Kleckner matches_.clear(); 96cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek } 97cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} 98cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 99cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimekvoid ZeroSuggestProvider::AddProviderInfo(ProvidersInfo* provider_info) const { 100cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo()); 101cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back(); 102fe7ed9ec307ed6bcb962b6780bf3a156420662b3Nick Lewycky new_entry.set_provider(AsOmniboxEventProviderType()); 103651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines new_entry.set_provider_done(done_); 104cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek std::vector<uint32> field_trial_hashes; 105cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek OmniboxFieldTrial::GetActiveSuggestFieldTrialHashes(&field_trial_hashes); 106cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek for (size_t i = 0; i < field_trial_hashes.size(); ++i) { 107cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek if (field_trial_triggered_) 108cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek new_entry.mutable_field_trial_triggered()->Add(field_trial_hashes[i]); 109566698851d76416129cd20ceea02bdd697934c5cNico Weber if (field_trial_triggered_in_session_) { 110566698851d76416129cd20ceea02bdd697934c5cNico Weber new_entry.mutable_field_trial_triggered_in_session()->Add( 111566698851d76416129cd20ceea02bdd697934c5cNico Weber field_trial_hashes[i]); 112566698851d76416129cd20ceea02bdd697934c5cNico Weber } 1138051db16aa9513333062ab3145f038429f66780fPeter Collingbourne } 1148051db16aa9513333062ab3145f038429f66780fPeter Collingbourne} 1158051db16aa9513333062ab3145f038429f66780fPeter Collingbourne 1168051db16aa9513333062ab3145f038429f66780fPeter Collingbournevoid ZeroSuggestProvider::ResetSession() { 1178051db16aa9513333062ab3145f038429f66780fPeter Collingbourne // The user has started editing in the omnibox, so leave 1188051db16aa9513333062ab3145f038429f66780fPeter Collingbourne // |field_trial_triggered_in_session_| unchanged and set 1198051db16aa9513333062ab3145f038429f66780fPeter Collingbourne // |field_trial_triggered_| to false since zero suggest is inactive now. 1208051db16aa9513333062ab3145f038429f66780fPeter Collingbourne field_trial_triggered_ = false; 1218051db16aa9513333062ab3145f038429f66780fPeter Collingbourne Stop(true); 1228051db16aa9513333062ab3145f038429f66780fPeter Collingbourne} 1238051db16aa9513333062ab3145f038429f66780fPeter Collingbourne 124566698851d76416129cd20ceea02bdd697934c5cNico Webervoid ZeroSuggestProvider::OnURLFetchComplete(const net::URLFetcher* source) { 125566698851d76416129cd20ceea02bdd697934c5cNico Weber have_pending_request_ = false; 126566698851d76416129cd20ceea02bdd697934c5cNico Weber LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REPLY_RECEIVED); 127cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 128cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek std::string json_data; 1298051db16aa9513333062ab3145f038429f66780fPeter Collingbourne source->GetResponseAsString(&json_data); 1308051db16aa9513333062ab3145f038429f66780fPeter Collingbourne const bool request_succeeded = 1318051db16aa9513333062ab3145f038429f66780fPeter Collingbourne source->GetStatus().is_success() && source->GetResponseCode() == 200; 132ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 133cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek bool have_results = false; 134cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek if (request_succeeded) { 135cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek JSONStringValueSerializer deserializer(json_data); 136cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek deserializer.set_allow_trailing_comma(true); 137cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek scoped_ptr<Value> data(deserializer.Deserialize(NULL, NULL)); 138cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek if (data.get()) { 139cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek ParseSuggestResults(*data.get()); 1408fa2fb859a4cb8e67d9763225281d9b0aa9cb59fManuel Klimek have_results = !query_matches_map_.empty() || 141cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek !navigation_results_.empty(); 14262d198c5b1174279174eb35d222b5cee46f3ef6fNAKAMURA Takumi } 143cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek } 144cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek done_ = true; 145cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 146a2148240bd94ef659a9195b87e9cd0023536c01fRafael Espindola if (have_results) { 147a2148240bd94ef659a9195b87e9cd0023536c01fRafael Espindola ConvertResultsToAutocompleteMatches(); 148ef8225444452a1486bd721f3285301fe84643b00Stephen Hines listener_->OnProviderUpdate(true); 149a2148240bd94ef659a9195b87e9cd0023536c01fRafael Espindola } 150bcb2500463e898e96656025c7742ae13eba7647eRafael Espindola} 1510f599acfd685437d1344f82ce363f994b0729a2fBenjamin Kramer 1520f599acfd685437d1344f82ce363f994b0729a2fBenjamin Kramervoid ZeroSuggestProvider::StartZeroSuggest(const GURL& url, 153cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek const string16& permanent_text) { 154cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek Stop(true); 1558051db16aa9513333062ab3145f038429f66780fPeter Collingbourne field_trial_triggered_ = false; 1568051db16aa9513333062ab3145f038429f66780fPeter Collingbourne field_trial_triggered_in_session_ = false; 1578051db16aa9513333062ab3145f038429f66780fPeter Collingbourne if (!ShouldRunZeroSuggest(url)) 1588051db16aa9513333062ab3145f038429f66780fPeter Collingbourne return; 1598051db16aa9513333062ab3145f038429f66780fPeter Collingbourne verbatim_relevance_ = kDefaultVerbatimZeroSuggestRelevance; 1608051db16aa9513333062ab3145f038429f66780fPeter Collingbourne done_ = false; 1618051db16aa9513333062ab3145f038429f66780fPeter Collingbourne permanent_text_ = permanent_text; 1628051db16aa9513333062ab3145f038429f66780fPeter Collingbourne current_query_ = url.spec(); 163651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines current_url_match_ = MatchForCurrentURL(); 1648051db16aa9513333062ab3145f038429f66780fPeter Collingbourne // TODO(jered): Consider adding locally-sourced zero-suggestions here too. 1658051db16aa9513333062ab3145f038429f66780fPeter Collingbourne // These may be useful on the NTP or more relevant to the user than server 1668051db16aa9513333062ab3145f038429f66780fPeter Collingbourne // suggestions, if based on local browsing history. 1678051db16aa9513333062ab3145f038429f66780fPeter Collingbourne Run(); 168651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 1698051db16aa9513333062ab3145f038429f66780fPeter Collingbourne 170651f13cea278ec967336033dd032faef0e9fc2ecStephen HinesZeroSuggestProvider::ZeroSuggestProvider( 171fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek AutocompleteProviderListener* listener, 172fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek Profile* profile) 173fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek : AutocompleteProvider(listener, profile, 1746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines AutocompleteProvider::TYPE_ZERO_SUGGEST), 1758051db16aa9513333062ab3145f038429f66780fPeter Collingbourne template_url_service_(TemplateURLServiceFactory::GetForProfile(profile)), 176651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines have_pending_request_(false), 1778051db16aa9513333062ab3145f038429f66780fPeter Collingbourne verbatim_relevance_(kDefaultVerbatimZeroSuggestRelevance), 178651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines field_trial_triggered_(false), 179fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek field_trial_triggered_in_session_(false) { 180fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek} 181fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek 1826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen HinesZeroSuggestProvider::~ZeroSuggestProvider() { 1838051db16aa9513333062ab3145f038429f66780fPeter Collingbourne} 1848051db16aa9513333062ab3145f038429f66780fPeter Collingbourne 1858051db16aa9513333062ab3145f038429f66780fPeter Collingbournebool ZeroSuggestProvider::ShouldRunZeroSuggest(const GURL& url) const { 1868051db16aa9513333062ab3145f038429f66780fPeter Collingbourne if (!url.is_valid()) 187cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek return false; 188cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 189fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek // Do not query non-http URLs. There will be no useful suggestions for https 190fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek // or chrome URLs. 191fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek if (url.scheme() != chrome::kHttpScheme) 192fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek return false; 193cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 1940ef8db20b32aaa027c2fbd230c46c22b4b47079dNAKAMURA Takumi // Don't enable ZeroSuggest until InstantExtended works with ZeroSuggest. 1950ef8db20b32aaa027c2fbd230c46c22b4b47079dNAKAMURA Takumi if (chrome::IsInstantExtendedAPIEnabled()) 1960ef8db20b32aaa027c2fbd230c46c22b4b47079dNAKAMURA Takumi return false; 197cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 198cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek // Don't run if there's no profile or in incognito mode. 199cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek if (profile_ == NULL || profile_->IsOffTheRecord()) 200cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek return false; 201651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 202651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Don't run if we can't get preferences or search suggest is not enabled. 203cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek PrefService* prefs = profile_->GetPrefs(); 20402c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor if (prefs == NULL || !prefs->GetBoolean(prefs::kSearchSuggestEnabled)) 205cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek return false; 20602c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor 20702c23ebf41ae2f70da0ba7337e05c51fbfe35f7fDouglas Gregor ProfileSyncService* service = 208fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_); 209fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek browser_sync::SyncPrefs sync_prefs(prefs); 210cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek // The user has needs to have Chrome Sync enabled (for permissions to 211651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // transmit their current URL) and be in the field trial. 212cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek if (!OmniboxFieldTrial::InZeroSuggestFieldTrial() || 213cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek service == NULL || 214cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek !service->IsSyncEnabledAndLoggedIn() || 215651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines !sync_prefs.HasKeepEverythingSynced()) { 216cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek return false; 217b1e25a1bc03292dc538d336573e0be1490223171Reid Kleckner } 218cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek return true; 2196bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 220cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 221cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimekvoid ZeroSuggestProvider::FillResults( 222651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const Value& root_val, 223cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek int* verbatim_relevance, 224651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SearchProvider::SuggestResults* suggest_results, 2258051db16aa9513333062ab3145f038429f66780fPeter Collingbourne SearchProvider::NavigationResults* navigation_results) { 226651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines string16 query; 227651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ListValue* root_list = NULL; 2288051db16aa9513333062ab3145f038429f66780fPeter Collingbourne const ListValue* results = NULL; 229651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ListValue* relevances = NULL; 230cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek // The response includes the query, which should be empty for ZeroSuggest 231cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek // responses. 232cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek if (!root_val.GetAsList(&root_list) || !root_list->GetString(0, &query) || 233cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek (!query.empty()) || !root_list->GetList(1, &results)) 234cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek return; 235d47afb96a3f988e6d21a92fe4dfe875ab227c7c0Sean Silva 236cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek // 3rd element: Description list. 237cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek const ListValue* descriptions = NULL; 238cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek root_list->GetList(2, &descriptions); 239fc3389701ead32709ba84825e4c06651065da2c0Hans Wennborg 240cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek // 4th element: Disregard the query URL list for now. 241cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 242cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek // Reset suggested relevance information from the provider. 243fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek *verbatim_relevance = kDefaultVerbatimZeroSuggestRelevance; 2448051db16aa9513333062ab3145f038429f66780fPeter Collingbourne 2458051db16aa9513333062ab3145f038429f66780fPeter Collingbourne // 5th element: Optional key-value pairs from the Suggest server. 2468051db16aa9513333062ab3145f038429f66780fPeter Collingbourne const ListValue* types = NULL; 247fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek const DictionaryValue* extras = NULL; 248fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek if (root_list->GetDictionary(4, &extras)) { 249cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek extras->GetList("google:suggesttype", &types); 250cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 251cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek // Discard this list if its size does not match that of the suggestions. 252cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek if (extras->GetList("google:suggestrelevance", &relevances) && 253cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek relevances->GetSize() != results->GetSize()) 2548051db16aa9513333062ab3145f038429f66780fPeter Collingbourne relevances = NULL; 2558051db16aa9513333062ab3145f038429f66780fPeter Collingbourne extras->GetInteger("google:verbatimrelevance", verbatim_relevance); 256651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 257651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Check if the active suggest field trial (if any) has triggered. 25814a192435425af39e7f32b6e71613f9357e995f7Alexander Kornienko bool triggered = false; 2596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines extras->GetBoolean("google:fieldtrialtriggered", &triggered); 260fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek field_trial_triggered_ |= triggered; 261cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek field_trial_triggered_in_session_ |= triggered; 262cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek } 263cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 264cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek // Clear the previous results now that new results are available. 265cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek suggest_results->clear(); 26614a192435425af39e7f32b6e71613f9357e995f7Alexander Kornienko navigation_results->clear(); 267cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 26898be86038b1e891a05583061c55dfa974150eb2cManuel Klimek string16 result, title; 269cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek std::string type; 270cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek for (size_t index = 0; results->GetString(index, &result); ++index) { 271cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek // Google search may return empty suggestions for weird input characters, 272cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek // they make no sense at all and can cause problems in our code. 273cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek if (result.empty()) 2746bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines continue; 27563d5335aea916584b76790af1f1ed7caeaf8efebPavel Labath 27663d5335aea916584b76790af1f1ed7caeaf8efebPavel Labath int relevance = kDefaultZeroSuggestRelevance; 277651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 278651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Apply valid suggested relevance scores; discard invalid lists. 279cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek if (relevances != NULL && !relevances->GetInteger(index, &relevance)) 28000f3c4f499cc27c88005176226bb424f6db4a31bManuel Klimek relevances = NULL; 281651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (types && types->GetString(index, &type) && (type == "NAVIGATION")) { 28200f3c4f499cc27c88005176226bb424f6db4a31bManuel Klimek // Do not blindly trust the URL coming from the server to be valid. 283651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines GURL url(URLFixerUpper::FixupURL(UTF16ToUTF8(result), std::string())); 284651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (url.is_valid()) { 285651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (descriptions != NULL) 286cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek descriptions->GetString(index, &title); 287cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek navigation_results->push_back(SearchProvider::NavigationResult( 288cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek *this, url, title, false, relevance, relevances != NULL)); 289cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek } 290cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek } else { 291cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek suggest_results->push_back(SearchProvider::SuggestResult( 292cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek result, false, relevance, relevances != NULL)); 2936bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 294cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek } 295cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} 296cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 297cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimekvoid ZeroSuggestProvider::AddSuggestResultsToMap( 298fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek const SearchProvider::SuggestResults& results, 299fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek const TemplateURL* template_url, 300fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek SearchProvider::MatchMap* map) { 301fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek for (size_t i = 0; i < results.size(); ++i) { 302cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek AddMatchToMap(results[i].relevance(), AutocompleteMatchType::SEARCH_SUGGEST, 303cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek template_url, results[i].suggestion(), i, map); 304cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek } 305cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} 306a01ddc787b5c8b1cf11e975d3586908d3629954cSimon Atanasyan 30748b3f0f74da575a66802dc5019b7440914983885Manuel Klimekvoid ZeroSuggestProvider::AddMatchToMap(int relevance, 30848b3f0f74da575a66802dc5019b7440914983885Manuel Klimek AutocompleteMatch::Type type, 30948b3f0f74da575a66802dc5019b7440914983885Manuel Klimek const TemplateURL* template_url, 31048b3f0f74da575a66802dc5019b7440914983885Manuel Klimek const string16& query_string, 31148b3f0f74da575a66802dc5019b7440914983885Manuel Klimek int accepted_suggestion, 31248b3f0f74da575a66802dc5019b7440914983885Manuel Klimek SearchProvider::MatchMap* map) { 31348b3f0f74da575a66802dc5019b7440914983885Manuel Klimek // Pass in query_string as the input_text since we don't want any bolding. 31448b3f0f74da575a66802dc5019b7440914983885Manuel Klimek // TODO(samarth|melevin): use the actual omnibox margin here as well instead 31548b3f0f74da575a66802dc5019b7440914983885Manuel Klimek // of passing in -1. 31648b3f0f74da575a66802dc5019b7440914983885Manuel Klimek AutocompleteMatch match = SearchProvider::CreateSearchSuggestion( 31748b3f0f74da575a66802dc5019b7440914983885Manuel Klimek this, relevance, type, template_url, query_string, query_string, 31848b3f0f74da575a66802dc5019b7440914983885Manuel Klimek AutocompleteInput(), false, accepted_suggestion, -1, true); 319a01ddc787b5c8b1cf11e975d3586908d3629954cSimon Atanasyan if (!match.destination_url.is_valid()) 320a01ddc787b5c8b1cf11e975d3586908d3629954cSimon Atanasyan return; 3218051db16aa9513333062ab3145f038429f66780fPeter Collingbourne 32230c009b5fa4d22ddabfe6ad6ba4158a664a4bd83Alexander Kornienko // Try to add |match| to |map|. If a match for |query_string| is already in 32330c009b5fa4d22ddabfe6ad6ba4158a664a4bd83Alexander Kornienko // |map|, replace it if |match| is more relevant. 32430c009b5fa4d22ddabfe6ad6ba4158a664a4bd83Alexander Kornienko // NOTE: Keep this ToLower() call in sync with url_database.cc. 32530c009b5fa4d22ddabfe6ad6ba4158a664a4bd83Alexander Kornienko const std::pair<SearchProvider::MatchMap::iterator, bool> i(map->insert( 32630c009b5fa4d22ddabfe6ad6ba4158a664a4bd83Alexander Kornienko std::make_pair(base::i18n::ToLower(query_string), match))); 32730c009b5fa4d22ddabfe6ad6ba4158a664a4bd83Alexander Kornienko // NOTE: We purposefully do a direct relevance comparison here instead of 32830c009b5fa4d22ddabfe6ad6ba4158a664a4bd83Alexander Kornienko // using AutocompleteMatch::MoreRelevant(), so that we'll prefer "items added 32930c009b5fa4d22ddabfe6ad6ba4158a664a4bd83Alexander Kornienko // first" rather than "items alphabetically first" when the scores are equal. 33030c009b5fa4d22ddabfe6ad6ba4158a664a4bd83Alexander Kornienko // The only case this matters is when a user has results with the same score 331ac1db6b2bde50e9a0f3846243f654f6c13682725Rafael Espindola // that differ only by capitalization; because the history system returns 33230c009b5fa4d22ddabfe6ad6ba4158a664a4bd83Alexander Kornienko // results sorted by recency, this means we'll pick the most recent such 333cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek // result even if the precision of our relevance score is too low to 334651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // distinguish the two. 33500f3c4f499cc27c88005176226bb424f6db4a31bManuel Klimek if (!i.second && (match.relevance > i.first->second.relevance)) 33600f3c4f499cc27c88005176226bb424f6db4a31bManuel Klimek i.first->second = match; 33700f3c4f499cc27c88005176226bb424f6db4a31bManuel Klimek} 33800f3c4f499cc27c88005176226bb424f6db4a31bManuel Klimek 33930c009b5fa4d22ddabfe6ad6ba4158a664a4bd83Alexander KornienkoAutocompleteMatch ZeroSuggestProvider::NavigationToMatch( 34000f3c4f499cc27c88005176226bb424f6db4a31bManuel Klimek const SearchProvider::NavigationResult& navigation) { 34100f3c4f499cc27c88005176226bb424f6db4a31bManuel Klimek AutocompleteMatch match(this, navigation.relevance(), false, 342651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines AutocompleteMatchType::NAVSUGGEST); 34300f3c4f499cc27c88005176226bb424f6db4a31bManuel Klimek match.destination_url = navigation.url(); 344651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 345651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const std::string languages( 346651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines profile_->GetPrefs()->GetString(prefs::kAcceptLanguages)); 347651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines match.contents = net::FormatUrl(navigation.url(), languages, 34830c009b5fa4d22ddabfe6ad6ba4158a664a4bd83Alexander Kornienko net::kFormatUrlOmitAll, net::UnescapeRule::SPACES, NULL, NULL, NULL); 34930c009b5fa4d22ddabfe6ad6ba4158a664a4bd83Alexander Kornienko match.fill_into_edit += 350ad7e160e36a5010358ef33c4c81904297d62b9b2Edwin Vane AutocompleteInput::FormattedStringWithEquivalentMeaning(navigation.url(), 351ad7e160e36a5010358ef33c4c81904297d62b9b2Edwin Vane match.contents); 352ad7e160e36a5010358ef33c4c81904297d62b9b2Edwin Vane match.inline_autocomplete_offset = string16::npos; 353651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 354ad7e160e36a5010358ef33c4c81904297d62b9b2Edwin Vane AutocompleteMatch::ClassifyLocationInString(string16::npos, 0, 355ef8225444452a1486bd721f3285301fe84643b00Stephen Hines match.contents.length(), ACMatchClassification::URL, 356fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek &match.contents_class); 357651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 358651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines match.description = 359cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek AutocompleteMatch::SanitizeString(navigation.description()); 360cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek AutocompleteMatch::ClassifyLocationInString(string16::npos, 0, 361ad7e160e36a5010358ef33c4c81904297d62b9b2Edwin Vane match.description.length(), ACMatchClassification::NONE, 362651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines &match.description_class); 363cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek return match; 364cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek} 365cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek 366cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimekvoid ZeroSuggestProvider::Run() { 367cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek have_pending_request_ = false; 368cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek const int kFetcherID = 1; 3698051db16aa9513333062ab3145f038429f66780fPeter Collingbourne 3708051db16aa9513333062ab3145f038429f66780fPeter Collingbourne const TemplateURL* default_provider = 3718051db16aa9513333062ab3145f038429f66780fPeter Collingbourne template_url_service_->GetDefaultSearchProvider(); 3726bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // TODO(hfung): Generalize if the default provider supports zero suggest. 3738051db16aa9513333062ab3145f038429f66780fPeter Collingbourne // Only make the request if we know that the provider supports zero suggest 3748051db16aa9513333062ab3145f038429f66780fPeter Collingbourne // (currently only the prepopulated Google provider). 3756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (default_provider == NULL || !default_provider->SupportsReplacement() || 3768051db16aa9513333062ab3145f038429f66780fPeter Collingbourne default_provider->prepopulate_id() != 1) { 377fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek Stop(true); 378651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return; 3798051db16aa9513333062ab3145f038429f66780fPeter Collingbourne } 3806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines string16 prefix; 381fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek TemplateURLRef::SearchTermsArgs search_term_args(prefix); 382fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek search_term_args.zero_prefix_url = current_query_; 383fa8e7d344fc6ac9bf464419cc9cc2743b5036047Manuel Klimek std::string req_url = default_provider->suggestions_url_ref(). 3848051db16aa9513333062ab3145f038429f66780fPeter Collingbourne ReplaceSearchTerms(search_term_args); 3858051db16aa9513333062ab3145f038429f66780fPeter Collingbourne GURL suggest_url(req_url); 3868051db16aa9513333062ab3145f038429f66780fPeter Collingbourne // Make sure we are sending the suggest request through HTTPS. 3876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (!suggest_url.SchemeIs(chrome::kHttpsScheme)) { 3888051db16aa9513333062ab3145f038429f66780fPeter Collingbourne Stop(true); 3898051db16aa9513333062ab3145f038429f66780fPeter Collingbourne return; 3908051db16aa9513333062ab3145f038429f66780fPeter Collingbourne } 3918051db16aa9513333062ab3145f038429f66780fPeter Collingbourne 3928051db16aa9513333062ab3145f038429f66780fPeter Collingbourne fetcher_.reset( 3938051db16aa9513333062ab3145f038429f66780fPeter Collingbourne net::URLFetcher::Create(kFetcherID, 3946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines suggest_url, 3958051db16aa9513333062ab3145f038429f66780fPeter Collingbourne net::URLFetcher::GET, this)); 3968051db16aa9513333062ab3145f038429f66780fPeter Collingbourne fetcher_->SetRequestContext(profile_->GetRequestContext()); 3978051db16aa9513333062ab3145f038429f66780fPeter Collingbourne fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES); 3988051db16aa9513333062ab3145f038429f66780fPeter Collingbourne // Add Chrome experiment state to the request headers. 3996bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines net::HttpRequestHeaders headers; 4006bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines chrome_variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders( 4018051db16aa9513333062ab3145f038429f66780fPeter Collingbourne fetcher_->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers); 4028051db16aa9513333062ab3145f038429f66780fPeter Collingbourne fetcher_->SetExtraRequestHeaders(headers.ToString()); 4038051db16aa9513333062ab3145f038429f66780fPeter Collingbourne 4046bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines fetcher_->Start(); 4056bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines have_pending_request_ = true; 4066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_SENT); 4076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines} 4088051db16aa9513333062ab3145f038429f66780fPeter Collingbourne 4098051db16aa9513333062ab3145f038429f66780fPeter Collingbournevoid ZeroSuggestProvider::ParseSuggestResults(const Value& root_val) { 4108051db16aa9513333062ab3145f038429f66780fPeter Collingbourne SearchProvider::SuggestResults suggest_results; 4116bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines FillResults(root_val, &verbatim_relevance_, 4128051db16aa9513333062ab3145f038429f66780fPeter Collingbourne &suggest_results, &navigation_results_); 4136bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 4146bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines query_matches_map_.clear(); 4158051db16aa9513333062ab3145f038429f66780fPeter Collingbourne AddSuggestResultsToMap(suggest_results, 4168051db16aa9513333062ab3145f038429f66780fPeter Collingbourne template_url_service_->GetDefaultSearchProvider(), 4178051db16aa9513333062ab3145f038429f66780fPeter Collingbourne &query_matches_map_); 4188051db16aa9513333062ab3145f038429f66780fPeter Collingbourne} 4198051db16aa9513333062ab3145f038429f66780fPeter Collingbourne 4206bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesvoid ZeroSuggestProvider::ConvertResultsToAutocompleteMatches() { 4218051db16aa9513333062ab3145f038429f66780fPeter Collingbourne matches_.clear(); 4228051db16aa9513333062ab3145f038429f66780fPeter Collingbourne 4236bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines const TemplateURL* default_provider = 4248051db16aa9513333062ab3145f038429f66780fPeter Collingbourne template_url_service_->GetDefaultSearchProvider(); 4258051db16aa9513333062ab3145f038429f66780fPeter Collingbourne // Fail if we can't set the clickthrough URL for query suggestions. 426cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek if (default_provider == NULL || !default_provider->SupportsReplacement()) 427cb971c6726d16e12ecd2a340941d7f5c06698332Manuel Klimek return; 428 429 const int num_query_results = query_matches_map_.size(); 430 const int num_nav_results = navigation_results_.size(); 431 const int num_results = num_query_results + num_nav_results; 432 UMA_HISTOGRAM_COUNTS("ZeroSuggest.QueryResults", num_query_results); 433 UMA_HISTOGRAM_COUNTS("ZeroSuggest.URLResults", num_nav_results); 434 UMA_HISTOGRAM_COUNTS("ZeroSuggest.AllResults", num_results); 435 436 if (num_results == 0) 437 return; 438 439 // TODO(jered): Rip this out once the first match is decoupled from the 440 // current typing in the omnibox. 441 matches_.push_back(current_url_match_); 442 443 for (SearchProvider::MatchMap::const_iterator it(query_matches_map_.begin()); 444 it != query_matches_map_.end(); ++it) 445 matches_.push_back(it->second); 446 447 for (SearchProvider::NavigationResults::const_iterator it( 448 navigation_results_.begin()); it != navigation_results_.end(); ++it) 449 matches_.push_back(NavigationToMatch(*it)); 450} 451 452AutocompleteMatch ZeroSuggestProvider::MatchForCurrentURL() { 453 AutocompleteInput input(permanent_text_, string16::npos, 454 string16(), GURL(current_query_), 455 false, false, true, AutocompleteInput::ALL_MATCHES); 456 457 AutocompleteMatch match( 458 HistoryURLProvider::SuggestExactInput(this, input, 459 !HasHTTPScheme(input.text()))); 460 match.is_history_what_you_typed_match = false; 461 match.inline_autocomplete_offset = string16::npos; 462 463 // The placeholder suggestion for the current URL has high relevance so 464 // that it is in the first suggestion slot and inline autocompleted. It 465 // gets dropped as soon as the user types something. 466 match.relevance = verbatim_relevance_; 467 468 return match; 469} 470