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 "components/omnibox/browser/zero_suggest_provider.h" | 5 #include "components/omnibox/browser/zero_suggest_provider.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include "base/callback.h" | 9 #include "base/callback.h" |
10 #include "base/i18n/case_conversion.h" | 10 #include "base/i18n/case_conversion.h" |
11 #include "base/json/json_string_value_serializer.h" | 11 #include "base/json/json_string_value_serializer.h" |
12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
13 #include "base/metrics/user_metrics.h" | 13 #include "base/metrics/user_metrics.h" |
14 #include "base/strings/string16.h" | 14 #include "base/strings/string16.h" |
15 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
16 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
17 #include "base/time/time.h" | 17 #include "base/time/time.h" |
18 #include "base/trace_event/trace_event.h" | 18 #include "base/trace_event/trace_event.h" |
19 #include "components/data_use_measurement/core/data_use_user_data.h" | 19 #include "components/data_use_measurement/core/data_use_user_data.h" |
20 #include "components/history/core/browser/history_types.h" | 20 #include "components/history/core/browser/history_types.h" |
21 #include "components/history/core/browser/top_sites.h" | 21 #include "components/history/core/browser/top_sites.h" |
| 22 #include "components/metrics/proto/omnibox_event.pb.h" |
22 #include "components/metrics/proto/omnibox_input_type.pb.h" | 23 #include "components/metrics/proto/omnibox_input_type.pb.h" |
23 #include "components/omnibox/browser/autocomplete_classifier.h" | 24 #include "components/omnibox/browser/autocomplete_classifier.h" |
24 #include "components/omnibox/browser/autocomplete_input.h" | 25 #include "components/omnibox/browser/autocomplete_input.h" |
25 #include "components/omnibox/browser/autocomplete_match.h" | 26 #include "components/omnibox/browser/autocomplete_match.h" |
26 #include "components/omnibox/browser/autocomplete_provider_listener.h" | 27 #include "components/omnibox/browser/autocomplete_provider_listener.h" |
27 #include "components/omnibox/browser/history_url_provider.h" | 28 #include "components/omnibox/browser/history_url_provider.h" |
28 #include "components/omnibox/browser/omnibox_field_trial.h" | 29 #include "components/omnibox/browser/omnibox_field_trial.h" |
29 #include "components/omnibox/browser/omnibox_pref_names.h" | 30 #include "components/omnibox/browser/omnibox_pref_names.h" |
30 #include "components/omnibox/browser/search_provider.h" | 31 #include "components/omnibox/browser/search_provider.h" |
31 #include "components/omnibox/browser/verbatim_match.h" | 32 #include "components/omnibox/browser/verbatim_match.h" |
32 #include "components/pref_registry/pref_registry_syncable.h" | 33 #include "components/pref_registry/pref_registry_syncable.h" |
33 #include "components/prefs/pref_service.h" | 34 #include "components/prefs/pref_service.h" |
34 #include "components/search_engines/template_url_service.h" | 35 #include "components/search_engines/template_url_service.h" |
35 #include "components/url_formatter/url_formatter.h" | 36 #include "components/url_formatter/url_formatter.h" |
36 #include "components/variations/net/variations_http_headers.h" | 37 #include "components/variations/net/variations_http_headers.h" |
37 #include "net/base/escape.h" | 38 #include "net/base/escape.h" |
38 #include "net/base/load_flags.h" | 39 #include "net/base/load_flags.h" |
39 #include "net/http/http_request_headers.h" | 40 #include "net/http/http_request_headers.h" |
40 #include "net/url_request/url_fetcher.h" | 41 #include "net/url_request/url_fetcher.h" |
41 #include "net/url_request/url_request_status.h" | 42 #include "net/url_request/url_request_status.h" |
42 #include "url/gurl.h" | 43 #include "url/gurl.h" |
43 | 44 |
44 namespace { | 45 namespace { |
45 | 46 |
| 47 // Represents whether ZeroSuggestProvider is allowed to display contextual |
| 48 // suggestions on focus, and if not, why not. |
| 49 // These values are written to logs. New enum values can be added, but existing |
| 50 // enums must never be renumbered or deleted and reused. |
| 51 enum class ZeroSuggestEligibility { |
| 52 ELIGIBLE = 0, |
| 53 // URL_INELIGIBLE would be ELIGIBLE except some property of the current URL |
| 54 // itself prevents ZeroSuggest from triggering. |
| 55 URL_INELIGIBLE = 1, |
| 56 GENERALLY_INELIGIBLE = 2, |
| 57 ELIGIBLE_MAX_VALUE |
| 58 }; |
| 59 |
46 // TODO(hfung): The histogram code was copied and modified from | 60 // TODO(hfung): The histogram code was copied and modified from |
47 // search_provider.cc. Refactor and consolidate the code. | 61 // search_provider.cc. Refactor and consolidate the code. |
48 // We keep track in a histogram how many suggest requests we send, how | 62 // 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 | 63 // many suggest requests we invalidate (e.g., due to a user typing |
50 // another character), and how many replies we receive. | 64 // another character), and how many replies we receive. |
51 // *** ADD NEW ENUMS AFTER ALL PREVIOUSLY DEFINED ONES! *** | 65 // These values are written to logs. New enum values can be added, but existing |
52 // (excluding the end-of-list enum value) | 66 // enums must never be renumbered or deleted and reused. |
53 // We do not want values of existing enums to change or else it screws | |
54 // up the statistics. | |
55 enum ZeroSuggestRequestsHistogramValue { | 67 enum ZeroSuggestRequestsHistogramValue { |
56 ZERO_SUGGEST_REQUEST_SENT = 1, | 68 ZERO_SUGGEST_REQUEST_SENT = 1, |
57 ZERO_SUGGEST_REQUEST_INVALIDATED, | 69 ZERO_SUGGEST_REQUEST_INVALIDATED = 2, |
58 ZERO_SUGGEST_REPLY_RECEIVED, | 70 ZERO_SUGGEST_REPLY_RECEIVED = 3, |
59 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE | 71 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE |
60 }; | 72 }; |
61 | 73 |
62 void LogOmniboxZeroSuggestRequest( | 74 void LogOmniboxZeroSuggestRequest( |
63 ZeroSuggestRequestsHistogramValue request_value) { | 75 ZeroSuggestRequestsHistogramValue request_value) { |
64 UMA_HISTOGRAM_ENUMERATION("Omnibox.ZeroSuggestRequests", request_value, | 76 UMA_HISTOGRAM_ENUMERATION("Omnibox.ZeroSuggestRequests", request_value, |
65 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE); | 77 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE); |
66 } | 78 } |
67 | 79 |
68 // Relevance value to use if it was not set explicitly by the server. | 80 // Relevance value to use if it was not set explicitly by the server. |
69 const int kDefaultZeroSuggestRelevance = 100; | 81 const int kDefaultZeroSuggestRelevance = 100; |
70 | 82 |
| 83 // Used for testing whether zero suggest is ever available. |
| 84 std::string kArbitraryInsecureUrlString = "http://www.google.com/"; |
| 85 |
71 } // namespace | 86 } // namespace |
72 | 87 |
73 // static | 88 // static |
74 ZeroSuggestProvider* ZeroSuggestProvider::Create( | 89 ZeroSuggestProvider* ZeroSuggestProvider::Create( |
75 AutocompleteProviderClient* client, | 90 AutocompleteProviderClient* client, |
76 HistoryURLProvider* history_url_provider, | 91 HistoryURLProvider* history_url_provider, |
77 AutocompleteProviderListener* listener) { | 92 AutocompleteProviderListener* listener) { |
78 return new ZeroSuggestProvider(client, history_url_provider, listener); | 93 return new ZeroSuggestProvider(client, history_url_provider, listener); |
79 } | 94 } |
80 | 95 |
(...skipping 13 matching lines...) Expand all Loading... |
94 return; | 109 return; |
95 | 110 |
96 Stop(true, false); | 111 Stop(true, false); |
97 set_field_trial_triggered(false); | 112 set_field_trial_triggered(false); |
98 set_field_trial_triggered_in_session(false); | 113 set_field_trial_triggered_in_session(false); |
99 results_from_cache_ = false; | 114 results_from_cache_ = false; |
100 permanent_text_ = input.text(); | 115 permanent_text_ = input.text(); |
101 current_query_ = input.current_url().spec(); | 116 current_query_ = input.current_url().spec(); |
102 current_page_classification_ = input.current_page_classification(); | 117 current_page_classification_ = input.current_page_classification(); |
103 current_url_match_ = MatchForCurrentURL(); | 118 current_url_match_ = MatchForCurrentURL(); |
104 TemplateURLService* template_url_service = client()->GetTemplateURLService(); | |
105 | 119 |
106 const TemplateURL* default_provider = | 120 std::string url_string = GetContextualSuggestionsUrl(); |
107 template_url_service->GetDefaultSearchProvider(); | |
108 if (default_provider == NULL) | |
109 return; | |
110 | |
111 base::string16 prefix; | |
112 TemplateURLRef::SearchTermsArgs search_term_args(prefix); | |
113 std::string url_string; | |
114 if (OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial()) { | |
115 url_string = OmniboxFieldTrial::ZeroSuggestRedirectToChromeServerAddress(); | |
116 } else { | |
117 url_string = default_provider->suggestions_url_ref().ReplaceSearchTerms( | |
118 search_term_args, template_url_service->search_terms_data()); | |
119 } | |
120 GURL suggest_url(url_string); | 121 GURL suggest_url(url_string); |
121 | |
122 if (!suggest_url.is_valid()) | 122 if (!suggest_url.is_valid()) |
123 return; | 123 return; |
124 | 124 |
125 // No need to send the current page URL in personalized suggest or | 125 // No need to send the current page URL in personalized suggest or |
126 // most visited field trials. | 126 // most visited field trials. |
127 if (CanSendURL(input.current_url(), suggest_url, default_provider, | 127 const TemplateURLService* template_url_service = |
| 128 client()->GetTemplateURLService(); |
| 129 const TemplateURL* default_provider = |
| 130 template_url_service->GetDefaultSearchProvider(); |
| 131 const bool can_send_current_url = |
| 132 CanSendURL(input.current_url(), suggest_url, default_provider, |
128 current_page_classification_, | 133 current_page_classification_, |
129 template_url_service->search_terms_data(), client()) && | 134 template_url_service->search_terms_data(), client()); |
| 135 GURL arbitrary_insecure_url(kArbitraryInsecureUrlString); |
| 136 ZeroSuggestEligibility eligibility = ZeroSuggestEligibility::ELIGIBLE; |
| 137 if (!can_send_current_url) { |
| 138 const bool can_send_ordinary_url = |
| 139 CanSendURL(arbitrary_insecure_url, suggest_url, default_provider, |
| 140 current_page_classification_, |
| 141 template_url_service->search_terms_data(), client()); |
| 142 eligibility = can_send_ordinary_url |
| 143 ? ZeroSuggestEligibility::URL_INELIGIBLE |
| 144 : ZeroSuggestEligibility::GENERALLY_INELIGIBLE; |
| 145 } |
| 146 UMA_HISTOGRAM_ENUMERATION( |
| 147 "Omnibox.ZeroSuggest.Eligible.OnFocus", static_cast<int>(eligibility), |
| 148 static_cast<int>(ZeroSuggestEligibility::ELIGIBLE_MAX_VALUE)); |
| 149 if (can_send_current_url && |
130 !OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() && | 150 !OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() && |
131 !OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) { | 151 !OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) { |
132 // Update suggest_url to include the current_page_url. | 152 // Update suggest_url to include the current_page_url. |
133 if (OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial()) { | 153 if (OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial()) { |
134 url_string += | 154 url_string += |
135 "/url=" + net::EscapePath(current_query_) + | 155 "/url=" + net::EscapePath(current_query_) + |
136 OmniboxFieldTrial::ZeroSuggestRedirectToChromeAdditionalFields(); | 156 OmniboxFieldTrial::ZeroSuggestRedirectToChromeAdditionalFields(); |
137 suggest_url = GURL(url_string); | 157 suggest_url = GURL(url_string); |
138 } else { | 158 } else { |
| 159 base::string16 prefix; |
| 160 TemplateURLRef::SearchTermsArgs search_term_args(prefix); |
139 search_term_args.current_page_url = current_query_; | 161 search_term_args.current_page_url = current_query_; |
140 suggest_url = | 162 suggest_url = |
141 GURL(default_provider->suggestions_url_ref().ReplaceSearchTerms( | 163 GURL(default_provider->suggestions_url_ref().ReplaceSearchTerms( |
142 search_term_args, template_url_service->search_terms_data())); | 164 search_term_args, template_url_service->search_terms_data())); |
143 } | 165 } |
144 } else if (!ShouldShowNonContextualZeroSuggest(suggest_url, | 166 } else if (!ShouldShowNonContextualZeroSuggest(suggest_url, |
145 input.current_url())) { | 167 input.current_url())) { |
146 return; | 168 return; |
147 } | 169 } |
148 | 170 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 ZeroSuggestProvider::ZeroSuggestProvider( | 224 ZeroSuggestProvider::ZeroSuggestProvider( |
203 AutocompleteProviderClient* client, | 225 AutocompleteProviderClient* client, |
204 HistoryURLProvider* history_url_provider, | 226 HistoryURLProvider* history_url_provider, |
205 AutocompleteProviderListener* listener) | 227 AutocompleteProviderListener* listener) |
206 : BaseSearchProvider(AutocompleteProvider::TYPE_ZERO_SUGGEST, client), | 228 : BaseSearchProvider(AutocompleteProvider::TYPE_ZERO_SUGGEST, client), |
207 history_url_provider_(history_url_provider), | 229 history_url_provider_(history_url_provider), |
208 listener_(listener), | 230 listener_(listener), |
209 results_from_cache_(false), | 231 results_from_cache_(false), |
210 waiting_for_most_visited_urls_request_(false), | 232 waiting_for_most_visited_urls_request_(false), |
211 weak_ptr_factory_(this) { | 233 weak_ptr_factory_(this) { |
| 234 // Record whether contextual zero suggest is possible for this user / profile. |
| 235 const TemplateURLService* template_url_service = |
| 236 client->GetTemplateURLService(); |
| 237 // Template URL service can be null in tests. |
| 238 if (template_url_service != nullptr) { |
| 239 GURL suggest_url(GetContextualSuggestionsUrl()); |
| 240 // To check whether this is allowed, use an arbitrary insecure (http) URL |
| 241 // as the URL we'd want suggestions for. The value of OTHER as the current |
| 242 // page classification is to correspond with that URL. |
| 243 UMA_HISTOGRAM_BOOLEAN( |
| 244 "Omnibox.ZeroSuggest.Eligible.OnProfileOpen", |
| 245 suggest_url.is_valid() && |
| 246 CanSendURL(GURL(kArbitraryInsecureUrlString), suggest_url, |
| 247 template_url_service->GetDefaultSearchProvider(), |
| 248 metrics::OmniboxEventProto::OTHER, |
| 249 template_url_service->search_terms_data(), client)); |
| 250 } |
212 } | 251 } |
213 | 252 |
214 ZeroSuggestProvider::~ZeroSuggestProvider() { | 253 ZeroSuggestProvider::~ZeroSuggestProvider() { |
215 } | 254 } |
216 | 255 |
217 const TemplateURL* ZeroSuggestProvider::GetTemplateURL(bool is_keyword) const { | 256 const TemplateURL* ZeroSuggestProvider::GetTemplateURL(bool is_keyword) const { |
218 // Zero suggest provider should not receive keyword results. | 257 // Zero suggest provider should not receive keyword results. |
219 DCHECK(!is_keyword); | 258 DCHECK(!is_keyword); |
220 return client()->GetTemplateURLService()->GetDefaultSearchProvider(); | 259 return client()->GetTemplateURLService()->GetDefaultSearchProvider(); |
221 } | 260 } |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
472 | 511 |
473 if (OmniboxFieldTrial::InZeroSuggestMostVisitedWithoutSerpFieldTrial() && | 512 if (OmniboxFieldTrial::InZeroSuggestMostVisitedWithoutSerpFieldTrial() && |
474 client() | 513 client() |
475 ->GetTemplateURLService() | 514 ->GetTemplateURLService() |
476 ->IsSearchResultsPageFromDefaultSearchProvider(current_page_url)) | 515 ->IsSearchResultsPageFromDefaultSearchProvider(current_page_url)) |
477 return false; | 516 return false; |
478 | 517 |
479 return true; | 518 return true; |
480 } | 519 } |
481 | 520 |
| 521 std::string ZeroSuggestProvider::GetContextualSuggestionsUrl() const { |
| 522 // Without a default search provider, refuse to do anything (even if the user |
| 523 // is in the redirect-to-chrome field trial). |
| 524 const TemplateURLService* template_url_service = |
| 525 client()->GetTemplateURLService(); |
| 526 const TemplateURL* default_provider = |
| 527 template_url_service->GetDefaultSearchProvider(); |
| 528 if (default_provider == nullptr) |
| 529 return std::string(); |
| 530 |
| 531 if (OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial()) |
| 532 return OmniboxFieldTrial::ZeroSuggestRedirectToChromeServerAddress(); |
| 533 base::string16 prefix; |
| 534 TemplateURLRef::SearchTermsArgs search_term_args(prefix); |
| 535 return default_provider->suggestions_url_ref().ReplaceSearchTerms( |
| 536 search_term_args, template_url_service->search_terms_data()); |
| 537 } |
| 538 |
482 void ZeroSuggestProvider::MaybeUseCachedSuggestions() { | 539 void ZeroSuggestProvider::MaybeUseCachedSuggestions() { |
483 if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial()) | 540 if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial()) |
484 return; | 541 return; |
485 | 542 |
486 std::string json_data = | 543 std::string json_data = |
487 client()->GetPrefs()->GetString(omnibox::kZeroSuggestCachedResults); | 544 client()->GetPrefs()->GetString(omnibox::kZeroSuggestCachedResults); |
488 if (!json_data.empty()) { | 545 if (!json_data.empty()) { |
489 std::unique_ptr<base::Value> data( | 546 std::unique_ptr<base::Value> data( |
490 SearchSuggestionParser::DeserializeJsonData(json_data)); | 547 SearchSuggestionParser::DeserializeJsonData(json_data)); |
491 if (data && ParseSuggestResults( | 548 if (data && ParseSuggestResults( |
492 *data, kDefaultZeroSuggestRelevance, false, &results_)) { | 549 *data, kDefaultZeroSuggestRelevance, false, &results_)) { |
493 ConvertResultsToAutocompleteMatches(); | 550 ConvertResultsToAutocompleteMatches(); |
494 results_from_cache_ = !matches_.empty(); | 551 results_from_cache_ = !matches_.empty(); |
495 } | 552 } |
496 } | 553 } |
497 } | 554 } |
OLD | NEW |