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" | |
23 #include "components/metrics/proto/omnibox_input_type.pb.h" | 22 #include "components/metrics/proto/omnibox_input_type.pb.h" |
24 #include "components/omnibox/browser/autocomplete_classifier.h" | 23 #include "components/omnibox/browser/autocomplete_classifier.h" |
25 #include "components/omnibox/browser/autocomplete_input.h" | 24 #include "components/omnibox/browser/autocomplete_input.h" |
26 #include "components/omnibox/browser/autocomplete_match.h" | 25 #include "components/omnibox/browser/autocomplete_match.h" |
27 #include "components/omnibox/browser/autocomplete_provider_listener.h" | 26 #include "components/omnibox/browser/autocomplete_provider_listener.h" |
28 #include "components/omnibox/browser/history_url_provider.h" | 27 #include "components/omnibox/browser/history_url_provider.h" |
29 #include "components/omnibox/browser/omnibox_field_trial.h" | 28 #include "components/omnibox/browser/omnibox_field_trial.h" |
30 #include "components/omnibox/browser/omnibox_pref_names.h" | 29 #include "components/omnibox/browser/omnibox_pref_names.h" |
31 #include "components/omnibox/browser/search_provider.h" | 30 #include "components/omnibox/browser/search_provider.h" |
32 #include "components/omnibox/browser/verbatim_match.h" | 31 #include "components/omnibox/browser/verbatim_match.h" |
33 #include "components/pref_registry/pref_registry_syncable.h" | 32 #include "components/pref_registry/pref_registry_syncable.h" |
34 #include "components/prefs/pref_service.h" | 33 #include "components/prefs/pref_service.h" |
35 #include "components/search_engines/template_url_service.h" | 34 #include "components/search_engines/template_url_service.h" |
36 #include "components/url_formatter/url_formatter.h" | 35 #include "components/url_formatter/url_formatter.h" |
37 #include "components/variations/net/variations_http_headers.h" | 36 #include "components/variations/net/variations_http_headers.h" |
38 #include "net/base/escape.h" | 37 #include "net/base/escape.h" |
39 #include "net/base/load_flags.h" | 38 #include "net/base/load_flags.h" |
40 #include "net/http/http_request_headers.h" | 39 #include "net/http/http_request_headers.h" |
41 #include "net/url_request/url_fetcher.h" | 40 #include "net/url_request/url_fetcher.h" |
42 #include "net/url_request/url_request_status.h" | 41 #include "net/url_request/url_request_status.h" |
43 #include "url/gurl.h" | 42 #include "url/gurl.h" |
44 | 43 |
45 namespace { | 44 namespace { |
46 | 45 |
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 | |
60 // TODO(hfung): The histogram code was copied and modified from | 46 // TODO(hfung): The histogram code was copied and modified from |
61 // search_provider.cc. Refactor and consolidate the code. | 47 // search_provider.cc. Refactor and consolidate the code. |
62 // We keep track in a histogram how many suggest requests we send, how | 48 // We keep track in a histogram how many suggest requests we send, how |
63 // many suggest requests we invalidate (e.g., due to a user typing | 49 // many suggest requests we invalidate (e.g., due to a user typing |
64 // another character), and how many replies we receive. | 50 // another character), and how many replies we receive. |
65 // These values are written to logs. New enum values can be added, but existing | 51 // *** ADD NEW ENUMS AFTER ALL PREVIOUSLY DEFINED ONES! *** |
66 // enums must never be renumbered or deleted and reused. | 52 // (excluding the end-of-list enum value) |
| 53 // We do not want values of existing enums to change or else it screws |
| 54 // up the statistics. |
67 enum ZeroSuggestRequestsHistogramValue { | 55 enum ZeroSuggestRequestsHistogramValue { |
68 ZERO_SUGGEST_REQUEST_SENT = 1, | 56 ZERO_SUGGEST_REQUEST_SENT = 1, |
69 ZERO_SUGGEST_REQUEST_INVALIDATED = 2, | 57 ZERO_SUGGEST_REQUEST_INVALIDATED, |
70 ZERO_SUGGEST_REPLY_RECEIVED = 3, | 58 ZERO_SUGGEST_REPLY_RECEIVED, |
71 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE | 59 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE |
72 }; | 60 }; |
73 | 61 |
74 void LogOmniboxZeroSuggestRequest( | 62 void LogOmniboxZeroSuggestRequest( |
75 ZeroSuggestRequestsHistogramValue request_value) { | 63 ZeroSuggestRequestsHistogramValue request_value) { |
76 UMA_HISTOGRAM_ENUMERATION("Omnibox.ZeroSuggestRequests", request_value, | 64 UMA_HISTOGRAM_ENUMERATION("Omnibox.ZeroSuggestRequests", request_value, |
77 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE); | 65 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE); |
78 } | 66 } |
79 | 67 |
80 // Relevance value to use if it was not set explicitly by the server. | 68 // Relevance value to use if it was not set explicitly by the server. |
81 const int kDefaultZeroSuggestRelevance = 100; | 69 const int kDefaultZeroSuggestRelevance = 100; |
82 | 70 |
83 // Used for testing whether zero suggest is ever available. | |
84 std::string kArbitraryInsecureUrlString = "http://www.google.com/"; | |
85 | |
86 } // namespace | 71 } // namespace |
87 | 72 |
88 // static | 73 // static |
89 ZeroSuggestProvider* ZeroSuggestProvider::Create( | 74 ZeroSuggestProvider* ZeroSuggestProvider::Create( |
90 AutocompleteProviderClient* client, | 75 AutocompleteProviderClient* client, |
91 HistoryURLProvider* history_url_provider, | 76 HistoryURLProvider* history_url_provider, |
92 AutocompleteProviderListener* listener) { | 77 AutocompleteProviderListener* listener) { |
93 return new ZeroSuggestProvider(client, history_url_provider, listener); | 78 return new ZeroSuggestProvider(client, history_url_provider, listener); |
94 } | 79 } |
95 | 80 |
(...skipping 13 matching lines...) Expand all Loading... |
109 return; | 94 return; |
110 | 95 |
111 Stop(true, false); | 96 Stop(true, false); |
112 set_field_trial_triggered(false); | 97 set_field_trial_triggered(false); |
113 set_field_trial_triggered_in_session(false); | 98 set_field_trial_triggered_in_session(false); |
114 results_from_cache_ = false; | 99 results_from_cache_ = false; |
115 permanent_text_ = input.text(); | 100 permanent_text_ = input.text(); |
116 current_query_ = input.current_url().spec(); | 101 current_query_ = input.current_url().spec(); |
117 current_page_classification_ = input.current_page_classification(); | 102 current_page_classification_ = input.current_page_classification(); |
118 current_url_match_ = MatchForCurrentURL(); | 103 current_url_match_ = MatchForCurrentURL(); |
| 104 TemplateURLService* template_url_service = client()->GetTemplateURLService(); |
119 | 105 |
120 std::string url_string = GetContextualSuggestionsUrl(); | 106 const TemplateURL* default_provider = |
| 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 } |
121 GURL suggest_url(url_string); | 120 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 const TemplateURLService* template_url_service = | 127 if (CanSendURL(input.current_url(), suggest_url, default_provider, |
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, | |
133 current_page_classification_, | 128 current_page_classification_, |
134 template_url_service->search_terms_data(), client()); | 129 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 && | |
150 !OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() && | 130 !OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() && |
151 !OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) { | 131 !OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) { |
152 // Update suggest_url to include the current_page_url. | 132 // Update suggest_url to include the current_page_url. |
153 if (OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial()) { | 133 if (OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial()) { |
154 url_string += | 134 url_string += |
155 "/url=" + net::EscapePath(current_query_) + | 135 "/url=" + net::EscapePath(current_query_) + |
156 OmniboxFieldTrial::ZeroSuggestRedirectToChromeAdditionalFields(); | 136 OmniboxFieldTrial::ZeroSuggestRedirectToChromeAdditionalFields(); |
157 suggest_url = GURL(url_string); | 137 suggest_url = GURL(url_string); |
158 } else { | 138 } else { |
159 base::string16 prefix; | |
160 TemplateURLRef::SearchTermsArgs search_term_args(prefix); | |
161 search_term_args.current_page_url = current_query_; | 139 search_term_args.current_page_url = current_query_; |
162 suggest_url = | 140 suggest_url = |
163 GURL(default_provider->suggestions_url_ref().ReplaceSearchTerms( | 141 GURL(default_provider->suggestions_url_ref().ReplaceSearchTerms( |
164 search_term_args, template_url_service->search_terms_data())); | 142 search_term_args, template_url_service->search_terms_data())); |
165 } | 143 } |
166 } else if (!ShouldShowNonContextualZeroSuggest(suggest_url, | 144 } else if (!ShouldShowNonContextualZeroSuggest(suggest_url, |
167 input.current_url())) { | 145 input.current_url())) { |
168 return; | 146 return; |
169 } | 147 } |
170 | 148 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 ZeroSuggestProvider::ZeroSuggestProvider( | 202 ZeroSuggestProvider::ZeroSuggestProvider( |
225 AutocompleteProviderClient* client, | 203 AutocompleteProviderClient* client, |
226 HistoryURLProvider* history_url_provider, | 204 HistoryURLProvider* history_url_provider, |
227 AutocompleteProviderListener* listener) | 205 AutocompleteProviderListener* listener) |
228 : BaseSearchProvider(AutocompleteProvider::TYPE_ZERO_SUGGEST, client), | 206 : BaseSearchProvider(AutocompleteProvider::TYPE_ZERO_SUGGEST, client), |
229 history_url_provider_(history_url_provider), | 207 history_url_provider_(history_url_provider), |
230 listener_(listener), | 208 listener_(listener), |
231 results_from_cache_(false), | 209 results_from_cache_(false), |
232 waiting_for_most_visited_urls_request_(false), | 210 waiting_for_most_visited_urls_request_(false), |
233 weak_ptr_factory_(this) { | 211 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 } | |
251 } | 212 } |
252 | 213 |
253 ZeroSuggestProvider::~ZeroSuggestProvider() { | 214 ZeroSuggestProvider::~ZeroSuggestProvider() { |
254 } | 215 } |
255 | 216 |
256 const TemplateURL* ZeroSuggestProvider::GetTemplateURL(bool is_keyword) const { | 217 const TemplateURL* ZeroSuggestProvider::GetTemplateURL(bool is_keyword) const { |
257 // Zero suggest provider should not receive keyword results. | 218 // Zero suggest provider should not receive keyword results. |
258 DCHECK(!is_keyword); | 219 DCHECK(!is_keyword); |
259 return client()->GetTemplateURLService()->GetDefaultSearchProvider(); | 220 return client()->GetTemplateURLService()->GetDefaultSearchProvider(); |
260 } | 221 } |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 | 472 |
512 if (OmniboxFieldTrial::InZeroSuggestMostVisitedWithoutSerpFieldTrial() && | 473 if (OmniboxFieldTrial::InZeroSuggestMostVisitedWithoutSerpFieldTrial() && |
513 client() | 474 client() |
514 ->GetTemplateURLService() | 475 ->GetTemplateURLService() |
515 ->IsSearchResultsPageFromDefaultSearchProvider(current_page_url)) | 476 ->IsSearchResultsPageFromDefaultSearchProvider(current_page_url)) |
516 return false; | 477 return false; |
517 | 478 |
518 return true; | 479 return true; |
519 } | 480 } |
520 | 481 |
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 | |
539 void ZeroSuggestProvider::MaybeUseCachedSuggestions() { | 482 void ZeroSuggestProvider::MaybeUseCachedSuggestions() { |
540 if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial()) | 483 if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial()) |
541 return; | 484 return; |
542 | 485 |
543 std::string json_data = | 486 std::string json_data = |
544 client()->GetPrefs()->GetString(omnibox::kZeroSuggestCachedResults); | 487 client()->GetPrefs()->GetString(omnibox::kZeroSuggestCachedResults); |
545 if (!json_data.empty()) { | 488 if (!json_data.empty()) { |
546 std::unique_ptr<base::Value> data( | 489 std::unique_ptr<base::Value> data( |
547 SearchSuggestionParser::DeserializeJsonData(json_data)); | 490 SearchSuggestionParser::DeserializeJsonData(json_data)); |
548 if (data && ParseSuggestResults( | 491 if (data && ParseSuggestResults( |
549 *data, kDefaultZeroSuggestRelevance, false, &results_)) { | 492 *data, kDefaultZeroSuggestRelevance, false, &results_)) { |
550 ConvertResultsToAutocompleteMatches(); | 493 ConvertResultsToAutocompleteMatches(); |
551 results_from_cache_ = !matches_.empty(); | 494 results_from_cache_ = !matches_.empty(); |
552 } | 495 } |
553 } | 496 } |
554 } | 497 } |
OLD | NEW |