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

Side by Side Diff: components/omnibox/browser/contextual_suggestions_service.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
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/omnibox/browser/contextual_suggestions_service.h"
6
7 #include "base/feature_list.h"
8 #include "base/memory/ptr_util.h"
9 #include "base/metrics/field_trial_params.h"
10 #include "base/strings/stringprintf.h"
11 #include "components/data_use_measurement/core/data_use_user_data.h"
12 #include "components/omnibox/browser/omnibox_field_trial.h"
13 #include "components/variations/net/variations_http_headers.h"
14 #include "net/base/escape.h"
15 #include "net/base/load_flags.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/traffic_annotation/network_traffic_annotation.h"
18 #include "net/url_request/url_fetcher.h"
19
20 namespace contextual_suggestions {
21
22 namespace {
23 // Server address for the experimental suggestions service.
24 const char kExperimentalServerAddress[] =
25 "https://cuscochromeextension-pa.googleapis.com/v1/zerosuggestions";
26
27 // Parameter name used by the experiment redirecting Zero Suggestion requests
28 // to a service provided by the Chrome team.
29 const char kZeroSuggestRedirectToChromeExperimentIdParam[] =
30 "ZeroSuggestRedirectToChromeExperimentID";
31
32 // Scope for the authentication token attached to the request sent to the
33 // experimental service.
34 const char kScopeForExperimentalService[] =
35 "https://www.googleapis.com/auth/cusco-chrome-extension";
36
37 // Format string for OAuth2 authentication headers.
38 const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
39
40 } // namespace
41
42 ContextualSuggestionsService::ContextualSuggestionsService(
43 SigninManagerBase* signin_manager,
44 OAuth2TokenService* token_service,
45 TemplateURLService* template_url_service,
46 net::URLRequestContextGetter* request_context)
47 : request_context_(request_context),
48 signin_manager_(signin_manager),
49 template_url_service_(template_url_service),
50 token_service_(token_service) {}
51
52 ContextualSuggestionsService::~ContextualSuggestionsService() {}
53
54 bool ContextualSuggestionsService::UseExperimentalZeroSuggestSuggestions(
55 const std::string& visited_url) const {
56 if (visited_url.empty()) {
57 return false;
58 }
59
60 if (!base::FeatureList::IsEnabled(omnibox::kZeroSuggestRedirectToChrome) ||
61 template_url_service_ == nullptr) {
62 return false;
63 }
64
65 // Check that the default search engine is Google.
66 const TemplateURL& default_provider_url =
67 *template_url_service_->GetDefaultSearchProvider();
68 const SearchTermsData& search_terms_data =
69 template_url_service_->search_terms_data();
70 if (default_provider_url.GetEngineType(search_terms_data) !=
71 SEARCH_ENGINE_GOOGLE) {
72 return false;
73 }
74
75 // Check that the suggest URL for redirect to chrome field trial is valid.
76 const GURL suggest_url =
77 ExperimentalZeroSuggestURL(/*visited_url=*/std::string());
Mark P 2017/07/18 19:11:28 Shouldn't you provide a real URL here? I wouldn't
Toyama 2017/07/18 20:28:47 I don't have the right context here, but everythin
78 if (!suggest_url.is_valid()) {
79 return false;
80 }
81
82 // Check that the suggest URL for redirect to chrome is HTTPS.
83 return suggest_url.SchemeIsCryptographic();
84 }
85
86 void ContextualSuggestionsService::CreateContextualSuggestionsRequest(
87 const std::string& visited_url,
88 net::URLFetcherDelegate* fetcher_delegate,
89 ContextualSuggestionsCallback callback) {
90 DCHECK(signin_manager_);
91 DCHECK(token_service_);
92
93 const bool experimental = UseExperimentalZeroSuggestSuggestions(visited_url);
94 std::unique_ptr<net::URLFetcher> fetcher =
95 CreateRequest(visited_url, experimental, fetcher_delegate);
96 if (fetcher == nullptr) {
97 std::move(callback).Run(nullptr);
98 return;
99 }
100
101 if (experimental) {
102 // Skip this request if still waiting for oauth2 token.
103 if (token_fetcher_) {
104 std::move(callback).Run(nullptr);
105 return;
106 }
107 // Create the oauth2 token fetcher.
108 OAuth2TokenService::ScopeSet scopes{kScopeForExperimentalService};
109 token_fetcher_ = base::MakeUnique<AccessTokenFetcher>(
110 "contextual_suggestions_service", signin_manager_, token_service_,
111 scopes,
112 base::BindOnce(&ContextualSuggestionsService::AccessTokenAvailable,
113 base::Unretained(this), std::move(fetcher),
114 std::move(callback)));
115 return;
116 }
117
118 std::move(callback).Run(std::move(fetcher));
119 }
120
121 // static
122 GURL ContextualSuggestionsService::ExperimentalZeroSuggestURL(
123 const std::string& visited_url) {
124 const std::string server_address(kExperimentalServerAddress);
125 const int experiment_id = base::GetFieldTrialParamByFeatureAsInt(
126 omnibox::kZeroSuggestRedirectToChrome,
127 kZeroSuggestRedirectToChromeExperimentIdParam, /*default_value=*/-1);
128 const std::string additional_parameters =
129 experiment_id >= 0
130 ? base::StringPrintf("&experiment_id=%d", experiment_id)
131 : "&";
132 return GURL(server_address + "/url=" + net::EscapePath(visited_url) +
133 additional_parameters);
134 }
135
136 GURL ContextualSuggestionsService::ZeroSuggestURL(
137 const std::string& visited_url,
138 bool experimental) const {
139 if (experimental) {
140 return ExperimentalZeroSuggestURL(visited_url);
141 }
142
143 const TemplateURLRef& suggestion_url_ref =
144 template_url_service_->GetDefaultSearchProvider()->suggestions_url_ref();
145 const SearchTermsData& search_terms_data =
146 template_url_service_->search_terms_data();
147 base::string16 prefix;
148 TemplateURLRef::SearchTermsArgs search_term_args(prefix);
149 if (!visited_url.empty()) {
150 search_term_args.current_page_url = visited_url;
151 }
152 return GURL(suggestion_url_ref.ReplaceSearchTerms(search_term_args,
153 search_terms_data));
154 }
155
156 std::unique_ptr<net::URLFetcher> ContextualSuggestionsService::CreateRequest(
157 const std::string& visited_url,
158 bool experimental,
159 net::URLFetcherDelegate* fetcher_delegate) const {
160 const GURL suggest_url = ZeroSuggestURL(visited_url, experimental);
161 DCHECK(suggest_url.is_valid());
162
163 if (visited_url.empty())
164 experimental = false;
165 const int kFetcherID = 1;
166 net::NetworkTrafficAnnotationTag annotation_tag =
167 experimental
168 ? net::DefineNetworkTrafficAnnotation(
169 "omnibox_zerosuggest_experimental", R"(
170 semantics {
171 sender: "Omnibox"
172 description:
173 "When the user focuses the omnibox, Chrome can provide search or "
174 "navigation suggestions from the default search provider in the "
175 "omnibox dropdown, based on the current page URL.\n"
176 "This is limited to users whose default search engine is Google, "
177 "as no other search engines currently support this kind of "
178 "suggestion."
179 trigger: "The omnibox receives focus."
180 data: "The user's OAuth2 credentials and the URL of the current page."
181 destination: GOOGLE_OWNED_SERVICE
182 }
183 policy {
184 cookies_allowed: false
185 setting:
186 "Users can control this feature via the 'Use a prediction service "
187 "to help complete searches and URLs typed in the address bar' "
188 "settings under 'Privacy'. The feature is enabled by default."
189 chrome_policy {
190 SearchSuggestEnabled {
191 policy_options {mode: MANDATORY}
192 SearchSuggestEnabled: false
193 }
194 }
195 })")
196 : net::DefineNetworkTrafficAnnotation("omnibox_zerosuggest", R"(
197 semantics {
198 sender: "Omnibox"
199 description:
200 "When the user focuses the omnibox, Chrome can provide search or "
201 "navigation suggestions from the default search provider in the "
202 "omnibox dropdown, based on the current page URL.\n"
203 "This is limited to users whose default search engine is Google, "
204 "as no other search engines currently support this kind of "
205 "suggestion."
206 trigger: "The omnibox receives focus."
207 data: "The URL of the current page."
208 destination: GOOGLE_OWNED_SERVICE
209 }
210 policy {
211 cookies_allowed: true
212 cookies_store: "user"
213 setting:
214 "Users can control this feature via the 'Use a prediction service "
215 "to help complete searches and URLs typed in the address bar' "
216 "settings under 'Privacy'. The feature is enabled by default."
217 chrome_policy {
218 SearchSuggestEnabled {
219 policy_options {mode: MANDATORY}
220 SearchSuggestEnabled: false
221 }
222 }
223 })");
224
225 std::unique_ptr<net::URLFetcher> fetcher =
226 net::URLFetcher::Create(kFetcherID, suggest_url, net::URLFetcher::GET,
227 fetcher_delegate, annotation_tag);
228 fetcher->SetRequestContext(request_context_);
229 if (experimental) {
230 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
231 net::LOAD_DO_NOT_SAVE_COOKIES);
232 } else {
233 data_use_measurement::DataUseUserData::AttachToFetcher(
234 fetcher.get(), data_use_measurement::DataUseUserData::OMNIBOX);
235 fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
236 // Add Chrome experiment state to the request headers.
237 net::HttpRequestHeaders headers;
238 // Note: It's OK to pass |is_signed_in| false if it's unknown, as it does
239 // not affect transmission of experiments coming from the variations server.
240 variations::AppendVariationHeaders(fetcher->GetOriginalURL(), false, false,
241 /*is_signed_in=*/false, &headers);
242 fetcher->SetExtraRequestHeaders(headers.ToString());
243 }
244 return fetcher;
245 }
246
247 void ContextualSuggestionsService::AccessTokenAvailable(
248 std::unique_ptr<net::URLFetcher> fetcher,
249 ContextualSuggestionsCallback callback,
250 const GoogleServiceAuthError& error,
251 const std::string& access_token) {
252 DCHECK(token_fetcher_);
253 std::unique_ptr<AccessTokenFetcher> token_fetcher_deleter(
254 std::move(token_fetcher_));
255
256 if (error.state() != GoogleServiceAuthError::NONE) {
257 std::move(callback).Run(nullptr);
258 return;
259 }
260 DCHECK(!access_token.empty());
261 fetcher->AddExtraRequestHeader(
262 base::StringPrintf(kAuthorizationHeaderFormat, access_token.c_str()));
263 std::move(callback).Run(std::move(fetcher));
264 }
265
266 } // namespace contextual_suggestions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698