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 |