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" |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
99 return endpoint.empty() ? kChromeReaderServer : endpoint; | 99 return endpoint.empty() ? kChromeReaderServer : endpoint; |
100 } | 100 } |
101 | 101 |
102 bool UsesChromeContentSuggestionsAPI(const GURL& endpoint) { | 102 bool UsesChromeContentSuggestionsAPI(const GURL& endpoint) { |
103 if (endpoint == GURL(kChromeReaderServer)) { | 103 if (endpoint == GURL(kChromeReaderServer)) { |
104 return false; | 104 return false; |
105 } else if (endpoint != GURL(kContentSuggestionsServer) && | 105 } else if (endpoint != GURL(kContentSuggestionsServer) && |
106 endpoint != GURL(kContentSuggestionsDevServer) && | 106 endpoint != GURL(kContentSuggestionsDevServer) && |
107 endpoint != GURL(kContentSuggestionsAlphaServer)) { | 107 endpoint != GURL(kContentSuggestionsAlphaServer)) { |
108 LOG(WARNING) << "Unknown value for " << kContentSuggestionsBackend << ": " | 108 LOG(WARNING) << "Unknown value for " << kContentSuggestionsBackend << ": " |
109 << "assuming chromecontentsuggestions-style API"; | 109 << "assuming chromecontentsuggestions-style API"; |
110 } | 110 } |
111 return true; | 111 return true; |
112 } | 112 } |
113 | 113 |
114 // Creates snippets from dictionary values in |list| and adds them to | 114 // Creates snippets from dictionary values in |list| and adds them to |
115 // |snippets|. Returns true on success, false if anything went wrong. | 115 // |snippets|. Returns true on success, false if anything went wrong. |
116 bool AddSnippetsFromListValue(bool content_suggestions_api, | 116 bool AddSnippetsFromListValue(bool content_suggestions_api, |
117 const base::ListValue& list, | 117 const base::ListValue& list, |
118 NTPSnippet::PtrVector* snippets) { | 118 NTPSnippet::PtrVector* snippets) { |
119 for (const auto& value : list) { | 119 for (const auto& value : list) { |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
162 token_service_(token_service), | 162 token_service_(token_service), |
163 waiting_for_refresh_token_(false), | 163 waiting_for_refresh_token_(false), |
164 url_request_context_getter_(url_request_context_getter), | 164 url_request_context_getter_(url_request_context_getter), |
165 category_factory_(category_factory), | 165 category_factory_(category_factory), |
166 parse_json_callback_(parse_json_callback), | 166 parse_json_callback_(parse_json_callback), |
167 fetch_url_(GetFetchEndpoint()), | 167 fetch_url_(GetFetchEndpoint()), |
168 fetch_api_(UsesChromeContentSuggestionsAPI(fetch_url_) | 168 fetch_api_(UsesChromeContentSuggestionsAPI(fetch_url_) |
169 ? CHROME_CONTENT_SUGGESTIONS_API | 169 ? CHROME_CONTENT_SUGGESTIONS_API |
170 : CHROME_READER_API), | 170 : CHROME_READER_API), |
171 is_stable_channel_(is_stable_channel), | 171 is_stable_channel_(is_stable_channel), |
172 interactive_request_(false), | |
172 tick_clock_(new base::DefaultTickClock()), | 173 tick_clock_(new base::DefaultTickClock()), |
173 request_throttler_( | 174 request_throttler_( |
174 pref_service, | 175 pref_service, |
175 RequestThrottler::RequestType::CONTENT_SUGGESTION_FETCHER), | 176 RequestThrottler::RequestType::CONTENT_SUGGESTION_FETCHER), |
176 oauth_token_retried_(false), | 177 oauth_token_retried_(false), |
177 weak_ptr_factory_(this) { | 178 weak_ptr_factory_(this) { |
178 // Parse the variation parameters and set the defaults if missing. | 179 // Parse the variation parameters and set the defaults if missing. |
179 std::string personalization = variations::GetVariationParamValue( | 180 std::string personalization = variations::GetVariationParamValue( |
180 ntp_snippets::kStudyName, kPersonalizationName); | 181 ntp_snippets::kStudyName, kPersonalizationName); |
181 if (personalization == kPersonalizationNonPersonalString) { | 182 if (personalization == kPersonalizationNonPersonalString) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
227 if (UsesHostRestrictions() && hosts_.empty()) { | 228 if (UsesHostRestrictions() && hosts_.empty()) { |
228 FetchFinished(OptionalSnippets(), FetchResult::EMPTY_HOSTS, | 229 FetchFinished(OptionalSnippets(), FetchResult::EMPTY_HOSTS, |
229 /*extra_message=*/std::string()); | 230 /*extra_message=*/std::string()); |
230 return; | 231 return; |
231 } | 232 } |
232 | 233 |
233 locale_ = PosixLocaleFromBCP47Language(language_code); | 234 locale_ = PosixLocaleFromBCP47Language(language_code); |
234 count_to_fetch_ = count; | 235 count_to_fetch_ = count; |
235 | 236 |
236 bool use_authentication = UsesAuthentication(); | 237 bool use_authentication = UsesAuthentication(); |
238 interactive_request_ = interactive_request; | |
237 | 239 |
238 if (use_authentication && signin_manager_->IsAuthenticated()) { | 240 if (use_authentication && signin_manager_->IsAuthenticated()) { |
239 // Signed-in: get OAuth token --> fetch snippets. | 241 // Signed-in: get OAuth token --> fetch snippets. |
240 oauth_token_retried_ = false; | 242 oauth_token_retried_ = false; |
241 StartTokenRequest(); | 243 StartTokenRequest(); |
242 } else if (use_authentication && signin_manager_->AuthInProgress()) { | 244 } else if (use_authentication && signin_manager_->AuthInProgress()) { |
243 // Currently signing in: wait for auth to finish (the refresh token) --> | 245 // Currently signing in: wait for auth to finish (the refresh token) --> |
244 // get OAuth token --> fetch snippets. | 246 // get OAuth token --> fetch snippets. |
245 if (!waiting_for_refresh_token_) { | 247 if (!waiting_for_refresh_token_) { |
246 // Wait until we get a refresh token. | 248 // Wait until we get a refresh token. |
247 waiting_for_refresh_token_ = true; | 249 waiting_for_refresh_token_ = true; |
248 token_service_->AddObserver(this); | 250 token_service_->AddObserver(this); |
249 } | 251 } |
250 } else { | 252 } else { |
251 // Not signed in: fetch snippets (without authentication). | 253 // Not signed in: fetch snippets (without authentication). |
252 FetchSnippetsNonAuthenticated(); | 254 FetchSnippetsNonAuthenticated(); |
253 } | 255 } |
254 } | 256 } |
255 | 257 |
256 NTPSnippetsFetcher::RequestParams::RequestParams() | 258 NTPSnippetsFetcher::RequestParams::RequestParams() |
257 : fetch_api(), | 259 : fetch_api(), |
258 obfuscated_gaia_id(), | 260 obfuscated_gaia_id(), |
259 only_return_personalized_results(), | 261 only_return_personalized_results(), |
260 user_locale(), | 262 user_locale(), |
261 host_restricts(), | 263 host_restricts(), |
262 count_to_fetch() {} | 264 count_to_fetch() {} |
Marc Treib
2016/08/25 09:26:58
Also initialize interactive_request here
vitaliii
2016/08/26 09:13:46
Done.
| |
263 | 265 |
264 NTPSnippetsFetcher::RequestParams::~RequestParams() = default; | 266 NTPSnippetsFetcher::RequestParams::~RequestParams() = default; |
265 | 267 |
266 std::string NTPSnippetsFetcher::RequestParams::BuildRequest() { | 268 std::string NTPSnippetsFetcher::RequestParams::BuildRequest() { |
267 auto request = base::MakeUnique<base::DictionaryValue>(); | 269 auto request = base::MakeUnique<base::DictionaryValue>(); |
268 switch (fetch_api) { | 270 switch (fetch_api) { |
269 case CHROME_READER_API: { | 271 case CHROME_READER_API: { |
270 auto content_params = base::MakeUnique<base::DictionaryValue>(); | 272 auto content_params = base::MakeUnique<base::DictionaryValue>(); |
271 content_params->SetBoolean("only_return_personalized_results", | 273 content_params->SetBoolean("only_return_personalized_results", |
272 only_return_personalized_results); | 274 only_return_personalized_results); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
315 | 317 |
316 case CHROME_CONTENT_SUGGESTIONS_API: { | 318 case CHROME_CONTENT_SUGGESTIONS_API: { |
317 if (!user_locale.empty()) { | 319 if (!user_locale.empty()) { |
318 request->SetString("uiLanguage", user_locale); | 320 request->SetString("uiLanguage", user_locale); |
319 } | 321 } |
320 auto regular_hosts = base::MakeUnique<base::ListValue>(); | 322 auto regular_hosts = base::MakeUnique<base::ListValue>(); |
321 for (const auto& host : host_restricts) { | 323 for (const auto& host : host_restricts) { |
322 regular_hosts->AppendString(host); | 324 regular_hosts->AppendString(host); |
323 } | 325 } |
324 request->Set("regularlyVisitedHostNames", std::move(regular_hosts)); | 326 request->Set("regularlyVisitedHostNames", std::move(regular_hosts)); |
327 request->SetString("type", | |
328 interactive_request ? "INTERACTIVE" : "BACKGROUND"); | |
325 | 329 |
326 // TODO(sfiera): support authentication and personalization | 330 // TODO(sfiera): support authentication and personalization |
327 // TODO(sfiera): support count_to_fetch | 331 // TODO(sfiera): support count_to_fetch |
328 break; | 332 break; |
329 } | 333 } |
330 } | 334 } |
331 | 335 |
332 std::string request_json; | 336 std::string request_json; |
333 bool success = base::JSONWriter::WriteWithOptions( | 337 bool success = base::JSONWriter::WriteWithOptions( |
334 *request, base::JSONWriter::OPTIONS_PRETTY_PRINT, &request_json); | 338 *request, base::JSONWriter::OPTIONS_PRETTY_PRINT, &request_json); |
(...skipping 19 matching lines...) Expand all Loading... | |
354 headers.SetHeader("Content-Type", "application/json; charset=UTF-8"); | 358 headers.SetHeader("Content-Type", "application/json; charset=UTF-8"); |
355 // Add X-Client-Data header with experiment IDs from field trials. | 359 // Add X-Client-Data header with experiment IDs from field trials. |
356 variations::AppendVariationHeaders(url, | 360 variations::AppendVariationHeaders(url, |
357 false, // incognito | 361 false, // incognito |
358 false, // uma_enabled | 362 false, // uma_enabled |
359 &headers); | 363 &headers); |
360 url_fetcher_->SetExtraRequestHeaders(headers.ToString()); | 364 url_fetcher_->SetExtraRequestHeaders(headers.ToString()); |
361 url_fetcher_->SetUploadData("application/json", request); | 365 url_fetcher_->SetUploadData("application/json", request); |
362 // Log the request for debugging network issues. | 366 // Log the request for debugging network issues. |
363 VLOG(1) << "Sending a NTP snippets request to " << url << ":" << std::endl | 367 VLOG(1) << "Sending a NTP snippets request to " << url << ":" << std::endl |
364 << headers.ToString() << std::endl << request; | 368 << headers.ToString() << std::endl |
369 << request; | |
365 // Fetchers are sometimes cancelled because a network change was detected. | 370 // Fetchers are sometimes cancelled because a network change was detected. |
366 url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); | 371 url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); |
367 // Try to make fetching the files bit more robust even with poor connection. | 372 // Try to make fetching the files bit more robust even with poor connection. |
368 url_fetcher_->SetMaxRetriesOn5xx(3); | 373 url_fetcher_->SetMaxRetriesOn5xx(3); |
369 url_fetcher_->Start(); | 374 url_fetcher_->Start(); |
370 } | 375 } |
371 | 376 |
372 bool NTPSnippetsFetcher::UsesHostRestrictions() const { | 377 bool NTPSnippetsFetcher::UsesHostRestrictions() const { |
373 return use_host_restriction_ && | 378 return use_host_restriction_ && |
374 !base::CommandLine::ForCurrentProcess()->HasSwitch( | 379 !base::CommandLine::ForCurrentProcess()->HasSwitch( |
(...skipping 11 matching lines...) Expand all Loading... | |
386 ? google_apis::GetAPIKey() | 391 ? google_apis::GetAPIKey() |
387 : google_apis::GetNonStableAPIKey(); | 392 : google_apis::GetNonStableAPIKey(); |
388 GURL url(base::StringPrintf(kSnippetsServerNonAuthorizedFormat, | 393 GURL url(base::StringPrintf(kSnippetsServerNonAuthorizedFormat, |
389 fetch_url_.spec().c_str(), key.c_str())); | 394 fetch_url_.spec().c_str(), key.c_str())); |
390 | 395 |
391 RequestParams params; | 396 RequestParams params; |
392 params.fetch_api = fetch_api_; | 397 params.fetch_api = fetch_api_; |
393 params.host_restricts = | 398 params.host_restricts = |
394 UsesHostRestrictions() ? hosts_ : std::set<std::string>(); | 399 UsesHostRestrictions() ? hosts_ : std::set<std::string>(); |
395 params.count_to_fetch = count_to_fetch_; | 400 params.count_to_fetch = count_to_fetch_; |
401 params.interactive_request = interactive_request_; | |
396 FetchSnippetsImpl(url, std::string(), params.BuildRequest()); | 402 FetchSnippetsImpl(url, std::string(), params.BuildRequest()); |
397 } | 403 } |
398 | 404 |
399 void NTPSnippetsFetcher::FetchSnippetsAuthenticated( | 405 void NTPSnippetsFetcher::FetchSnippetsAuthenticated( |
400 const std::string& account_id, | 406 const std::string& account_id, |
401 const std::string& oauth_access_token) { | 407 const std::string& oauth_access_token) { |
402 RequestParams params; | 408 RequestParams params; |
403 params.fetch_api = fetch_api_; | 409 params.fetch_api = fetch_api_; |
404 params.obfuscated_gaia_id = account_id; | 410 params.obfuscated_gaia_id = account_id; |
405 params.only_return_personalized_results = | 411 params.only_return_personalized_results = |
406 personalization_ == Personalization::kPersonal; | 412 personalization_ == Personalization::kPersonal; |
407 params.user_locale = locale_; | 413 params.user_locale = locale_; |
408 params.host_restricts = | 414 params.host_restricts = |
409 UsesHostRestrictions() ? hosts_ : std::set<std::string>(); | 415 UsesHostRestrictions() ? hosts_ : std::set<std::string>(); |
410 params.count_to_fetch = count_to_fetch_; | 416 params.count_to_fetch = count_to_fetch_; |
417 params.interactive_request = interactive_request_; | |
411 // TODO(jkrcal, treib): Add unit-tests for authenticated fetches. | 418 // TODO(jkrcal, treib): Add unit-tests for authenticated fetches. |
412 FetchSnippetsImpl(fetch_url_, | 419 FetchSnippetsImpl(fetch_url_, |
413 base::StringPrintf(kAuthorizationRequestHeaderFormat, | 420 base::StringPrintf(kAuthorizationRequestHeaderFormat, |
414 oauth_access_token.c_str()), | 421 oauth_access_token.c_str()), |
415 params.BuildRequest()); | 422 params.BuildRequest()); |
416 } | 423 } |
417 | 424 |
418 void NTPSnippetsFetcher::StartTokenRequest() { | 425 void NTPSnippetsFetcher::StartTokenRequest() { |
419 OAuth2TokenService::ScopeSet scopes; | 426 OAuth2TokenService::ScopeSet scopes; |
420 scopes.insert(fetch_api_ == CHROME_CONTENT_SUGGESTIONS_API | 427 scopes.insert(fetch_api_ == CHROME_CONTENT_SUGGESTIONS_API |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
490 } else if (source->GetResponseCode() != net::HTTP_OK) { | 497 } else if (source->GetResponseCode() != net::HTTP_OK) { |
491 // TODO(jkrcal): https://crbug.com/609084 | 498 // TODO(jkrcal): https://crbug.com/609084 |
492 // We need to deal with the edge case again where the auth | 499 // We need to deal with the edge case again where the auth |
493 // token expires just before we send the request (in which case we need to | 500 // token expires just before we send the request (in which case we need to |
494 // fetch a new auth token). We should extract that into a common class | 501 // fetch a new auth token). We should extract that into a common class |
495 // instead of adding it to every single class that uses auth tokens. | 502 // instead of adding it to every single class that uses auth tokens. |
496 FetchFinished( | 503 FetchFinished( |
497 OptionalSnippets(), FetchResult::HTTP_ERROR, | 504 OptionalSnippets(), FetchResult::HTTP_ERROR, |
498 /*extra_message=*/base::StringPrintf(" %d", source->GetResponseCode())); | 505 /*extra_message=*/base::StringPrintf(" %d", source->GetResponseCode())); |
499 } else { | 506 } else { |
500 bool stores_result_to_string = source->GetResponseAsString( | 507 bool stores_result_to_string = |
501 &last_fetch_json_); | 508 source->GetResponseAsString(&last_fetch_json_); |
502 DCHECK(stores_result_to_string); | 509 DCHECK(stores_result_to_string); |
503 | 510 |
504 parse_json_callback_.Run( | 511 parse_json_callback_.Run(last_fetch_json_, |
505 last_fetch_json_, | 512 base::Bind(&NTPSnippetsFetcher::OnJsonParsed, |
506 base::Bind(&NTPSnippetsFetcher::OnJsonParsed, | 513 weak_ptr_factory_.GetWeakPtr()), |
507 weak_ptr_factory_.GetWeakPtr()), | 514 base::Bind(&NTPSnippetsFetcher::OnJsonError, |
508 base::Bind(&NTPSnippetsFetcher::OnJsonError, | 515 weak_ptr_factory_.GetWeakPtr())); |
509 weak_ptr_factory_.GetWeakPtr())); | |
510 } | 516 } |
511 } | 517 } |
512 | 518 |
513 bool NTPSnippetsFetcher::JsonToSnippets(const base::Value& parsed, | 519 bool NTPSnippetsFetcher::JsonToSnippets(const base::Value& parsed, |
514 NTPSnippet::CategoryMap* snippets) { | 520 NTPSnippet::CategoryMap* snippets) { |
515 const base::DictionaryValue* top_dict = nullptr; | 521 const base::DictionaryValue* top_dict = nullptr; |
516 if (!parsed.GetAsDictionary(&top_dict)) { | 522 if (!parsed.GetAsDictionary(&top_dict)) { |
517 return false; | 523 return false; |
518 } | 524 } |
519 | 525 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
565 /*extra_message=*/std::string()); | 571 /*extra_message=*/std::string()); |
566 } else { | 572 } else { |
567 LOG(WARNING) << "Received invalid snippets: " << last_fetch_json_; | 573 LOG(WARNING) << "Received invalid snippets: " << last_fetch_json_; |
568 FetchFinished(OptionalSnippets(), | 574 FetchFinished(OptionalSnippets(), |
569 FetchResult::INVALID_SNIPPET_CONTENT_ERROR, | 575 FetchResult::INVALID_SNIPPET_CONTENT_ERROR, |
570 /*extra_message=*/std::string()); | 576 /*extra_message=*/std::string()); |
571 } | 577 } |
572 } | 578 } |
573 | 579 |
574 void NTPSnippetsFetcher::OnJsonError(const std::string& error) { | 580 void NTPSnippetsFetcher::OnJsonError(const std::string& error) { |
575 LOG(WARNING) << "Received invalid JSON (" << error << "): " | 581 LOG(WARNING) << "Received invalid JSON (" << error |
576 << last_fetch_json_; | 582 << "): " << last_fetch_json_; |
Marc Treib
2016/08/25 09:26:58
Was this auto-formatted?! (It's fine either way, I
vitaliii
2016/08/26 09:13:46
Yes.
Eclipse format happened to differ from git c
| |
577 FetchFinished( | 583 FetchFinished( |
578 OptionalSnippets(), FetchResult::JSON_PARSE_ERROR, | 584 OptionalSnippets(), FetchResult::JSON_PARSE_ERROR, |
579 /*extra_message=*/base::StringPrintf(" (error %s)", error.c_str())); | 585 /*extra_message=*/base::StringPrintf(" (error %s)", error.c_str())); |
580 } | 586 } |
581 | 587 |
582 void NTPSnippetsFetcher::FetchFinished(OptionalSnippets snippets, | 588 void NTPSnippetsFetcher::FetchFinished(OptionalSnippets snippets, |
583 FetchResult result, | 589 FetchResult result, |
584 const std::string& extra_message) { | 590 const std::string& extra_message) { |
585 DCHECK(result == FetchResult::SUCCESS || !snippets); | 591 DCHECK(result == FetchResult::SUCCESS || !snippets); |
586 last_status_ = FetchResultToString(result) + extra_message; | 592 last_status_ = FetchResultToString(result) + extra_message; |
587 | 593 |
588 // If the result is EMPTY_HOSTS or OAUTH_TOKEN_ERROR, we didn't actually send | 594 // If the result is EMPTY_HOSTS or OAUTH_TOKEN_ERROR, we didn't actually send |
589 // a network request, so don't record FetchTime in those cases. | 595 // a network request, so don't record FetchTime in those cases. |
590 if (result != FetchResult::EMPTY_HOSTS && | 596 if (result != FetchResult::EMPTY_HOSTS && |
591 result != FetchResult::OAUTH_TOKEN_ERROR) { | 597 result != FetchResult::OAUTH_TOKEN_ERROR) { |
592 UMA_HISTOGRAM_TIMES("NewTabPage.Snippets.FetchTime", | 598 UMA_HISTOGRAM_TIMES("NewTabPage.Snippets.FetchTime", |
593 tick_clock_->NowTicks() - fetch_start_time_); | 599 tick_clock_->NowTicks() - fetch_start_time_); |
594 } | 600 } |
595 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Snippets.FetchResult", | 601 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Snippets.FetchResult", |
596 static_cast<int>(result), | 602 static_cast<int>(result), |
597 static_cast<int>(FetchResult::RESULT_MAX)); | 603 static_cast<int>(FetchResult::RESULT_MAX)); |
598 | 604 |
599 if (!snippets_available_callback_.is_null()) | 605 if (!snippets_available_callback_.is_null()) |
600 snippets_available_callback_.Run(std::move(snippets)); | 606 snippets_available_callback_.Run(std::move(snippets)); |
601 } | 607 } |
602 | 608 |
603 } // namespace ntp_snippets | 609 } // namespace ntp_snippets |
OLD | NEW |