OLD | NEW |
---|---|
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/ntp_snippets/ntp_snippets_fetcher.h" | 5 #include "components/ntp_snippets/ntp_snippets_fetcher.h" |
6 | 6 |
7 #include <stdlib.h> | 7 #include <stdlib.h> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
11 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
12 #include "base/json/json_writer.h" | |
13 #include "base/memory/ptr_util.h" | |
12 #include "base/metrics/histogram_macros.h" | 14 #include "base/metrics/histogram_macros.h" |
13 #include "base/metrics/sparse_histogram.h" | 15 #include "base/metrics/sparse_histogram.h" |
14 #include "base/path_service.h" | 16 #include "base/path_service.h" |
15 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
16 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
17 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
18 #include "base/time/default_tick_clock.h" | 20 #include "base/time/default_tick_clock.h" |
19 #include "base/values.h" | 21 #include "base/values.h" |
20 #include "components/data_use_measurement/core/data_use_user_data.h" | 22 #include "components/data_use_measurement/core/data_use_user_data.h" |
21 #include "components/ntp_snippets/ntp_snippets_constants.h" | 23 #include "components/ntp_snippets/ntp_snippets_constants.h" |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
55 | 57 |
56 // Constants for possible values of the "fetching_personalization" parameter. | 58 // Constants for possible values of the "fetching_personalization" parameter. |
57 const char kPersonalizationPersonalString[] = "personal"; | 59 const char kPersonalizationPersonalString[] = "personal"; |
58 const char kPersonalizationNonPersonalString[] = "non_personal"; | 60 const char kPersonalizationNonPersonalString[] = "non_personal"; |
59 const char kPersonalizationBothString[] = "both"; // the default value | 61 const char kPersonalizationBothString[] = "both"; // the default value |
60 | 62 |
61 // Constants for possible values of the "fetching_host_restrict" parameter. | 63 // Constants for possible values of the "fetching_host_restrict" parameter. |
62 const char kHostRestrictionOnString[] = "on"; // the default value | 64 const char kHostRestrictionOnString[] = "on"; // the default value |
63 const char kHostRestrictionOffString[] = "off"; | 65 const char kHostRestrictionOffString[] = "off"; |
64 | 66 |
65 const char kRequestFormat[] = | |
66 "{" | |
67 " \"response_detail_level\": \"STANDARD\"," | |
68 "%s" // If authenticated - an obfuscated Gaia ID will be inserted here. | |
69 " \"advanced_options\": {" | |
70 " \"local_scoring_params\": {" | |
71 " \"content_params\": {" | |
72 " \"only_return_personalized_results\": %s" | |
73 "%s" // If authenticated - user segment (lang code) will be inserted here. | |
74 " }," | |
75 " \"content_restricts\": [" | |
76 " {" | |
77 " \"type\": \"METADATA\"," | |
78 " \"value\": \"TITLE\"" | |
79 " }," | |
80 " {" | |
81 " \"type\": \"METADATA\"," | |
82 " \"value\": \"SNIPPET\"" | |
83 " }," | |
84 " {" | |
85 " \"type\": \"METADATA\"," | |
86 " \"value\": \"THUMBNAIL\"" | |
87 " }" | |
88 " ]," | |
89 " \"content_selectors\": [%s]" | |
90 " }," | |
91 " \"global_scoring_params\": {" | |
92 " \"num_to_return\": %i," | |
93 " \"sort_type\": 1" | |
94 " }" | |
95 " }" | |
96 "}"; | |
97 | |
98 const char kGaiaIdFormat[] = " \"obfuscated_gaia_id\": \"%s\","; | |
99 const char kUserSegmentFormat[] = " ,\"user_segment\": \"%s\""; | |
100 const char kHostRestrictFormat[] = | |
101 " {" | |
102 " \"type\": \"HOST_RESTRICT\"," | |
103 " \"value\": \"%s\"" | |
104 " }"; | |
105 const char kTrueString[] = "true"; | |
106 const char kFalseString[] = "false"; | |
107 | |
108 std::string FetchResultToString(NTPSnippetsFetcher::FetchResult result) { | 67 std::string FetchResultToString(NTPSnippetsFetcher::FetchResult result) { |
109 switch (result) { | 68 switch (result) { |
110 case NTPSnippetsFetcher::FetchResult::SUCCESS: | 69 case NTPSnippetsFetcher::FetchResult::SUCCESS: |
111 return "OK"; | 70 return "OK"; |
112 case NTPSnippetsFetcher::FetchResult::EMPTY_HOSTS: | 71 case NTPSnippetsFetcher::FetchResult::EMPTY_HOSTS: |
113 return "Cannot fetch for empty hosts list."; | 72 return "Cannot fetch for empty hosts list."; |
114 case NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR: | 73 case NTPSnippetsFetcher::FetchResult::URL_REQUEST_STATUS_ERROR: |
115 return "URLRequestStatus error"; | 74 return "URLRequestStatus error"; |
116 case NTPSnippetsFetcher::FetchResult::HTTP_ERROR: | 75 case NTPSnippetsFetcher::FetchResult::HTTP_ERROR: |
117 return "HTTP error"; | 76 return "HTTP error"; |
118 case NTPSnippetsFetcher::FetchResult::JSON_PARSE_ERROR: | 77 case NTPSnippetsFetcher::FetchResult::JSON_PARSE_ERROR: |
119 return "Received invalid JSON"; | 78 return "Received invalid JSON"; |
120 case NTPSnippetsFetcher::FetchResult::INVALID_SNIPPET_CONTENT_ERROR: | 79 case NTPSnippetsFetcher::FetchResult::INVALID_SNIPPET_CONTENT_ERROR: |
121 return "Invalid / empty list."; | 80 return "Invalid / empty list."; |
122 case NTPSnippetsFetcher::FetchResult::OAUTH_TOKEN_ERROR: | 81 case NTPSnippetsFetcher::FetchResult::OAUTH_TOKEN_ERROR: |
123 return "Error in obtaining an OAuth2 access token."; | 82 return "Error in obtaining an OAuth2 access token."; |
124 case NTPSnippetsFetcher::FetchResult::RESULT_MAX: | 83 case NTPSnippetsFetcher::FetchResult::RESULT_MAX: |
125 break; | 84 break; |
126 } | 85 } |
127 NOTREACHED(); | 86 NOTREACHED(); |
128 return "Unknown error"; | 87 return "Unknown error"; |
129 } | 88 } |
130 | 89 |
131 std::string BuildRequest(const std::string& obfuscated_gaia_id, | |
132 bool only_return_personalized_results, | |
133 const std::string& user_segment, | |
134 const std::string& host_restricts, | |
135 int count_to_fetch) { | |
136 return base::StringPrintf( | |
137 kRequestFormat, obfuscated_gaia_id.c_str(), | |
138 only_return_personalized_results ? kTrueString : kFalseString, | |
139 user_segment.c_str(), host_restricts.c_str(), count_to_fetch); | |
140 } | |
141 | |
142 } // namespace | 90 } // namespace |
143 | 91 |
144 NTPSnippetsFetcher::NTPSnippetsFetcher( | 92 NTPSnippetsFetcher::NTPSnippetsFetcher( |
145 SigninManagerBase* signin_manager, | 93 SigninManagerBase* signin_manager, |
146 OAuth2TokenService* token_service, | 94 OAuth2TokenService* token_service, |
147 scoped_refptr<URLRequestContextGetter> url_request_context_getter, | 95 scoped_refptr<URLRequestContextGetter> url_request_context_getter, |
148 const ParseJSONCallback& parse_json_callback, | 96 const ParseJSONCallback& parse_json_callback, |
149 bool is_stable_channel) | 97 bool is_stable_channel) |
150 : OAuth2TokenService::Consumer("ntp_snippets"), | 98 : OAuth2TokenService::Consumer("ntp_snippets"), |
151 signin_manager_(signin_manager), | 99 signin_manager_(signin_manager), |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
230 // Wait until we get a refresh token. | 178 // Wait until we get a refresh token. |
231 waiting_for_refresh_token_ = true; | 179 waiting_for_refresh_token_ = true; |
232 token_service_->AddObserver(this); | 180 token_service_->AddObserver(this); |
233 } | 181 } |
234 } else { | 182 } else { |
235 // Not signed in: fetch snippets (without authentication). | 183 // Not signed in: fetch snippets (without authentication). |
236 FetchSnippetsNonAuthenticated(); | 184 FetchSnippetsNonAuthenticated(); |
237 } | 185 } |
238 } | 186 } |
239 | 187 |
188 // static | |
189 std::string NTPSnippetsFetcher::BuildRequest( | |
190 const std::string& obfuscated_gaia_id, | |
191 bool only_return_personalized_results, | |
192 const std::string& user_segment, | |
193 const std::set<std::string>& host_restricts, | |
194 int count_to_fetch) { | |
195 auto content_params = base::MakeUnique<base::DictionaryValue>(); | |
196 content_params->SetBoolean("only_return_personalized_results", | |
197 only_return_personalized_results); | |
198 if (!user_segment.empty()) { | |
199 content_params->SetString("user_segment", user_segment); | |
200 } | |
201 | |
202 auto content_restricts = base::MakeUnique<base::ListValue>(); | |
203 for (const auto& metadata : {"TITLE", "SNIPPET", "THUMBNAIL"}) { | |
204 std::unique_ptr<base::DictionaryValue> entry(new base::DictionaryValue); | |
Marc Treib
2016/06/17 15:28:09
Any reason this doesn't use the "auto var = MakeUn
sfiera
2016/06/20 10:21:52
I think I wrote it before Bernhard enlightened me
| |
205 entry->SetString("type", "METADATA"); | |
206 entry->SetString("value", metadata); | |
207 content_restricts->Append(std::move(entry)); | |
208 } | |
209 | |
210 auto content_selectors = base::MakeUnique<base::ListValue>(); | |
211 for (const auto& host : host_restricts) { | |
212 std::unique_ptr<base::DictionaryValue> entry(new base::DictionaryValue); | |
Marc Treib
2016/06/17 15:28:09
Also here.
sfiera
2016/06/20 10:21:52
and copy-pasted it below. Both fixed.
| |
213 entry->SetString("type", "HOST_RESTRICT"); | |
214 entry->SetString("value", host); | |
215 content_selectors->Append(std::move(entry)); | |
216 } | |
217 | |
218 auto local_scoring_params = base::MakeUnique<base::DictionaryValue>(); | |
219 local_scoring_params->Set("content_params", std::move(content_params)); | |
220 local_scoring_params->Set("content_restricts", std::move(content_restricts)); | |
221 local_scoring_params->Set("content_selectors", std::move(content_selectors)); | |
222 | |
223 auto global_scoring_params = base::MakeUnique<base::DictionaryValue>(); | |
224 global_scoring_params->SetInteger("num_to_return", count_to_fetch); | |
225 global_scoring_params->SetInteger("sort_type", 1); | |
226 | |
227 auto advanced = base::MakeUnique<base::DictionaryValue>(); | |
228 advanced->Set("local_scoring_params", std::move(local_scoring_params)); | |
229 advanced->Set("global_scoring_params", std::move(global_scoring_params)); | |
230 | |
231 auto request = base::MakeUnique<base::DictionaryValue>(); | |
232 request->SetString("response_detail_level", "STANDARD"); | |
233 request->Set("advanced_options", std::move(advanced)); | |
234 if (!obfuscated_gaia_id.empty()) { | |
235 request->SetString("obfuscated_gaia_id", obfuscated_gaia_id); | |
236 } | |
237 | |
238 std::string request_json; | |
239 DCHECK(base::JSONWriter::WriteWithOptions( | |
Marc Treib
2016/06/17 15:28:09
The content of the DCHECK will only be executed in
sfiera
2016/06/20 10:21:52
Done.
| |
240 *request, base::JSONWriter::OPTIONS_PRETTY_PRINT, &request_json)); | |
241 return request_json; | |
242 } | |
243 | |
240 void NTPSnippetsFetcher::FetchSnippetsImpl(const GURL& url, | 244 void NTPSnippetsFetcher::FetchSnippetsImpl(const GURL& url, |
241 const std::string& auth_header, | 245 const std::string& auth_header, |
242 const std::string& request) { | 246 const std::string& request) { |
243 url_fetcher_ = URLFetcher::Create(url, URLFetcher::POST, this); | 247 url_fetcher_ = URLFetcher::Create(url, URLFetcher::POST, this); |
244 | 248 |
245 url_fetcher_->SetRequestContext(url_request_context_getter_.get()); | 249 url_fetcher_->SetRequestContext(url_request_context_getter_.get()); |
246 url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 250 url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
247 net::LOAD_DO_NOT_SAVE_COOKIES); | 251 net::LOAD_DO_NOT_SAVE_COOKIES); |
248 | 252 |
249 data_use_measurement::DataUseUserData::AttachToFetcher( | 253 data_use_measurement::DataUseUserData::AttachToFetcher( |
250 url_fetcher_.get(), data_use_measurement::DataUseUserData::NTP_SNIPPETS); | 254 url_fetcher_.get(), data_use_measurement::DataUseUserData::NTP_SNIPPETS); |
251 | 255 |
252 HttpRequestHeaders headers; | 256 HttpRequestHeaders headers; |
253 if (!auth_header.empty()) | 257 if (!auth_header.empty()) |
254 headers.SetHeader("Authorization", auth_header); | 258 headers.SetHeader("Authorization", auth_header); |
255 headers.SetHeader("Content-Type", "application/json; charset=UTF-8"); | 259 headers.SetHeader("Content-Type", "application/json; charset=UTF-8"); |
256 url_fetcher_->SetExtraRequestHeaders(headers.ToString()); | 260 url_fetcher_->SetExtraRequestHeaders(headers.ToString()); |
257 url_fetcher_->SetUploadData("application/json", request); | 261 url_fetcher_->SetUploadData("application/json", request); |
258 // Fetchers are sometimes cancelled because a network change was detected. | 262 // Fetchers are sometimes cancelled because a network change was detected. |
259 url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); | 263 url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); |
260 // Try to make fetching the files bit more robust even with poor connection. | 264 // Try to make fetching the files bit more robust even with poor connection. |
261 url_fetcher_->SetMaxRetriesOn5xx(3); | 265 url_fetcher_->SetMaxRetriesOn5xx(3); |
262 url_fetcher_->Start(); | 266 url_fetcher_->Start(); |
263 } | 267 } |
264 | 268 |
265 std::string NTPSnippetsFetcher::GetHostRestricts() const { | |
266 std::string host_restricts; | |
267 if (UsesHostRestrictions()) { | |
268 for (const std::string& host : hosts_) { | |
269 if (!host_restricts.empty()) | |
270 host_restricts.push_back(','); | |
271 host_restricts += base::StringPrintf(kHostRestrictFormat, host.c_str()); | |
272 } | |
273 } | |
274 return host_restricts; | |
275 } | |
276 | |
277 bool NTPSnippetsFetcher::UsesHostRestrictions() const { | 269 bool NTPSnippetsFetcher::UsesHostRestrictions() const { |
278 return use_host_restriction_ && | 270 return use_host_restriction_ && |
279 !base::CommandLine::ForCurrentProcess()->HasSwitch( | 271 !base::CommandLine::ForCurrentProcess()->HasSwitch( |
280 switches::kDontRestrict); | 272 switches::kDontRestrict); |
281 } | 273 } |
282 | 274 |
283 bool NTPSnippetsFetcher::UsesAuthentication() const { | 275 bool NTPSnippetsFetcher::UsesAuthentication() const { |
284 return (personalization_ == Personalization::kPersonal || | 276 return (personalization_ == Personalization::kPersonal || |
285 personalization_ == Personalization::kBoth); | 277 personalization_ == Personalization::kBoth); |
286 } | 278 } |
287 | 279 |
288 void NTPSnippetsFetcher::FetchSnippetsNonAuthenticated() { | 280 void NTPSnippetsFetcher::FetchSnippetsNonAuthenticated() { |
289 // When not providing OAuth token, we need to pass the Google API key. | 281 // When not providing OAuth token, we need to pass the Google API key. |
290 const std::string& key = is_stable_channel_ | 282 const std::string& key = is_stable_channel_ |
291 ? google_apis::GetAPIKey() | 283 ? google_apis::GetAPIKey() |
292 : google_apis::GetNonStableAPIKey(); | 284 : google_apis::GetNonStableAPIKey(); |
293 GURL url(base::StringPrintf(kSnippetsServerNonAuthorizedFormat, | 285 GURL url(base::StringPrintf(kSnippetsServerNonAuthorizedFormat, |
294 kSnippetsServer, key.c_str())); | 286 kSnippetsServer, key.c_str())); |
295 | 287 |
296 FetchSnippetsImpl(url, std::string(), | 288 FetchSnippetsImpl( |
297 BuildRequest(/*obfuscated_gaia_id=*/std::string(), | 289 url, std::string(), |
298 /*only_return_personalized_results=*/false, | 290 BuildRequest(/*obfuscated_gaia_id=*/std::string(), |
299 /*user_segment=*/std::string(), | 291 /*only_return_personalized_results=*/false, |
300 GetHostRestricts(), count_to_fetch_)); | 292 /*user_segment=*/std::string(), |
293 UsesHostRestrictions() ? hosts_ : std::set<std::string>(), | |
294 count_to_fetch_)); | |
301 } | 295 } |
302 | 296 |
303 void NTPSnippetsFetcher::FetchSnippetsAuthenticated( | 297 void NTPSnippetsFetcher::FetchSnippetsAuthenticated( |
304 const std::string& account_id, | 298 const std::string& account_id, |
305 const std::string& oauth_access_token) { | 299 const std::string& oauth_access_token) { |
306 std::string gaia_id = base::StringPrintf(kGaiaIdFormat, account_id.c_str()); | |
307 std::string user_segment = | |
308 base::StringPrintf(kUserSegmentFormat, locale_.c_str()); | |
309 | |
310 FetchSnippetsImpl( | 300 FetchSnippetsImpl( |
311 GURL(kSnippetsServer), | 301 GURL(kSnippetsServer), |
312 base::StringPrintf(kAuthorizationRequestHeaderFormat, | 302 base::StringPrintf(kAuthorizationRequestHeaderFormat, |
313 oauth_access_token.c_str()), | 303 oauth_access_token.c_str()), |
314 BuildRequest(gaia_id, personalization_ == Personalization::kPersonal, | 304 BuildRequest(account_id, personalization_ == Personalization::kPersonal, |
315 user_segment, GetHostRestricts(), count_to_fetch_)); | 305 locale_, |
306 UsesHostRestrictions() ? hosts_ : std::set<std::string>(), | |
307 count_to_fetch_)); | |
316 } | 308 } |
317 | 309 |
318 void NTPSnippetsFetcher::StartTokenRequest() { | 310 void NTPSnippetsFetcher::StartTokenRequest() { |
319 OAuth2TokenService::ScopeSet scopes; | 311 OAuth2TokenService::ScopeSet scopes; |
320 scopes.insert(kApiScope); | 312 scopes.insert(kApiScope); |
321 oauth_request_ = token_service_->StartRequest( | 313 oauth_request_ = token_service_->StartRequest( |
322 signin_manager_->GetAuthenticatedAccountId(), scopes, this); | 314 signin_manager_->GetAuthenticatedAccountId(), scopes, this); |
323 } | 315 } |
324 | 316 |
325 //////////////////////////////////////////////////////////////////////////////// | 317 //////////////////////////////////////////////////////////////////////////////// |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
433 tick_clock_->NowTicks() - fetch_start_time_); | 425 tick_clock_->NowTicks() - fetch_start_time_); |
434 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Snippets.FetchResult", | 426 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Snippets.FetchResult", |
435 static_cast<int>(result), | 427 static_cast<int>(result), |
436 static_cast<int>(FetchResult::RESULT_MAX)); | 428 static_cast<int>(FetchResult::RESULT_MAX)); |
437 | 429 |
438 if (!snippets_available_callback_.is_null()) | 430 if (!snippets_available_callback_.is_null()) |
439 snippets_available_callback_.Run(std::move(snippets)); | 431 snippets_available_callback_.Run(std::move(snippets)); |
440 } | 432 } |
441 | 433 |
442 } // namespace ntp_snippets | 434 } // namespace ntp_snippets |
OLD | NEW |