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" |
11 #include "base/prefs/pref_service.h" | 11 #include "base/prefs/pref_service.h" |
12 #include "base/strings/string16.h" | 12 #include "base/strings/string16.h" |
13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
15 #include "base/time/time.h" | 15 #include "base/time/time.h" |
16 #include "chrome/browser/autocomplete/autocomplete_classifier.h" | 16 #include "chrome/browser/autocomplete/autocomplete_classifier.h" |
17 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" | 17 #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" |
18 #include "chrome/browser/autocomplete/autocomplete_input.h" | 18 #include "chrome/browser/autocomplete/autocomplete_input.h" |
19 #include "chrome/browser/autocomplete/autocomplete_match.h" | 19 #include "chrome/browser/autocomplete/autocomplete_match.h" |
20 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h" | 20 #include "chrome/browser/autocomplete/autocomplete_provider_listener.h" |
21 #include "chrome/browser/autocomplete/history_url_provider.h" | 21 #include "chrome/browser/autocomplete/history_url_provider.h" |
22 #include "chrome/browser/autocomplete/search_provider.h" | 22 #include "chrome/browser/autocomplete/search_provider.h" |
23 #include "chrome/browser/autocomplete/url_prefix.h" | 23 #include "chrome/browser/autocomplete/url_prefix.h" |
24 #include "chrome/browser/google/google_util.h" | |
25 #include "chrome/browser/history/history_types.h" | 24 #include "chrome/browser/history/history_types.h" |
26 #include "chrome/browser/history/top_sites.h" | 25 #include "chrome/browser/history/top_sites.h" |
27 #include "chrome/browser/metrics/variations/variations_http_header_provider.h" | 26 #include "chrome/browser/metrics/variations/variations_http_header_provider.h" |
28 #include "chrome/browser/omnibox/omnibox_field_trial.h" | 27 #include "chrome/browser/omnibox/omnibox_field_trial.h" |
29 #include "chrome/browser/profiles/profile.h" | 28 #include "chrome/browser/profiles/profile.h" |
30 #include "chrome/browser/search/search.h" | 29 #include "chrome/browser/search/search.h" |
31 #include "chrome/browser/search_engines/template_url_service.h" | 30 #include "chrome/browser/search_engines/template_url_service.h" |
32 #include "chrome/browser/search_engines/template_url_service_factory.h" | 31 #include "chrome/browser/search_engines/template_url_service_factory.h" |
33 #include "chrome/browser/sync/profile_sync_service.h" | |
34 #include "chrome/browser/sync/profile_sync_service_factory.h" | |
35 #include "chrome/common/net/url_fixer_upper.h" | 32 #include "chrome/common/net/url_fixer_upper.h" |
36 #include "chrome/common/pref_names.h" | 33 #include "chrome/common/pref_names.h" |
37 #include "chrome/common/url_constants.h" | 34 #include "chrome/common/url_constants.h" |
38 #include "net/base/escape.h" | 35 #include "net/base/escape.h" |
39 #include "net/base/load_flags.h" | 36 #include "net/base/load_flags.h" |
40 #include "net/base/net_util.h" | 37 #include "net/base/net_util.h" |
41 #include "net/http/http_request_headers.h" | 38 #include "net/http/http_request_headers.h" |
42 #include "net/http/http_response_headers.h" | 39 #include "net/http/http_response_headers.h" |
43 #include "net/url_request/url_fetcher.h" | 40 #include "net/url_request/url_fetcher.h" |
44 #include "net/url_request/url_request_status.h" | 41 #include "net/url_request/url_request_status.h" |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 listener_->OnProviderUpdate(true); | 146 listener_->OnProviderUpdate(true); |
150 } | 147 } |
151 | 148 |
152 void ZeroSuggestProvider::StartZeroSuggest( | 149 void ZeroSuggestProvider::StartZeroSuggest( |
153 const GURL& url, | 150 const GURL& url, |
154 AutocompleteInput::PageClassification page_classification, | 151 AutocompleteInput::PageClassification page_classification, |
155 const string16& permanent_text) { | 152 const string16& permanent_text) { |
156 Stop(true); | 153 Stop(true); |
157 field_trial_triggered_ = false; | 154 field_trial_triggered_ = false; |
158 field_trial_triggered_in_session_ = false; | 155 field_trial_triggered_in_session_ = false; |
159 if (!ShouldRunZeroSuggest(url)) | 156 if (!SearchProvider::CanSendURL( |
| 157 url, template_url_service_->GetDefaultSearchProvider(), profile_) || |
| 158 !OmniboxFieldTrial::InZeroSuggestFieldTrial()) |
160 return; | 159 return; |
161 verbatim_relevance_ = kDefaultVerbatimZeroSuggestRelevance; | 160 verbatim_relevance_ = kDefaultVerbatimZeroSuggestRelevance; |
162 done_ = false; | 161 done_ = false; |
163 permanent_text_ = permanent_text; | 162 permanent_text_ = permanent_text; |
164 current_query_ = url.spec(); | 163 current_query_ = url.spec(); |
165 current_page_classification_ = page_classification; | 164 current_page_classification_ = page_classification; |
166 current_url_match_ = MatchForCurrentURL(); | 165 current_url_match_ = MatchForCurrentURL(); |
167 // TODO(jered): Consider adding locally-sourced zero-suggestions here too. | 166 // TODO(jered): Consider adding locally-sourced zero-suggestions here too. |
168 // These may be useful on the NTP or more relevant to the user than server | 167 // These may be useful on the NTP or more relevant to the user than server |
169 // suggestions, if based on local browsing history. | 168 // suggestions, if based on local browsing history. |
170 Run(); | 169 Run(); |
171 } | 170 } |
172 | 171 |
173 ZeroSuggestProvider::ZeroSuggestProvider( | 172 ZeroSuggestProvider::ZeroSuggestProvider( |
174 AutocompleteProviderListener* listener, | 173 AutocompleteProviderListener* listener, |
175 Profile* profile) | 174 Profile* profile) |
176 : AutocompleteProvider(listener, profile, | 175 : AutocompleteProvider(listener, profile, |
177 AutocompleteProvider::TYPE_ZERO_SUGGEST), | 176 AutocompleteProvider::TYPE_ZERO_SUGGEST), |
178 template_url_service_(TemplateURLServiceFactory::GetForProfile(profile)), | 177 template_url_service_(TemplateURLServiceFactory::GetForProfile(profile)), |
179 have_pending_request_(false), | 178 have_pending_request_(false), |
180 verbatim_relevance_(kDefaultVerbatimZeroSuggestRelevance), | 179 verbatim_relevance_(kDefaultVerbatimZeroSuggestRelevance), |
181 field_trial_triggered_(false), | 180 field_trial_triggered_(false), |
182 field_trial_triggered_in_session_(false), | 181 field_trial_triggered_in_session_(false), |
183 weak_ptr_factory_(this) { | 182 weak_ptr_factory_(this) { |
184 } | 183 } |
185 | 184 |
186 ZeroSuggestProvider::~ZeroSuggestProvider() { | 185 ZeroSuggestProvider::~ZeroSuggestProvider() { |
187 } | 186 } |
188 | 187 |
189 bool ZeroSuggestProvider::ShouldRunZeroSuggest(const GURL& url) const { | |
190 if (!ShouldSendURL(url)) | |
191 return false; | |
192 | |
193 // Don't run if there's no profile or in incognito mode. | |
194 if (profile_ == NULL || profile_->IsOffTheRecord()) | |
195 return false; | |
196 | |
197 // Don't run if we can't get preferences or search suggest is not enabled. | |
198 PrefService* prefs = profile_->GetPrefs(); | |
199 if (prefs == NULL || !prefs->GetBoolean(prefs::kSearchSuggestEnabled)) | |
200 return false; | |
201 | |
202 ProfileSyncService* service = | |
203 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_); | |
204 browser_sync::SyncPrefs sync_prefs(prefs); | |
205 | |
206 // ZeroSuggest requires sending the current URL to the suggest provider, so we | |
207 // only want to enable it if the user is willing to have this data sent. | |
208 // Because tab sync involves sending the same data, we currently use | |
209 // "tab sync is enabled and tab sync data is unencrypted" as a proxy for | |
210 // "the user is OK with sending this data". We might someday want to change | |
211 // this to a standalone setting or part of some other explicit general opt-in. | |
212 if (!OmniboxFieldTrial::InZeroSuggestFieldTrial() || | |
213 service == NULL || | |
214 !service->IsSyncEnabledAndLoggedIn() || | |
215 !sync_prefs.GetPreferredDataTypes(syncer::UserTypes()).Has( | |
216 syncer::PROXY_TABS) || | |
217 service->GetEncryptedDataTypes().Has(syncer::SESSIONS)) { | |
218 return false; | |
219 } | |
220 return true; | |
221 } | |
222 | |
223 bool ZeroSuggestProvider::ShouldSendURL(const GURL& url) const { | |
224 if (!url.is_valid()) | |
225 return false; | |
226 | |
227 // Only allow HTTP URLs or Google HTTPS URLs (including Google search | |
228 // result pages). For the latter case, Google was already sent the HTTPS | |
229 // URLs when requesting the page, so the information is just re-sent. | |
230 return (url.scheme() == content::kHttpScheme) || | |
231 google_util::IsGoogleDomainUrl(url, google_util::ALLOW_SUBDOMAIN, | |
232 google_util::ALLOW_NON_STANDARD_PORTS); | |
233 } | |
234 | |
235 void ZeroSuggestProvider::FillResults( | 188 void ZeroSuggestProvider::FillResults( |
236 const Value& root_val, | 189 const Value& root_val, |
237 int* verbatim_relevance, | 190 int* verbatim_relevance, |
238 SearchProvider::SuggestResults* suggest_results, | 191 SearchProvider::SuggestResults* suggest_results, |
239 SearchProvider::NavigationResults* navigation_results) { | 192 SearchProvider::NavigationResults* navigation_results) { |
240 string16 query; | 193 string16 query; |
241 const ListValue* root_list = NULL; | 194 const ListValue* root_list = NULL; |
242 const ListValue* results = NULL; | 195 const ListValue* results = NULL; |
243 const ListValue* relevances = NULL; | 196 const ListValue* relevances = NULL; |
244 // The response includes the query, which should be empty for ZeroSuggest | 197 // The response includes the query, which should be empty for ZeroSuggest |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 &match.description_class); | 328 &match.description_class); |
376 return match; | 329 return match; |
377 } | 330 } |
378 | 331 |
379 void ZeroSuggestProvider::Run() { | 332 void ZeroSuggestProvider::Run() { |
380 have_pending_request_ = false; | 333 have_pending_request_ = false; |
381 const int kFetcherID = 1; | 334 const int kFetcherID = 1; |
382 | 335 |
383 const TemplateURL* default_provider = | 336 const TemplateURL* default_provider = |
384 template_url_service_->GetDefaultSearchProvider(); | 337 template_url_service_->GetDefaultSearchProvider(); |
385 // TODO(hfung): Generalize if the default provider supports zero suggest. | |
386 // Only make the request if we know that the provider supports zero suggest | |
387 // (currently only the prepopulated Google provider). | |
388 if (default_provider == NULL || !default_provider->SupportsReplacement() || | |
389 default_provider->prepopulate_id() != 1) { | |
390 Stop(true); | |
391 return; | |
392 } | |
393 string16 prefix; | 338 string16 prefix; |
394 TemplateURLRef::SearchTermsArgs search_term_args(prefix); | 339 TemplateURLRef::SearchTermsArgs search_term_args(prefix); |
395 search_term_args.zero_prefix_url = current_query_; | 340 search_term_args.current_page_url = current_query_; |
396 std::string req_url = default_provider->suggestions_url_ref(). | 341 std::string req_url = default_provider->suggestions_url_ref(). |
397 ReplaceSearchTerms(search_term_args); | 342 ReplaceSearchTerms(search_term_args); |
398 GURL suggest_url(req_url); | 343 GURL suggest_url(req_url); |
399 // Make sure we are sending the suggest request through HTTPS. | 344 // Make sure we are sending the suggest request through HTTPS. |
400 if (!suggest_url.SchemeIs(content::kHttpsScheme)) { | 345 if (!suggest_url.SchemeIs(content::kHttpsScheme)) { |
401 Stop(true); | 346 Stop(true); |
402 return; | 347 return; |
403 } | 348 } |
404 | 349 |
405 fetcher_.reset( | 350 fetcher_.reset( |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 match.is_history_what_you_typed_match = false; | 452 match.is_history_what_you_typed_match = false; |
508 match.allowed_to_be_default_match = true; | 453 match.allowed_to_be_default_match = true; |
509 | 454 |
510 // The placeholder suggestion for the current URL has high relevance so | 455 // The placeholder suggestion for the current URL has high relevance so |
511 // that it is in the first suggestion slot and inline autocompleted. It | 456 // that it is in the first suggestion slot and inline autocompleted. It |
512 // gets dropped as soon as the user types something. | 457 // gets dropped as soon as the user types something. |
513 match.relevance = verbatim_relevance_; | 458 match.relevance = verbatim_relevance_; |
514 | 459 |
515 return match; | 460 return match; |
516 } | 461 } |
OLD | NEW |