Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: components/omnibox/browser/zero_suggest_provider.cc

Issue 2965173002: Add ContextualSuggestionsService to Omnibox (Closed)
Patch Set: Move contextual suggestions service to c/o/b Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/feature_list.h" 10 #include "base/feature_list.h"
11 #include "base/i18n/case_conversion.h" 11 #include "base/i18n/case_conversion.h"
12 #include "base/json/json_string_value_serializer.h" 12 #include "base/json/json_string_value_serializer.h"
13 #include "base/metrics/histogram_macros.h" 13 #include "base/metrics/histogram_macros.h"
14 #include "base/metrics/user_metrics.h" 14 #include "base/metrics/user_metrics.h"
15 #include "base/strings/string16.h" 15 #include "base/strings/string16.h"
16 #include "base/strings/string_util.h" 16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h" 17 #include "base/strings/utf_string_conversions.h"
18 #include "base/time/time.h" 18 #include "base/time/time.h"
19 #include "base/trace_event/trace_event.h" 19 #include "base/trace_event/trace_event.h"
20 #include "components/data_use_measurement/core/data_use_user_data.h" 20 #include "components/data_use_measurement/core/data_use_user_data.h"
21 #include "components/history/core/browser/history_types.h" 21 #include "components/history/core/browser/history_types.h"
22 #include "components/history/core/browser/top_sites.h" 22 #include "components/history/core/browser/top_sites.h"
23 #include "components/metrics/proto/omnibox_event.pb.h" 23 #include "components/metrics/proto/omnibox_event.pb.h"
24 #include "components/metrics/proto/omnibox_input_type.pb.h" 24 #include "components/metrics/proto/omnibox_input_type.pb.h"
25 #include "components/omnibox/browser/autocomplete_classifier.h" 25 #include "components/omnibox/browser/autocomplete_classifier.h"
26 #include "components/omnibox/browser/autocomplete_input.h" 26 #include "components/omnibox/browser/autocomplete_input.h"
27 #include "components/omnibox/browser/autocomplete_match.h" 27 #include "components/omnibox/browser/autocomplete_match.h"
28 #include "components/omnibox/browser/autocomplete_provider_listener.h" 28 #include "components/omnibox/browser/autocomplete_provider_listener.h"
29 #include "components/omnibox/browser/contextual_suggestions_service.h"
29 #include "components/omnibox/browser/history_url_provider.h" 30 #include "components/omnibox/browser/history_url_provider.h"
30 #include "components/omnibox/browser/omnibox_field_trial.h" 31 #include "components/omnibox/browser/omnibox_field_trial.h"
31 #include "components/omnibox/browser/omnibox_pref_names.h" 32 #include "components/omnibox/browser/omnibox_pref_names.h"
32 #include "components/omnibox/browser/search_provider.h" 33 #include "components/omnibox/browser/search_provider.h"
33 #include "components/omnibox/browser/verbatim_match.h" 34 #include "components/omnibox/browser/verbatim_match.h"
34 #include "components/pref_registry/pref_registry_syncable.h" 35 #include "components/pref_registry/pref_registry_syncable.h"
35 #include "components/prefs/pref_service.h" 36 #include "components/prefs/pref_service.h"
36 #include "components/search_engines/template_url_service.h" 37 #include "components/search_engines/template_url_service.h"
37 #include "components/url_formatter/url_formatter.h" 38 #include "components/url_formatter/url_formatter.h"
38 #include "components/variations/net/variations_http_headers.h" 39 #include "components/variations/net/variations_http_headers.h"
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 UMA_HISTOGRAM_ENUMERATION("Omnibox.ZeroSuggestRequests", request_value, 79 UMA_HISTOGRAM_ENUMERATION("Omnibox.ZeroSuggestRequests", request_value,
79 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE); 80 ZERO_SUGGEST_MAX_REQUEST_HISTOGRAM_VALUE);
80 } 81 }
81 82
82 // Relevance value to use if it was not set explicitly by the server. 83 // Relevance value to use if it was not set explicitly by the server.
83 const int kDefaultZeroSuggestRelevance = 100; 84 const int kDefaultZeroSuggestRelevance = 100;
84 85
85 // Used for testing whether zero suggest is ever available. 86 // Used for testing whether zero suggest is ever available.
86 constexpr char kArbitraryInsecureUrlString[] = "http://www.google.com/"; 87 constexpr char kArbitraryInsecureUrlString[] = "http://www.google.com/";
87 88
88 // Returns true if the folowing conditions are valid:
89 // * The |default_provider| is Google.
90 // * The user is in the ZeroSuggestRedirectToChrome field trial.
91 // * The field trial provides a valid server address where the suggest request
92 // is redirected.
93 // * The suggest request is over HTTPS. This avoids leaking the current page URL
94 // or personal data in unencrypted network traffic.
95 // Note: these checks are in addition to CanSendUrl() on the default contextual
96 // suggestion URL.
97 bool UseExperimentalSuggestService(const TemplateURLService& default_provider) {
98 const TemplateURL& default_provider_url =
99 *default_provider.GetDefaultSearchProvider();
100 const SearchTermsData& search_terms_data =
101 default_provider.search_terms_data();
102 if ((default_provider_url.GetEngineType(search_terms_data) !=
103 SEARCH_ENGINE_GOOGLE) ||
104 !OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial())
105 return false;
106 // Check that the suggest URL for redirect to chrome field trial is valid.
107 const GURL suggest_url(
108 OmniboxFieldTrial::ZeroSuggestRedirectToChromeServerAddress());
109 if (!suggest_url.is_valid())
110 return false;
111 return suggest_url.SchemeIsCryptographic();
112 }
113
114 } // namespace 89 } // namespace
115 90
116 // static 91 // static
117 ZeroSuggestProvider* ZeroSuggestProvider::Create( 92 ZeroSuggestProvider* ZeroSuggestProvider::Create(
118 AutocompleteProviderClient* client, 93 AutocompleteProviderClient* client,
119 HistoryURLProvider* history_url_provider, 94 HistoryURLProvider* history_url_provider,
120 AutocompleteProviderListener* listener) { 95 AutocompleteProviderListener* listener) {
121 return new ZeroSuggestProvider(client, history_url_provider, listener); 96 return new ZeroSuggestProvider(client, history_url_provider, listener);
122 } 97 }
123 98
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 CanSendURL(arbitrary_insecure_url, suggest_url, default_provider, 142 CanSendURL(arbitrary_insecure_url, suggest_url, default_provider,
168 current_page_classification_, 143 current_page_classification_,
169 template_url_service->search_terms_data(), client()); 144 template_url_service->search_terms_data(), client());
170 eligibility = can_send_ordinary_url 145 eligibility = can_send_ordinary_url
171 ? ZeroSuggestEligibility::URL_INELIGIBLE 146 ? ZeroSuggestEligibility::URL_INELIGIBLE
172 : ZeroSuggestEligibility::GENERALLY_INELIGIBLE; 147 : ZeroSuggestEligibility::GENERALLY_INELIGIBLE;
173 } 148 }
174 UMA_HISTOGRAM_ENUMERATION( 149 UMA_HISTOGRAM_ENUMERATION(
175 "Omnibox.ZeroSuggest.Eligible.OnFocus", static_cast<int>(eligibility), 150 "Omnibox.ZeroSuggest.Eligible.OnFocus", static_cast<int>(eligibility),
176 static_cast<int>(ZeroSuggestEligibility::ELIGIBLE_MAX_VALUE)); 151 static_cast<int>(ZeroSuggestEligibility::ELIGIBLE_MAX_VALUE));
177 if (can_send_current_url && 152
153 bool attach_current_url =
Mark P 2017/07/18 19:11:30 optional nit: how about can_attach_current_url?
154 can_send_current_url &&
178 !OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() && 155 !OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() &&
179 !OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) { 156 !OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial();
180 // Update suggest_url to include the current_page_url. 157
181 if (UseExperimentalSuggestService(*template_url_service)) { 158 if (!attach_current_url &&
182 suggest_url = GURL( 159 !ShouldShowNonContextualZeroSuggest(input.current_url())) {
183 OmniboxFieldTrial::ZeroSuggestRedirectToChromeServerAddress() +
184 "/url=" + net::EscapePath(current_query_) +
185 OmniboxFieldTrial::ZeroSuggestRedirectToChromeAdditionalFields());
186 } else {
187 base::string16 prefix;
188 TemplateURLRef::SearchTermsArgs search_term_args(prefix);
189 search_term_args.current_page_url = current_query_;
190 suggest_url =
191 GURL(default_provider->suggestions_url_ref().ReplaceSearchTerms(
192 search_term_args, template_url_service->search_terms_data()));
193 }
194 } else if (!ShouldShowNonContextualZeroSuggest(input.current_url())) {
195 return; 160 return;
196 } 161 }
197 162
198 done_ = false;
Mark P 2017/07/18 19:11:30 I think this line should probably stay. I wonder
199 // TODO(jered): Consider adding locally-sourced zero-suggestions here too. 163 // TODO(jered): Consider adding locally-sourced zero-suggestions here too.
200 // These may be useful on the NTP or more relevant to the user than server 164 // These may be useful on the NTP or more relevant to the user than server
201 // suggestions, if based on local browsing history. 165 // suggestions, if based on local browsing history.
202 MaybeUseCachedSuggestions(); 166 MaybeUseCachedSuggestions();
203 Run(suggest_url); 167
168 if (OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) {
169 most_visited_urls_.clear();
170 scoped_refptr<history::TopSites> ts = client()->GetTopSites();
171 if (ts) {
172 waiting_for_most_visited_urls_request_ = true;
173 ts->GetMostVisitedURLs(
174 base::Bind(&ZeroSuggestProvider::OnMostVisitedUrlsAvailable,
175 weak_ptr_factory_.GetWeakPtr()),
176 false);
177 }
178 return;
179 }
180
181 // Create a request for experimental suggestions with |this| as the
182 // fetcher delegate.
183 client()
184 ->GetContextualSuggestionsService()
Mark P 2017/07/18 19:11:30 Is GetContextualSuggestionsService() always going
185 ->CreateContextualSuggestionsRequest(
186 attach_current_url ? current_query_ : std::string(),
187 /*fetcher_delegate=*/this,
188 base::BindOnce(
189 &ZeroSuggestProvider::OnContextualSuggestionsFetcherAvailable,
190 weak_ptr_factory_.GetWeakPtr()));
191 }
192
193 void ZeroSuggestProvider::OnContextualSuggestionsFetcherAvailable(
Mark P 2017/07/18 19:11:30 nit: Definitions in the .cc file should be in the
194 std::unique_ptr<net::URLFetcher> fetcher) {
195 if (fetcher == nullptr) {
Mark P 2017/07/18 19:11:30 Why / how can this happen? Also, since we're going
196 return;
197 }
198 fetcher_ = std::move(fetcher);
199 done_ = false;
Mark P 2017/07/18 19:11:30 I don't think this is the right place to set done_
200 fetcher_->Start();
201 LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_SENT);
204 } 202 }
205 203
206 void ZeroSuggestProvider::Stop(bool clear_cached_results, 204 void ZeroSuggestProvider::Stop(bool clear_cached_results,
207 bool due_to_user_inactivity) { 205 bool due_to_user_inactivity) {
208 if (fetcher_) 206 if (fetcher_)
209 LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_INVALIDATED); 207 LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_INVALIDATED);
210 fetcher_.reset(); 208 fetcher_.reset();
211 waiting_for_most_visited_urls_request_ = false; 209 waiting_for_most_visited_urls_request_ = false;
212 done_ = true; 210 done_ = true;
213 211
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 387
390 match.description = 388 match.description =
391 AutocompleteMatch::SanitizeString(navigation.description()); 389 AutocompleteMatch::SanitizeString(navigation.description());
392 AutocompleteMatch::ClassifyLocationInString(base::string16::npos, 0, 390 AutocompleteMatch::ClassifyLocationInString(base::string16::npos, 0,
393 match.description.length(), ACMatchClassification::NONE, 391 match.description.length(), ACMatchClassification::NONE,
394 &match.description_class); 392 &match.description_class);
395 match.subtype_identifier = navigation.subtype_identifier(); 393 match.subtype_identifier = navigation.subtype_identifier();
396 return match; 394 return match;
397 } 395 }
398 396
399 void ZeroSuggestProvider::Run(const GURL& suggest_url) {
400 if (OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) {
401 most_visited_urls_.clear();
402 scoped_refptr<history::TopSites> ts = client()->GetTopSites();
403 if (ts) {
404 waiting_for_most_visited_urls_request_ = true;
405 ts->GetMostVisitedURLs(
406 base::Bind(&ZeroSuggestProvider::OnMostVisitedUrlsAvailable,
407 weak_ptr_factory_.GetWeakPtr()), false);
408 }
409 } else {
410 net::NetworkTrafficAnnotationTag traffic_annotation =
411 net::DefineNetworkTrafficAnnotation("omnibox_zerosuggest", R"(
412 semantics {
413 sender: "Omnibox"
414 description:
415 "When the user focuses the omnibox, Chrome can provide search or "
416 "navigation suggestions from the default search provider in the "
417 "omnibox dropdown, based on the current page URL.\n"
418 "This is limited to users whose default search engine is Google, "
419 "as no other search engines currently support this kind of "
420 "suggestion."
421 trigger: "The omnibox receives focus."
422 data: "The URL of the current page."
423 destination: GOOGLE_OWNED_SERVICE
424 }
425 policy {
426 cookies_allowed: true
427 cookies_store: "user"
428 setting:
429 "Users can control this feature via the 'Use a prediction service "
430 "to help complete searches and URLs typed in the address bar' "
431 "settings under 'Privacy'. The feature is enabled by default."
432 chrome_policy {
433 SearchSuggestEnabled {
434 policy_options {mode: MANDATORY}
435 SearchSuggestEnabled: false
436 }
437 }
438 })");
439 const int kFetcherID = 1;
440 fetcher_ =
441 net::URLFetcher::Create(kFetcherID, suggest_url, net::URLFetcher::GET,
442 this, traffic_annotation);
443 data_use_measurement::DataUseUserData::AttachToFetcher(
444 fetcher_.get(), data_use_measurement::DataUseUserData::OMNIBOX);
445 fetcher_->SetRequestContext(client()->GetRequestContext());
446 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
447 // Add Chrome experiment state to the request headers.
448 net::HttpRequestHeaders headers;
449 // Note: It's OK to pass |is_signed_in| false if it's unknown, as it does
450 // not affect transmission of experiments coming from the variations server.
451 bool is_signed_in = false;
452 variations::AppendVariationHeaders(fetcher_->GetOriginalURL(),
453 client()->IsOffTheRecord(), false,
454 is_signed_in, &headers);
455 fetcher_->SetExtraRequestHeaders(headers.ToString());
456 fetcher_->Start();
457 LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_SENT);
458 }
459 }
460
461 void ZeroSuggestProvider::OnMostVisitedUrlsAvailable( 397 void ZeroSuggestProvider::OnMostVisitedUrlsAvailable(
462 const history::MostVisitedURLList& urls) { 398 const history::MostVisitedURLList& urls) {
463 if (!waiting_for_most_visited_urls_request_) return; 399 if (!waiting_for_most_visited_urls_request_) return;
464 most_visited_urls_ = urls; 400 most_visited_urls_ = urls;
465 waiting_for_most_visited_urls_request_ = false; 401 waiting_for_most_visited_urls_request_ = false;
466 done_ = true; 402 done_ = true;
467 ConvertResultsToAutocompleteMatches(); 403 ConvertResultsToAutocompleteMatches();
468 listener_->OnProviderUpdate(true); 404 listener_->OnProviderUpdate(true);
469 } 405 }
470 406
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 if (!json_data.empty()) { 537 if (!json_data.empty()) {
602 std::unique_ptr<base::Value> data( 538 std::unique_ptr<base::Value> data(
603 SearchSuggestionParser::DeserializeJsonData(json_data)); 539 SearchSuggestionParser::DeserializeJsonData(json_data));
604 if (data && ParseSuggestResults( 540 if (data && ParseSuggestResults(
605 *data, kDefaultZeroSuggestRelevance, false, &results_)) { 541 *data, kDefaultZeroSuggestRelevance, false, &results_)) {
606 ConvertResultsToAutocompleteMatches(); 542 ConvertResultsToAutocompleteMatches();
607 results_from_cache_ = !matches_.empty(); 543 results_from_cache_ = !matches_.empty();
608 } 544 }
609 } 545 }
610 } 546 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698