| 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/remote/ntp_snippets_fetcher.h" | 5 #include "components/ntp_snippets/remote/ntp_snippets_fetcher.h" |
| 6 | 6 |
| 7 #include <cstdlib> | 7 #include <cstdlib> |
| 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 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 130 return true; | 130 return true; |
| 131 } | 131 } |
| 132 | 132 |
| 133 // Creates snippets from dictionary values in |list| and adds them to | 133 // Creates snippets from dictionary values in |list| and adds them to |
| 134 // |snippets|. Returns true on success, false if anything went wrong. | 134 // |snippets|. Returns true on success, false if anything went wrong. |
| 135 bool AddSnippetsFromListValue(bool content_suggestions_api, | 135 bool AddSnippetsFromListValue(bool content_suggestions_api, |
| 136 const base::ListValue& list, | 136 const base::ListValue& list, |
| 137 NTPSnippet::PtrVector* snippets) { | 137 NTPSnippet::PtrVector* snippets) { |
| 138 for (const auto& value : list) { | 138 for (const auto& value : list) { |
| 139 const base::DictionaryValue* dict = nullptr; | 139 const base::DictionaryValue* dict = nullptr; |
| 140 if (!value->GetAsDictionary(&dict)) | 140 if (!value->GetAsDictionary(&dict)) { |
| 141 return false; | 141 return false; |
| 142 } |
| 142 | 143 |
| 143 std::unique_ptr<NTPSnippet> snippet; | 144 std::unique_ptr<NTPSnippet> snippet; |
| 144 if (content_suggestions_api) { | 145 if (content_suggestions_api) { |
| 145 snippet = NTPSnippet::CreateFromContentSuggestionsDictionary(*dict); | 146 snippet = NTPSnippet::CreateFromContentSuggestionsDictionary(*dict); |
| 146 } else { | 147 } else { |
| 147 snippet = NTPSnippet::CreateFromChromeReaderDictionary(*dict); | 148 snippet = NTPSnippet::CreateFromChromeReaderDictionary(*dict); |
| 148 } | 149 } |
| 149 if (!snippet) | 150 if (!snippet) { |
| 150 return false; | 151 return false; |
| 152 } |
| 151 | 153 |
| 152 snippets->push_back(std::move(snippet)); | 154 snippets->push_back(std::move(snippet)); |
| 153 } | 155 } |
| 154 return true; | 156 return true; |
| 155 } | 157 } |
| 156 | 158 |
| 157 // Translate the BCP 47 |language_code| into a posix locale string. | 159 // Translate the BCP 47 |language_code| into a posix locale string. |
| 158 std::string PosixLocaleFromBCP47Language(const std::string& language_code) { | 160 std::string PosixLocaleFromBCP47Language(const std::string& language_code) { |
| 159 char locale[ULOC_FULLNAME_CAPACITY]; | 161 char locale[ULOC_FULLNAME_CAPACITY]; |
| 160 UErrorCode error = U_ZERO_ERROR; | 162 UErrorCode error = U_ZERO_ERROR; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 snippets_available_callback_ = callback; | 233 snippets_available_callback_ = callback; |
| 232 } | 234 } |
| 233 | 235 |
| 234 void NTPSnippetsFetcher::FetchSnippetsFromHosts( | 236 void NTPSnippetsFetcher::FetchSnippetsFromHosts( |
| 235 const std::set<std::string>& hosts, | 237 const std::set<std::string>& hosts, |
| 236 const std::string& language_code, | 238 const std::string& language_code, |
| 237 const std::set<std::string>& excluded_ids, | 239 const std::set<std::string>& excluded_ids, |
| 238 int count, | 240 int count, |
| 239 bool interactive_request) { | 241 bool interactive_request) { |
| 240 if (!request_throttler_.DemandQuotaForRequest(interactive_request)) { | 242 if (!request_throttler_.DemandQuotaForRequest(interactive_request)) { |
| 241 FetchFinished(OptionalSnippets(), | 243 FetchFinished(OptionalFetchedCategories(), |
| 242 interactive_request | 244 interactive_request |
| 243 ? FetchResult::INTERACTIVE_QUOTA_ERROR | 245 ? FetchResult::INTERACTIVE_QUOTA_ERROR |
| 244 : FetchResult::NON_INTERACTIVE_QUOTA_ERROR, | 246 : FetchResult::NON_INTERACTIVE_QUOTA_ERROR, |
| 245 /*extra_message=*/std::string()); | 247 /*extra_message=*/std::string()); |
| 246 return; | 248 return; |
| 247 } | 249 } |
| 248 | 250 |
| 249 hosts_ = hosts; | 251 hosts_ = hosts; |
| 250 fetch_start_time_ = tick_clock_->NowTicks(); | 252 fetch_start_time_ = tick_clock_->NowTicks(); |
| 251 excluded_ids_ = excluded_ids; | 253 excluded_ids_ = excluded_ids; |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 477 error.state() == GoogleServiceAuthError::State::REQUEST_CANCELED) { | 479 error.state() == GoogleServiceAuthError::State::REQUEST_CANCELED) { |
| 478 // The request (especially on startup) can get reset by loading the refresh | 480 // The request (especially on startup) can get reset by loading the refresh |
| 479 // token - do it one more time. | 481 // token - do it one more time. |
| 480 oauth_token_retried_ = true; | 482 oauth_token_retried_ = true; |
| 481 StartTokenRequest(); | 483 StartTokenRequest(); |
| 482 return; | 484 return; |
| 483 } | 485 } |
| 484 | 486 |
| 485 DLOG(ERROR) << "Unable to get token: " << error.ToString(); | 487 DLOG(ERROR) << "Unable to get token: " << error.ToString(); |
| 486 FetchFinished( | 488 FetchFinished( |
| 487 OptionalSnippets(), FetchResult::OAUTH_TOKEN_ERROR, | 489 OptionalFetchedCategories(), FetchResult::OAUTH_TOKEN_ERROR, |
| 488 /*extra_message=*/base::StringPrintf(" (%s)", error.ToString().c_str())); | 490 /*extra_message=*/base::StringPrintf(" (%s)", error.ToString().c_str())); |
| 489 } | 491 } |
| 490 | 492 |
| 491 //////////////////////////////////////////////////////////////////////////////// | 493 //////////////////////////////////////////////////////////////////////////////// |
| 492 // OAuth2TokenService::Observer overrides | 494 // OAuth2TokenService::Observer overrides |
| 493 void NTPSnippetsFetcher::OnRefreshTokenAvailable( | 495 void NTPSnippetsFetcher::OnRefreshTokenAvailable( |
| 494 const std::string& account_id) { | 496 const std::string& account_id) { |
| 495 // Only react on tokens for the account the user has signed in with. | 497 // Only react on tokens for the account the user has signed in with. |
| 496 if (account_id != signin_manager_->GetAuthenticatedAccountId()) | 498 if (account_id != signin_manager_->GetAuthenticatedAccountId()) |
| 497 return; | 499 return; |
| 498 | 500 |
| 499 token_service_->RemoveObserver(this); | 501 token_service_->RemoveObserver(this); |
| 500 waiting_for_refresh_token_ = false; | 502 waiting_for_refresh_token_ = false; |
| 501 oauth_token_retried_ = false; | 503 oauth_token_retried_ = false; |
| 502 StartTokenRequest(); | 504 StartTokenRequest(); |
| 503 } | 505 } |
| 504 | 506 |
| 505 //////////////////////////////////////////////////////////////////////////////// | 507 //////////////////////////////////////////////////////////////////////////////// |
| 506 // URLFetcherDelegate overrides | 508 // URLFetcherDelegate overrides |
| 507 void NTPSnippetsFetcher::OnURLFetchComplete(const URLFetcher* source) { | 509 void NTPSnippetsFetcher::OnURLFetchComplete(const URLFetcher* source) { |
| 508 DCHECK_EQ(url_fetcher_.get(), source); | 510 DCHECK_EQ(url_fetcher_.get(), source); |
| 509 | 511 |
| 510 const URLRequestStatus& status = source->GetStatus(); | 512 const URLRequestStatus& status = source->GetStatus(); |
| 511 | 513 |
| 512 UMA_HISTOGRAM_SPARSE_SLOWLY( | 514 UMA_HISTOGRAM_SPARSE_SLOWLY( |
| 513 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode", | 515 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode", |
| 514 status.is_success() ? source->GetResponseCode() : status.error()); | 516 status.is_success() ? source->GetResponseCode() : status.error()); |
| 515 | 517 |
| 516 if (!status.is_success()) { | 518 if (!status.is_success()) { |
| 517 FetchFinished(OptionalSnippets(), FetchResult::URL_REQUEST_STATUS_ERROR, | 519 FetchFinished(OptionalFetchedCategories(), |
| 520 FetchResult::URL_REQUEST_STATUS_ERROR, |
| 518 /*extra_message=*/base::StringPrintf(" %d", status.error())); | 521 /*extra_message=*/base::StringPrintf(" %d", status.error())); |
| 519 } else if (source->GetResponseCode() != net::HTTP_OK) { | 522 } else if (source->GetResponseCode() != net::HTTP_OK) { |
| 520 // TODO(jkrcal): https://crbug.com/609084 | 523 // TODO(jkrcal): https://crbug.com/609084 |
| 521 // We need to deal with the edge case again where the auth | 524 // We need to deal with the edge case again where the auth |
| 522 // token expires just before we send the request (in which case we need to | 525 // token expires just before we send the request (in which case we need to |
| 523 // fetch a new auth token). We should extract that into a common class | 526 // fetch a new auth token). We should extract that into a common class |
| 524 // instead of adding it to every single class that uses auth tokens. | 527 // instead of adding it to every single class that uses auth tokens. |
| 525 FetchFinished( | 528 FetchFinished( |
| 526 OptionalSnippets(), FetchResult::HTTP_ERROR, | 529 OptionalFetchedCategories(), FetchResult::HTTP_ERROR, |
| 527 /*extra_message=*/base::StringPrintf(" %d", source->GetResponseCode())); | 530 /*extra_message=*/base::StringPrintf(" %d", source->GetResponseCode())); |
| 528 } else { | 531 } else { |
| 529 bool stores_result_to_string = | 532 bool stores_result_to_string = |
| 530 source->GetResponseAsString(&last_fetch_json_); | 533 source->GetResponseAsString(&last_fetch_json_); |
| 531 DCHECK(stores_result_to_string); | 534 DCHECK(stores_result_to_string); |
| 532 | 535 |
| 533 parse_json_callback_.Run(last_fetch_json_, | 536 parse_json_callback_.Run(last_fetch_json_, |
| 534 base::Bind(&NTPSnippetsFetcher::OnJsonParsed, | 537 base::Bind(&NTPSnippetsFetcher::OnJsonParsed, |
| 535 weak_ptr_factory_.GetWeakPtr()), | 538 weak_ptr_factory_.GetWeakPtr()), |
| 536 base::Bind(&NTPSnippetsFetcher::OnJsonError, | 539 base::Bind(&NTPSnippetsFetcher::OnJsonError, |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 591 return true; | 594 return true; |
| 592 } | 595 } |
| 593 } | 596 } |
| 594 NOTREACHED(); | 597 NOTREACHED(); |
| 595 return false; | 598 return false; |
| 596 } | 599 } |
| 597 | 600 |
| 598 void NTPSnippetsFetcher::OnJsonParsed(std::unique_ptr<base::Value> parsed) { | 601 void NTPSnippetsFetcher::OnJsonParsed(std::unique_ptr<base::Value> parsed) { |
| 599 FetchedCategoriesVector categories; | 602 FetchedCategoriesVector categories; |
| 600 if (JsonToSnippets(*parsed, &categories)) { | 603 if (JsonToSnippets(*parsed, &categories)) { |
| 601 FetchFinished(OptionalSnippets(std::move(categories)), FetchResult::SUCCESS, | 604 FetchFinished(OptionalFetchedCategories(std::move(categories)), |
| 605 FetchResult::SUCCESS, |
| 602 /*extra_message=*/std::string()); | 606 /*extra_message=*/std::string()); |
| 603 } else { | 607 } else { |
| 604 LOG(WARNING) << "Received invalid snippets: " << last_fetch_json_; | 608 LOG(WARNING) << "Received invalid snippets: " << last_fetch_json_; |
| 605 FetchFinished(OptionalSnippets(), | 609 FetchFinished(OptionalFetchedCategories(), |
| 606 FetchResult::INVALID_SNIPPET_CONTENT_ERROR, | 610 FetchResult::INVALID_SNIPPET_CONTENT_ERROR, |
| 607 /*extra_message=*/std::string()); | 611 /*extra_message=*/std::string()); |
| 608 } | 612 } |
| 609 } | 613 } |
| 610 | 614 |
| 611 void NTPSnippetsFetcher::OnJsonError(const std::string& error) { | 615 void NTPSnippetsFetcher::OnJsonError(const std::string& error) { |
| 612 LOG(WARNING) << "Received invalid JSON (" << error | 616 LOG(WARNING) << "Received invalid JSON (" << error |
| 613 << "): " << last_fetch_json_; | 617 << "): " << last_fetch_json_; |
| 614 FetchFinished( | 618 FetchFinished( |
| 615 OptionalSnippets(), FetchResult::JSON_PARSE_ERROR, | 619 OptionalFetchedCategories(), FetchResult::JSON_PARSE_ERROR, |
| 616 /*extra_message=*/base::StringPrintf(" (error %s)", error.c_str())); | 620 /*extra_message=*/base::StringPrintf(" (error %s)", error.c_str())); |
| 617 } | 621 } |
| 618 | 622 |
| 619 void NTPSnippetsFetcher::FetchFinished(OptionalSnippets snippets, | 623 void NTPSnippetsFetcher::FetchFinished( |
| 620 FetchResult result, | 624 OptionalFetchedCategories fetched_categories, |
| 621 const std::string& extra_message) { | 625 FetchResult result, |
| 622 DCHECK(result == FetchResult::SUCCESS || !snippets); | 626 const std::string& extra_message) { |
| 627 DCHECK(result == FetchResult::SUCCESS || !fetched_categories); |
| 623 last_status_ = FetchResultToString(result) + extra_message; | 628 last_status_ = FetchResultToString(result) + extra_message; |
| 624 | 629 |
| 625 // Don't record FetchTimes if the result indicates that a precondition | 630 // Don't record FetchTimes if the result indicates that a precondition |
| 626 // failed and we never actually sent a network request | 631 // failed and we never actually sent a network request |
| 627 if (!IsFetchPreconditionFailed(result)) { | 632 if (!IsFetchPreconditionFailed(result)) { |
| 628 UMA_HISTOGRAM_TIMES("NewTabPage.Snippets.FetchTime", | 633 UMA_HISTOGRAM_TIMES("NewTabPage.Snippets.FetchTime", |
| 629 tick_clock_->NowTicks() - fetch_start_time_); | 634 tick_clock_->NowTicks() - fetch_start_time_); |
| 630 } | 635 } |
| 631 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Snippets.FetchResult", | 636 UMA_HISTOGRAM_ENUMERATION("NewTabPage.Snippets.FetchResult", |
| 632 static_cast<int>(result), | 637 static_cast<int>(result), |
| 633 static_cast<int>(FetchResult::RESULT_MAX)); | 638 static_cast<int>(FetchResult::RESULT_MAX)); |
| 634 | 639 |
| 635 DVLOG(1) << "Fetch finished: " << last_status_; | 640 DVLOG(1) << "Fetch finished: " << last_status_; |
| 636 if (!snippets_available_callback_.is_null()) | 641 if (!snippets_available_callback_.is_null()) |
| 637 snippets_available_callback_.Run(std::move(snippets)); | 642 snippets_available_callback_.Run(std::move(fetched_categories)); |
| 638 } | 643 } |
| 639 | 644 |
| 640 } // namespace ntp_snippets | 645 } // namespace ntp_snippets |
| OLD | NEW |