| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/autocomplete/zero_suggest_provider.h" | 5 #include "chrome/browser/autocomplete/zero_suggest_provider.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/i18n/case_conversion.h" | 8 #include "base/i18n/case_conversion.h" |
| 9 #include "base/json/json_string_value_serializer.h" | 9 #include "base/json/json_string_value_serializer.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 159 void ZeroSuggestProvider::ModifyProviderInfo( | 159 void ZeroSuggestProvider::ModifyProviderInfo( |
| 160 metrics::OmniboxEventProto_ProviderInfo* provider_info) const { | 160 metrics::OmniboxEventProto_ProviderInfo* provider_info) const { |
| 161 if (!results_.suggest_results.empty() || !results_.navigation_results.empty()) | 161 if (!results_.suggest_results.empty() || !results_.navigation_results.empty()) |
| 162 provider_info->set_times_returned_results_in_session(1); | 162 provider_info->set_times_returned_results_in_session(1); |
| 163 } | 163 } |
| 164 | 164 |
| 165 ZeroSuggestProvider::ZeroSuggestProvider( | 165 ZeroSuggestProvider::ZeroSuggestProvider( |
| 166 AutocompleteProviderListener* listener, | 166 AutocompleteProviderListener* listener, |
| 167 TemplateURLService* template_url_service, | 167 TemplateURLService* template_url_service, |
| 168 Profile* profile) | 168 Profile* profile) |
| 169 : BaseSearchProvider(listener, template_url_service, profile, | 169 : BaseSearchProvider(template_url_service, profile, |
| 170 AutocompleteProvider::TYPE_ZERO_SUGGEST), | 170 AutocompleteProvider::TYPE_ZERO_SUGGEST), |
| 171 listener_(listener), |
| 171 results_from_cache_(false), | 172 results_from_cache_(false), |
| 172 weak_ptr_factory_(this) { | 173 weak_ptr_factory_(this) { |
| 173 } | 174 } |
| 174 | 175 |
| 175 ZeroSuggestProvider::~ZeroSuggestProvider() { | 176 ZeroSuggestProvider::~ZeroSuggestProvider() { |
| 176 } | 177 } |
| 177 | 178 |
| 178 bool ZeroSuggestProvider::StoreSuggestionResponse( | |
| 179 const std::string& json_data, | |
| 180 const base::Value& parsed_data) { | |
| 181 if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() || | |
| 182 json_data.empty()) | |
| 183 return false; | |
| 184 profile_->GetPrefs()->SetString(prefs::kZeroSuggestCachedResults, json_data); | |
| 185 | |
| 186 // If we received an empty result list, we should update the display, as it | |
| 187 // may be showing cached results that should not be shown. | |
| 188 const base::ListValue* root_list = NULL; | |
| 189 const base::ListValue* results_list = NULL; | |
| 190 if (parsed_data.GetAsList(&root_list) && | |
| 191 root_list->GetList(1, &results_list) && | |
| 192 results_list->empty()) | |
| 193 return false; | |
| 194 | |
| 195 // We are finished with the request and want to bail early. | |
| 196 if (results_from_cache_) | |
| 197 done_ = true; | |
| 198 | |
| 199 return results_from_cache_; | |
| 200 } | |
| 201 | |
| 202 const TemplateURL* ZeroSuggestProvider::GetTemplateURL(bool is_keyword) const { | 179 const TemplateURL* ZeroSuggestProvider::GetTemplateURL(bool is_keyword) const { |
| 203 // Zero suggest provider should not receive keyword results. | 180 // Zero suggest provider should not receive keyword results. |
| 204 DCHECK(!is_keyword); | 181 DCHECK(!is_keyword); |
| 205 return template_url_service_->GetDefaultSearchProvider(); | 182 return template_url_service_->GetDefaultSearchProvider(); |
| 206 } | 183 } |
| 207 | 184 |
| 208 const AutocompleteInput ZeroSuggestProvider::GetInput(bool is_keyword) const { | 185 const AutocompleteInput ZeroSuggestProvider::GetInput(bool is_keyword) const { |
| 209 return AutocompleteInput( | 186 return AutocompleteInput( |
| 210 base::string16(), base::string16::npos, base::string16(), | 187 base::string16(), base::string16::npos, base::string16(), |
| 211 GURL(current_query_), current_page_classification_, true, false, false, | 188 GURL(current_query_), current_page_classification_, true, false, false, |
| 212 true, ChromeAutocompleteSchemeClassifier(profile_)); | 189 true, ChromeAutocompleteSchemeClassifier(profile_)); |
| 213 } | 190 } |
| 214 | 191 |
| 215 SearchSuggestionParser::Results* ZeroSuggestProvider::GetResultsToFill( | |
| 216 bool is_keyword) { | |
| 217 DCHECK(!is_keyword); | |
| 218 return &results_; | |
| 219 } | |
| 220 | |
| 221 bool ZeroSuggestProvider::ShouldAppendExtraParams( | 192 bool ZeroSuggestProvider::ShouldAppendExtraParams( |
| 222 const SearchSuggestionParser::SuggestResult& result) const { | 193 const SearchSuggestionParser::SuggestResult& result) const { |
| 223 // We always use the default provider for search, so append the params. | 194 // We always use the default provider for search, so append the params. |
| 224 return true; | 195 return true; |
| 225 } | 196 } |
| 226 | 197 |
| 227 void ZeroSuggestProvider::StopSuggest() { | 198 void ZeroSuggestProvider::StopSuggest() { |
| 228 if (suggest_results_pending_ > 0) | 199 if (fetcher_) |
| 229 LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_INVALIDATED); | 200 LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_INVALIDATED); |
| 230 suggest_results_pending_ = 0; | |
| 231 fetcher_.reset(); | 201 fetcher_.reset(); |
| 232 } | 202 } |
| 233 | 203 |
| 234 void ZeroSuggestProvider::ClearAllResults() { | 204 void ZeroSuggestProvider::ClearAllResults() { |
| 235 // We do not call Clear() on |results_| to retain |verbatim_relevance| | 205 // We do not call Clear() on |results_| to retain |verbatim_relevance| |
| 236 // value in the |results_| object. |verbatim_relevance| is used at the | 206 // value in the |results_| object. |verbatim_relevance| is used at the |
| 237 // beginning of the next StartZeroSuggest() call to determine the current url | 207 // beginning of the next StartZeroSuggest() call to determine the current url |
| 238 // match relevance. | 208 // match relevance. |
| 239 results_.suggest_results.clear(); | 209 results_.suggest_results.clear(); |
| 240 results_.navigation_results.clear(); | 210 results_.navigation_results.clear(); |
| 241 current_query_.clear(); | 211 current_query_.clear(); |
| 242 } | 212 } |
| 243 | 213 |
| 244 int ZeroSuggestProvider::GetDefaultResultRelevance() const { | |
| 245 return kDefaultZeroSuggestRelevance; | |
| 246 } | |
| 247 | |
| 248 void ZeroSuggestProvider::RecordDeletionResult(bool success) { | 214 void ZeroSuggestProvider::RecordDeletionResult(bool success) { |
| 249 if (success) { | 215 if (success) { |
| 250 base::RecordAction( | 216 base::RecordAction( |
| 251 base::UserMetricsAction("Omnibox.ZeroSuggestDelete.Success")); | 217 base::UserMetricsAction("Omnibox.ZeroSuggestDelete.Success")); |
| 252 } else { | 218 } else { |
| 253 base::RecordAction( | 219 base::RecordAction( |
| 254 base::UserMetricsAction("Omnibox.ZeroSuggestDelete.Failure")); | 220 base::UserMetricsAction("Omnibox.ZeroSuggestDelete.Failure")); |
| 255 } | 221 } |
| 256 } | 222 } |
| 257 | 223 |
| 258 void ZeroSuggestProvider::LogFetchComplete(bool success, bool is_keyword) { | 224 void ZeroSuggestProvider::OnURLFetchComplete(const net::URLFetcher* source) { |
| 225 DCHECK(!done_); |
| 226 DCHECK_EQ(fetcher_.get(), source); |
| 227 |
| 259 LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REPLY_RECEIVED); | 228 LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REPLY_RECEIVED); |
| 229 |
| 230 bool results_updated = false; |
| 231 if (source->GetStatus().is_success() && source->GetResponseCode() == 200) { |
| 232 std::string json_data = SearchSuggestionParser::ExtractJsonData(source); |
| 233 scoped_ptr<base::Value> data( |
| 234 SearchSuggestionParser::DeserializeJsonData(json_data)); |
| 235 if (data) { |
| 236 if (StoreSuggestionResponse(json_data, *data)) |
| 237 return; |
| 238 results_updated = ParseSuggestResults( |
| 239 *data, kDefaultZeroSuggestRelevance, false, &results_); |
| 240 } |
| 241 } |
| 242 fetcher_.reset(); |
| 243 done_ = true; |
| 244 ConvertResultsToAutocompleteMatches(); |
| 245 listener_->OnProviderUpdate(results_updated); |
| 260 } | 246 } |
| 261 | 247 |
| 262 bool ZeroSuggestProvider::IsKeywordFetcher( | 248 bool ZeroSuggestProvider::StoreSuggestionResponse( |
| 263 const net::URLFetcher* fetcher) const { | 249 const std::string& json_data, |
| 264 // ZeroSuggestProvider does not have a keyword provider. | 250 const base::Value& parsed_data) { |
| 265 DCHECK_EQ(fetcher, fetcher_.get()); | 251 if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() || |
| 266 return false; | 252 json_data.empty()) |
| 267 } | 253 return false; |
| 254 profile_->GetPrefs()->SetString(prefs::kZeroSuggestCachedResults, json_data); |
| 268 | 255 |
| 269 void ZeroSuggestProvider::UpdateMatches() { | 256 // If we received an empty result list, we should update the display, as it |
| 270 done_ = true; | 257 // may be showing cached results that should not be shown. |
| 271 ConvertResultsToAutocompleteMatches(); | 258 const base::ListValue* root_list = NULL; |
| 259 const base::ListValue* results_list = NULL; |
| 260 if (parsed_data.GetAsList(&root_list) && |
| 261 root_list->GetList(1, &results_list) && |
| 262 results_list->empty()) |
| 263 return false; |
| 264 |
| 265 // We are finished with the request and want to bail early. |
| 266 if (results_from_cache_) |
| 267 done_ = true; |
| 268 |
| 269 return results_from_cache_; |
| 272 } | 270 } |
| 273 | 271 |
| 274 void ZeroSuggestProvider::AddSuggestResultsToMap( | 272 void ZeroSuggestProvider::AddSuggestResultsToMap( |
| 275 const SearchSuggestionParser::SuggestResults& results, | 273 const SearchSuggestionParser::SuggestResults& results, |
| 276 MatchMap* map) { | 274 MatchMap* map) { |
| 277 for (size_t i = 0; i < results.size(); ++i) | 275 for (size_t i = 0; i < results.size(); ++i) |
| 278 AddMatchToMap(results[i], std::string(), i, false, map); | 276 AddMatchToMap(results[i], std::string(), i, false, map); |
| 279 } | 277 } |
| 280 | 278 |
| 281 AutocompleteMatch ZeroSuggestProvider::NavigationToMatch( | 279 AutocompleteMatch ZeroSuggestProvider::NavigationToMatch( |
| (...skipping 17 matching lines...) Expand all Loading... |
| 299 | 297 |
| 300 match.description = | 298 match.description = |
| 301 AutocompleteMatch::SanitizeString(navigation.description()); | 299 AutocompleteMatch::SanitizeString(navigation.description()); |
| 302 AutocompleteMatch::ClassifyLocationInString(base::string16::npos, 0, | 300 AutocompleteMatch::ClassifyLocationInString(base::string16::npos, 0, |
| 303 match.description.length(), ACMatchClassification::NONE, | 301 match.description.length(), ACMatchClassification::NONE, |
| 304 &match.description_class); | 302 &match.description_class); |
| 305 return match; | 303 return match; |
| 306 } | 304 } |
| 307 | 305 |
| 308 void ZeroSuggestProvider::Run(const GURL& suggest_url) { | 306 void ZeroSuggestProvider::Run(const GURL& suggest_url) { |
| 309 suggest_results_pending_ = 0; | |
| 310 const int kFetcherID = 1; | 307 const int kFetcherID = 1; |
| 311 fetcher_.reset( | 308 fetcher_.reset( |
| 312 net::URLFetcher::Create(kFetcherID, | 309 net::URLFetcher::Create(kFetcherID, |
| 313 suggest_url, | 310 suggest_url, |
| 314 net::URLFetcher::GET, this)); | 311 net::URLFetcher::GET, this)); |
| 315 fetcher_->SetRequestContext(profile_->GetRequestContext()); | 312 fetcher_->SetRequestContext(profile_->GetRequestContext()); |
| 316 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES); | 313 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES); |
| 317 // Add Chrome experiment state to the request headers. | 314 // Add Chrome experiment state to the request headers. |
| 318 net::HttpRequestHeaders headers; | 315 net::HttpRequestHeaders headers; |
| 319 variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders( | 316 variations::VariationsHttpHeaderProvider::GetInstance()->AppendHeaders( |
| 320 fetcher_->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers); | 317 fetcher_->GetOriginalURL(), profile_->IsOffTheRecord(), false, &headers); |
| 321 fetcher_->SetExtraRequestHeaders(headers.ToString()); | 318 fetcher_->SetExtraRequestHeaders(headers.ToString()); |
| 322 fetcher_->Start(); | 319 fetcher_->Start(); |
| 323 | 320 |
| 324 if (OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) { | 321 if (OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) { |
| 325 most_visited_urls_.clear(); | 322 most_visited_urls_.clear(); |
| 326 history::TopSites* ts = profile_->GetTopSites(); | 323 history::TopSites* ts = profile_->GetTopSites(); |
| 327 if (ts) { | 324 if (ts) { |
| 328 ts->GetMostVisitedURLs( | 325 ts->GetMostVisitedURLs( |
| 329 base::Bind(&ZeroSuggestProvider::OnMostVisitedUrlsAvailable, | 326 base::Bind(&ZeroSuggestProvider::OnMostVisitedUrlsAvailable, |
| 330 weak_ptr_factory_.GetWeakPtr()), false); | 327 weak_ptr_factory_.GetWeakPtr()), false); |
| 331 } | 328 } |
| 332 } | 329 } |
| 333 suggest_results_pending_ = 1; | |
| 334 LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_SENT); | 330 LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_SENT); |
| 335 } | 331 } |
| 336 | 332 |
| 337 void ZeroSuggestProvider::OnMostVisitedUrlsAvailable( | 333 void ZeroSuggestProvider::OnMostVisitedUrlsAvailable( |
| 338 const history::MostVisitedURLList& urls) { | 334 const history::MostVisitedURLList& urls) { |
| 339 most_visited_urls_ = urls; | 335 most_visited_urls_ = urls; |
| 340 } | 336 } |
| 341 | 337 |
| 342 void ZeroSuggestProvider::ConvertResultsToAutocompleteMatches() { | 338 void ZeroSuggestProvider::ConvertResultsToAutocompleteMatches() { |
| 343 matches_.clear(); | 339 matches_.clear(); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 | 448 |
| 453 void ZeroSuggestProvider::MaybeUseCachedSuggestions() { | 449 void ZeroSuggestProvider::MaybeUseCachedSuggestions() { |
| 454 if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial()) | 450 if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial()) |
| 455 return; | 451 return; |
| 456 | 452 |
| 457 std::string json_data = profile_->GetPrefs()->GetString( | 453 std::string json_data = profile_->GetPrefs()->GetString( |
| 458 prefs::kZeroSuggestCachedResults); | 454 prefs::kZeroSuggestCachedResults); |
| 459 if (!json_data.empty()) { | 455 if (!json_data.empty()) { |
| 460 scoped_ptr<base::Value> data( | 456 scoped_ptr<base::Value> data( |
| 461 SearchSuggestionParser::DeserializeJsonData(json_data)); | 457 SearchSuggestionParser::DeserializeJsonData(json_data)); |
| 462 if (data && ParseSuggestResults(*data.get(), false, &results_)) { | 458 if (data && ParseSuggestResults( |
| 459 *data, kDefaultZeroSuggestRelevance, false, &results_)) { |
| 463 ConvertResultsToAutocompleteMatches(); | 460 ConvertResultsToAutocompleteMatches(); |
| 464 results_from_cache_ = !matches_.empty(); | 461 results_from_cache_ = !matches_.empty(); |
| 465 } | 462 } |
| 466 } | 463 } |
| 467 } | 464 } |
| OLD | NEW |