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 if, on focus, ZeroSuggestProvider is allowed to display | |
Peter Kasting
2017/03/02 21:31:34
Nit: "Represents whether ZeroSuggestProvider is al
Mark P
2017/03/02 23:17:00
Done.
| |
48 // contextual suggestions 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 ZeroSuggestEligibleOnFocus { | |
Peter Kasting
2017/03/02 21:31:34
Nit: Maybe you should use an enum class, and then
Mark P
2017/03/02 23:17:00
Sure. Done.
| |
52 ZERO_SUGGEST_ELIGIBLE = 0, | |
53 ZERO_SUGGEST_GENERALLY_ELIGIBLE_BUT_NOT_THIS_URL = 1, | |
54 ZERO_SUGGEST_GENERALLY_INELIGIBLE = 2, | |
Peter Kasting
2017/03/02 21:31:34
Nit: Maybe _URL_INELIGIBLE versus _GLOBALLY_INELIG
Mark P
2017/03/02 23:17:00
Revised the middle enum name and added a comment.
| |
55 ZERO_SUGGEST_ELIGIBLE_MAX_VALUE | |
56 }; | |
57 | |
46 // TODO(hfung): The histogram code was copied and modified from | 58 // TODO(hfung): The histogram code was copied and modified from |
47 // search_provider.cc. Refactor and consolidate the code. | 59 // search_provider.cc. Refactor and consolidate the code. |
48 // We keep track in a histogram how many suggest requests we send, how | 60 // 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 | 61 // many suggest requests we invalidate (e.g., due to a user typing |
50 // another character), and how many replies we receive. | 62 // another character), and how many replies we receive. |
51 // *** ADD NEW ENUMS AFTER ALL PREVIOUSLY DEFINED ONES! *** | 63 // These values are written to logs. New enum values can be added, but existing |
52 // (excluding the end-of-list enum value) | 64 // 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 { | 65 enum ZeroSuggestRequestsHistogramValue { |
56 ZERO_SUGGEST_REQUEST_SENT = 1, | 66 ZERO_SUGGEST_REQUEST_SENT = 1, |
57 ZERO_SUGGEST_REQUEST_INVALIDATED, | 67 ZERO_SUGGEST_REQUEST_INVALIDATED = 2, |
58 ZERO_SUGGEST_REPLY_RECEIVED, | 68 ZERO_SUGGEST_REPLY_RECEIVED = 3, |
59 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE | 69 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE |
60 }; | 70 }; |
61 | 71 |
62 void LogOmniboxZeroSuggestRequest( | 72 void LogOmniboxZeroSuggestRequest( |
63 ZeroSuggestRequestsHistogramValue request_value) { | 73 ZeroSuggestRequestsHistogramValue request_value) { |
64 UMA_HISTOGRAM_ENUMERATION("Omnibox.ZeroSuggestRequests", request_value, | 74 UMA_HISTOGRAM_ENUMERATION("Omnibox.ZeroSuggestRequests", request_value, |
65 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE); | 75 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE); |
66 } | 76 } |
67 | 77 |
68 // Relevance value to use if it was not set explicitly by the server. | 78 // Relevance value to use if it was not set explicitly by the server. |
69 const int kDefaultZeroSuggestRelevance = 100; | 79 const int kDefaultZeroSuggestRelevance = 100; |
70 | 80 |
81 // Used for testing whether zero suggest is ever available. | |
82 std::string kArbitraryInsecureUrlString = "http://www.google.com/"; | |
Peter Kasting
2017/03/02 21:31:34
Nit: Would an intranet hostname like "test/" work?
Mark P
2017/03/02 23:17:00
No. I can easily imagine having a test (not sure
| |
83 | |
71 } // namespace | 84 } // namespace |
72 | 85 |
73 // static | 86 // static |
74 ZeroSuggestProvider* ZeroSuggestProvider::Create( | 87 ZeroSuggestProvider* ZeroSuggestProvider::Create( |
75 AutocompleteProviderClient* client, | 88 AutocompleteProviderClient* client, |
76 HistoryURLProvider* history_url_provider, | 89 HistoryURLProvider* history_url_provider, |
77 AutocompleteProviderListener* listener) { | 90 AutocompleteProviderListener* listener) { |
78 return new ZeroSuggestProvider(client, history_url_provider, listener); | 91 return new ZeroSuggestProvider(client, history_url_provider, listener); |
79 } | 92 } |
80 | 93 |
(...skipping 13 matching lines...) Expand all Loading... | |
94 return; | 107 return; |
95 | 108 |
96 Stop(true, false); | 109 Stop(true, false); |
97 set_field_trial_triggered(false); | 110 set_field_trial_triggered(false); |
98 set_field_trial_triggered_in_session(false); | 111 set_field_trial_triggered_in_session(false); |
99 results_from_cache_ = false; | 112 results_from_cache_ = false; |
100 permanent_text_ = input.text(); | 113 permanent_text_ = input.text(); |
101 current_query_ = input.current_url().spec(); | 114 current_query_ = input.current_url().spec(); |
102 current_page_classification_ = input.current_page_classification(); | 115 current_page_classification_ = input.current_page_classification(); |
103 current_url_match_ = MatchForCurrentURL(); | 116 current_url_match_ = MatchForCurrentURL(); |
104 TemplateURLService* template_url_service = client()->GetTemplateURLService(); | |
105 | 117 |
106 const TemplateURL* default_provider = | 118 std::string url_string(GetContextualSuggestionsUrl()); |
Peter Kasting
2017/03/02 21:31:34
Nit: Prefer = to () for simple inits like this; se
Mark P
2017/03/02 23:17:00
Done.
| |
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); | 119 GURL suggest_url(url_string); |
121 | |
122 if (!suggest_url.is_valid()) | 120 if (!suggest_url.is_valid()) |
123 return; | 121 return; |
124 | 122 |
125 // No need to send the current page URL in personalized suggest or | 123 // No need to send the current page URL in personalized suggest or |
126 // most visited field trials. | 124 // most visited field trials. |
127 if (CanSendURL(input.current_url(), suggest_url, default_provider, | 125 const TemplateURLService* template_url_service = |
126 client()->GetTemplateURLService(); | |
Peter Kasting
2017/03/02 21:31:34
I don't have specific recommendations here, but I
Mark P
2017/03/02 23:17:00
There isn't, because most of the parameters betwee
| |
127 const TemplateURL* default_provider = | |
128 template_url_service->GetDefaultSearchProvider(); | |
129 const bool can_send_current_url = | |
130 CanSendURL(input.current_url(), suggest_url, default_provider, | |
128 current_page_classification_, | 131 current_page_classification_, |
129 template_url_service->search_terms_data(), client()) && | 132 template_url_service->search_terms_data(), client()); |
133 GURL arbitrary_insecure_url(kArbitraryInsecureUrlString); | |
134 const bool can_send_ordinary_url = | |
135 CanSendURL(arbitrary_insecure_url, suggest_url, default_provider, | |
136 current_page_classification_, | |
137 template_url_service->search_terms_data(), client()); | |
138 const ZeroSuggestEligibleOnFocus eligibility = | |
139 can_send_current_url | |
140 ? ZERO_SUGGEST_ELIGIBLE | |
141 : (can_send_ordinary_url | |
142 ? ZERO_SUGGEST_GENERALLY_ELIGIBLE_BUT_NOT_THIS_URL | |
143 : ZERO_SUGGEST_GENERALLY_INELIGIBLE); | |
Peter Kasting
2017/03/02 21:31:34
Nit: Not a fan of nesting ?:. How about something
Mark P
2017/03/02 23:17:00
Good idea. Done.
| |
144 UMA_HISTOGRAM_ENUMERATION("Omnibox.ZeroSuggest.Eligible.OnFocus", eligibility, | |
145 ZERO_SUGGEST_ELIGIBLE_MAX_VALUE); | |
146 if (can_send_current_url && | |
130 !OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() && | 147 !OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() && |
131 !OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) { | 148 !OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) { |
132 // Update suggest_url to include the current_page_url. | 149 // Update suggest_url to include the current_page_url. |
133 if (OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial()) { | 150 if (OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial()) { |
134 url_string += | 151 url_string += |
135 "/url=" + net::EscapePath(current_query_) + | 152 "/url=" + net::EscapePath(current_query_) + |
136 OmniboxFieldTrial::ZeroSuggestRedirectToChromeAdditionalFields(); | 153 OmniboxFieldTrial::ZeroSuggestRedirectToChromeAdditionalFields(); |
137 suggest_url = GURL(url_string); | 154 suggest_url = GURL(url_string); |
138 } else { | 155 } else { |
156 base::string16 prefix; | |
Peter Kasting
2017/03/02 21:31:34
Nit: Can just pass string16() in the call below, n
Mark P
2017/03/02 23:17:00
I tried getting rid of it when I wrote the code, t
| |
157 TemplateURLRef::SearchTermsArgs search_term_args(prefix); | |
139 search_term_args.current_page_url = current_query_; | 158 search_term_args.current_page_url = current_query_; |
140 suggest_url = | 159 suggest_url = |
141 GURL(default_provider->suggestions_url_ref().ReplaceSearchTerms( | 160 GURL(default_provider->suggestions_url_ref().ReplaceSearchTerms( |
142 search_term_args, template_url_service->search_terms_data())); | 161 search_term_args, template_url_service->search_terms_data())); |
143 } | 162 } |
144 } else if (!ShouldShowNonContextualZeroSuggest(suggest_url, | 163 } else if (!ShouldShowNonContextualZeroSuggest(suggest_url, |
145 input.current_url())) { | 164 input.current_url())) { |
146 return; | 165 return; |
147 } | 166 } |
148 | 167 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
202 ZeroSuggestProvider::ZeroSuggestProvider( | 221 ZeroSuggestProvider::ZeroSuggestProvider( |
203 AutocompleteProviderClient* client, | 222 AutocompleteProviderClient* client, |
204 HistoryURLProvider* history_url_provider, | 223 HistoryURLProvider* history_url_provider, |
205 AutocompleteProviderListener* listener) | 224 AutocompleteProviderListener* listener) |
206 : BaseSearchProvider(AutocompleteProvider::TYPE_ZERO_SUGGEST, client), | 225 : BaseSearchProvider(AutocompleteProvider::TYPE_ZERO_SUGGEST, client), |
207 history_url_provider_(history_url_provider), | 226 history_url_provider_(history_url_provider), |
208 listener_(listener), | 227 listener_(listener), |
209 results_from_cache_(false), | 228 results_from_cache_(false), |
210 waiting_for_most_visited_urls_request_(false), | 229 waiting_for_most_visited_urls_request_(false), |
211 weak_ptr_factory_(this) { | 230 weak_ptr_factory_(this) { |
231 // Record whether contextual zero suggest is possible for this user / profile. | |
232 // To check whether this is allowed, use an arbitrary insecure (http) URL | |
Peter Kasting
2017/03/02 21:31:34
Nit: I'd move these last 3/4ths of the comment to
Mark P
2017/03/02 23:17:00
Good diagnosis of the situation. Done.
| |
233 // as the URL we'd want suggestions for. The value of OTHER as the current | |
234 // page classification is to correspond with that URL. | |
235 const TemplateURLService* template_url_service = | |
236 client->GetTemplateURLService(); | |
237 // Template URL service can be null in tests. | |
238 if (template_url_service != nullptr) { | |
Peter Kasting
2017/03/02 21:31:34
Nit: Optional, but I find it slightly more common
Mark P
2017/03/02 23:17:00
Left as is. (That may be true in general in the c
| |
239 GURL suggest_url(GetContextualSuggestionsUrl()); | |
240 UMA_HISTOGRAM_BOOLEAN( | |
241 "Omnibox.ZeroSuggest.Eligible.OnProfileOpen", | |
242 suggest_url.is_valid() && | |
243 CanSendURL(GURL(kArbitraryInsecureUrlString), suggest_url, | |
244 template_url_service->GetDefaultSearchProvider(), | |
245 metrics::OmniboxEventProto::OTHER, | |
246 template_url_service->search_terms_data(), client)); | |
247 } | |
212 } | 248 } |
213 | 249 |
214 ZeroSuggestProvider::~ZeroSuggestProvider() { | 250 ZeroSuggestProvider::~ZeroSuggestProvider() { |
215 } | 251 } |
216 | 252 |
217 const TemplateURL* ZeroSuggestProvider::GetTemplateURL(bool is_keyword) const { | 253 const TemplateURL* ZeroSuggestProvider::GetTemplateURL(bool is_keyword) const { |
218 // Zero suggest provider should not receive keyword results. | 254 // Zero suggest provider should not receive keyword results. |
219 DCHECK(!is_keyword); | 255 DCHECK(!is_keyword); |
220 return client()->GetTemplateURLService()->GetDefaultSearchProvider(); | 256 return client()->GetTemplateURLService()->GetDefaultSearchProvider(); |
221 } | 257 } |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
472 | 508 |
473 if (OmniboxFieldTrial::InZeroSuggestMostVisitedWithoutSerpFieldTrial() && | 509 if (OmniboxFieldTrial::InZeroSuggestMostVisitedWithoutSerpFieldTrial() && |
474 client() | 510 client() |
475 ->GetTemplateURLService() | 511 ->GetTemplateURLService() |
476 ->IsSearchResultsPageFromDefaultSearchProvider(current_page_url)) | 512 ->IsSearchResultsPageFromDefaultSearchProvider(current_page_url)) |
477 return false; | 513 return false; |
478 | 514 |
479 return true; | 515 return true; |
480 } | 516 } |
481 | 517 |
518 std::string ZeroSuggestProvider::GetContextualSuggestionsUrl() const { | |
519 // Without a default search provider, refuse to do anything (even if the user | |
520 // in the redirect-to-chrome field trial). | |
Peter Kasting
2017/03/02 21:31:34
Nit: in -> is in
Mark P
2017/03/02 23:17:00
Done.
| |
521 const TemplateURLService* template_url_service = | |
522 client()->GetTemplateURLService(); | |
523 const TemplateURL* default_provider = | |
524 template_url_service->GetDefaultSearchProvider(); | |
525 if (default_provider == nullptr) | |
526 return ""; | |
Peter Kasting
2017/03/02 21:31:34
Nit: "" -> std::string()
Mark P
2017/03/02 23:17:00
Done.
| |
527 | |
528 if (OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial()) { | |
Peter Kasting
2017/03/02 21:31:34
Nit: No {}
Mark P
2017/03/02 23:17:00
Done.
| |
529 return OmniboxFieldTrial::ZeroSuggestRedirectToChromeServerAddress(); | |
530 } | |
531 base::string16 prefix; | |
Peter Kasting
2017/03/02 21:31:34
Nit: Can just pass string16() in the call below, n
Mark P
2017/03/02 23:17:00
See earlier comment.
| |
532 TemplateURLRef::SearchTermsArgs search_term_args(prefix); | |
533 return default_provider->suggestions_url_ref().ReplaceSearchTerms( | |
534 search_term_args, template_url_service->search_terms_data()); | |
535 } | |
536 | |
482 void ZeroSuggestProvider::MaybeUseCachedSuggestions() { | 537 void ZeroSuggestProvider::MaybeUseCachedSuggestions() { |
483 if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial()) | 538 if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial()) |
484 return; | 539 return; |
485 | 540 |
486 std::string json_data = | 541 std::string json_data = |
487 client()->GetPrefs()->GetString(omnibox::kZeroSuggestCachedResults); | 542 client()->GetPrefs()->GetString(omnibox::kZeroSuggestCachedResults); |
488 if (!json_data.empty()) { | 543 if (!json_data.empty()) { |
489 std::unique_ptr<base::Value> data( | 544 std::unique_ptr<base::Value> data( |
490 SearchSuggestionParser::DeserializeJsonData(json_data)); | 545 SearchSuggestionParser::DeserializeJsonData(json_data)); |
491 if (data && ParseSuggestResults( | 546 if (data && ParseSuggestResults( |
492 *data, kDefaultZeroSuggestRelevance, false, &results_)) { | 547 *data, kDefaultZeroSuggestRelevance, false, &results_)) { |
493 ConvertResultsToAutocompleteMatches(); | 548 ConvertResultsToAutocompleteMatches(); |
494 results_from_cache_ = !matches_.empty(); | 549 results_from_cache_ = !matches_.empty(); |
495 } | 550 } |
496 } | 551 } |
497 } | 552 } |
OLD | NEW |