| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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/remote_suggestions_provider_impl.h" | 5 #include "components/ntp_snippets/remote/remote_suggestions_provider_impl.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <iterator> | 8 #include <iterator> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 238 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 suggestion_id.id_within_category(), url, | 249 suggestion_id.id_within_category(), url, |
| 250 base::Bind(&CachedImageFetcher::OnImageDecodingDone, | 250 base::Bind(&CachedImageFetcher::OnImageDecodingDone, |
| 251 base::Unretained(this), callback)); | 251 base::Unretained(this), callback)); |
| 252 } | 252 } |
| 253 | 253 |
| 254 RemoteSuggestionsProviderImpl::RemoteSuggestionsProviderImpl( | 254 RemoteSuggestionsProviderImpl::RemoteSuggestionsProviderImpl( |
| 255 Observer* observer, | 255 Observer* observer, |
| 256 PrefService* pref_service, | 256 PrefService* pref_service, |
| 257 const std::string& application_language_code, | 257 const std::string& application_language_code, |
| 258 CategoryRanker* category_ranker, | 258 CategoryRanker* category_ranker, |
| 259 RemoteSuggestionsScheduler* scheduler, |
| 259 std::unique_ptr<RemoteSuggestionsFetcher> suggestions_fetcher, | 260 std::unique_ptr<RemoteSuggestionsFetcher> suggestions_fetcher, |
| 260 std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher, | 261 std::unique_ptr<image_fetcher::ImageFetcher> image_fetcher, |
| 261 std::unique_ptr<RemoteSuggestionsDatabase> database, | 262 std::unique_ptr<RemoteSuggestionsDatabase> database, |
| 262 std::unique_ptr<RemoteSuggestionsStatusService> status_service) | 263 std::unique_ptr<RemoteSuggestionsStatusService> status_service) |
| 263 : RemoteSuggestionsProvider(observer), | 264 : RemoteSuggestionsProvider(observer), |
| 264 state_(State::NOT_INITED), | 265 state_(State::NOT_INITED), |
| 265 pref_service_(pref_service), | 266 pref_service_(pref_service), |
| 266 articles_category_( | 267 articles_category_( |
| 267 Category::FromKnownCategory(KnownCategories::ARTICLES)), | 268 Category::FromKnownCategory(KnownCategories::ARTICLES)), |
| 268 application_language_code_(application_language_code), | 269 application_language_code_(application_language_code), |
| 269 category_ranker_(category_ranker), | 270 category_ranker_(category_ranker), |
| 271 remote_suggestions_scheduler_(scheduler), |
| 270 suggestions_fetcher_(std::move(suggestions_fetcher)), | 272 suggestions_fetcher_(std::move(suggestions_fetcher)), |
| 271 database_(std::move(database)), | 273 database_(std::move(database)), |
| 272 image_fetcher_(std::move(image_fetcher), pref_service, database_.get()), | 274 image_fetcher_(std::move(image_fetcher), pref_service, database_.get()), |
| 273 status_service_(std::move(status_service)), | 275 status_service_(std::move(status_service)), |
| 274 fetch_when_ready_(false), | 276 fetch_when_ready_(false), |
| 275 fetch_when_ready_interactive_(false), | 277 fetch_when_ready_interactive_(false), |
| 276 fetch_when_ready_callback_(nullptr), | 278 fetch_when_ready_callback_(nullptr), |
| 277 remote_suggestions_scheduler_(nullptr), | |
| 278 clear_history_dependent_state_when_initialized_(false), | 279 clear_history_dependent_state_when_initialized_(false), |
| 279 clock_(base::MakeUnique<base::DefaultClock>()) { | 280 clock_(base::MakeUnique<base::DefaultClock>()) { |
| 280 RestoreCategoriesFromPrefs(); | 281 RestoreCategoriesFromPrefs(); |
| 281 // The articles category always exists. Add it if we didn't get it from prefs. | 282 // The articles category always exists. Add it if we didn't get it from prefs. |
| 282 // TODO(treib): Rethink this. | 283 // TODO(treib): Rethink this. |
| 283 category_contents_.insert( | 284 category_contents_.insert( |
| 284 std::make_pair(articles_category_, | 285 std::make_pair(articles_category_, |
| 285 CategoryContent(BuildArticleCategoryInfo(base::nullopt)))); | 286 CategoryContent(BuildArticleCategoryInfo(base::nullopt)))); |
| 286 // Tell the observer about all the categories. | 287 // Tell the observer about all the categories. |
| 287 for (const auto& entry : category_contents_) { | 288 for (const auto& entry : category_contents_) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 309 | 310 |
| 310 // static | 311 // static |
| 311 void RemoteSuggestionsProviderImpl::RegisterProfilePrefs( | 312 void RemoteSuggestionsProviderImpl::RegisterProfilePrefs( |
| 312 PrefRegistrySimple* registry) { | 313 PrefRegistrySimple* registry) { |
| 313 registry->RegisterListPref(prefs::kRemoteSuggestionCategories); | 314 registry->RegisterListPref(prefs::kRemoteSuggestionCategories); |
| 314 registry->RegisterInt64Pref(prefs::kLastSuccessfulBackgroundFetchTime, 0); | 315 registry->RegisterInt64Pref(prefs::kLastSuccessfulBackgroundFetchTime, 0); |
| 315 | 316 |
| 316 RemoteSuggestionsStatusService::RegisterProfilePrefs(registry); | 317 RemoteSuggestionsStatusService::RegisterProfilePrefs(registry); |
| 317 } | 318 } |
| 318 | 319 |
| 319 void RemoteSuggestionsProviderImpl::SetRemoteSuggestionsScheduler( | |
| 320 RemoteSuggestionsScheduler* scheduler) { | |
| 321 remote_suggestions_scheduler_ = scheduler; | |
| 322 // Call the observer right away if we've reached any final state. | |
| 323 NotifyStateChanged(); | |
| 324 } | |
| 325 | |
| 326 void RemoteSuggestionsProviderImpl::ReloadSuggestions() { | 320 void RemoteSuggestionsProviderImpl::ReloadSuggestions() { |
| 321 if (!remote_suggestions_scheduler_->AcquireQuotaForInteractiveFetch()) { |
| 322 return; |
| 323 } |
| 327 FetchSuggestions(/*interactive_request=*/true, | 324 FetchSuggestions(/*interactive_request=*/true, |
| 328 /*callback=*/nullptr); | 325 /*callback=*/nullptr); |
| 329 } | 326 } |
| 330 | 327 |
| 331 void RemoteSuggestionsProviderImpl::RefetchInTheBackground( | 328 void RemoteSuggestionsProviderImpl::RefetchInTheBackground( |
| 332 std::unique_ptr<FetchStatusCallback> callback) { | 329 std::unique_ptr<FetchStatusCallback> callback) { |
| 333 FetchSuggestions(/*interactive_request=*/false, std::move(callback)); | 330 FetchSuggestions(/*interactive_request=*/false, std::move(callback)); |
| 334 } | 331 } |
| 335 | 332 |
| 336 const RemoteSuggestionsFetcher* | 333 const RemoteSuggestionsFetcher* |
| (...skipping 24 matching lines...) Expand all Loading... |
| 361 void RemoteSuggestionsProviderImpl::Fetch( | 358 void RemoteSuggestionsProviderImpl::Fetch( |
| 362 const Category& category, | 359 const Category& category, |
| 363 const std::set<std::string>& known_suggestion_ids, | 360 const std::set<std::string>& known_suggestion_ids, |
| 364 const FetchDoneCallback& callback) { | 361 const FetchDoneCallback& callback) { |
| 365 if (!ready()) { | 362 if (!ready()) { |
| 366 CallWithEmptyResults(callback, | 363 CallWithEmptyResults(callback, |
| 367 Status(StatusCode::TEMPORARY_ERROR, | 364 Status(StatusCode::TEMPORARY_ERROR, |
| 368 "RemoteSuggestionsProvider is not ready!")); | 365 "RemoteSuggestionsProvider is not ready!")); |
| 369 return; | 366 return; |
| 370 } | 367 } |
| 368 if (!remote_suggestions_scheduler_->AcquireQuotaForInteractiveFetch()) { |
| 369 CallWithEmptyResults(callback, Status(StatusCode::TEMPORARY_ERROR, |
| 370 "Interactive quota exceeded!")); |
| 371 return; |
| 372 } |
| 371 RequestParams params = BuildFetchParams(); | 373 RequestParams params = BuildFetchParams(); |
| 372 params.excluded_ids.insert(known_suggestion_ids.begin(), | 374 params.excluded_ids.insert(known_suggestion_ids.begin(), |
| 373 known_suggestion_ids.end()); | 375 known_suggestion_ids.end()); |
| 374 params.interactive_request = true; | 376 params.interactive_request = true; |
| 375 params.exclusive_category = category; | 377 params.exclusive_category = category; |
| 376 | 378 |
| 377 suggestions_fetcher_->FetchSnippets( | 379 suggestions_fetcher_->FetchSnippets( |
| 378 params, | 380 params, |
| 379 base::BindOnce(&RemoteSuggestionsProviderImpl::OnFetchMoreFinished, | 381 base::BindOnce(&RemoteSuggestionsProviderImpl::OnFetchMoreFinished, |
| 380 base::Unretained(this), callback)); | 382 base::Unretained(this), callback)); |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 | 638 |
| 637 IntegrateSuggestions(existing_content, | 639 IntegrateSuggestions(existing_content, |
| 638 std::move(fetched_category.suggestions)); | 640 std::move(fetched_category.suggestions)); |
| 639 | 641 |
| 640 // TODO(tschumann): We should properly honor the existing category state, | 642 // TODO(tschumann): We should properly honor the existing category state, |
| 641 // e.g. to make sure we don't serve results after the sign-out. Revisit this: | 643 // e.g. to make sure we don't serve results after the sign-out. Revisit this: |
| 642 // Should Nuke also cancel outstanding requests, or do we want to check the | 644 // Should Nuke also cancel outstanding requests, or do we want to check the |
| 643 // status? | 645 // status? |
| 644 UpdateCategoryStatus(category, CategoryStatus::AVAILABLE); | 646 UpdateCategoryStatus(category, CategoryStatus::AVAILABLE); |
| 645 // Notify callers and observers. | 647 // Notify callers and observers. |
| 648 remote_suggestions_scheduler_->OnInteractiveFetchFinished(status); |
| 646 fetching_callback.Run(Status::Success(), std::move(result)); | 649 fetching_callback.Run(Status::Success(), std::move(result)); |
| 647 NotifyNewSuggestions(category, *existing_content); | 650 NotifyNewSuggestions(category, *existing_content); |
| 648 } | 651 } |
| 649 | 652 |
| 650 void RemoteSuggestionsProviderImpl::OnFetchFinished( | 653 void RemoteSuggestionsProviderImpl::OnFetchFinished( |
| 651 std::unique_ptr<FetchStatusCallback> callback, | 654 std::unique_ptr<FetchStatusCallback> callback, |
| 652 bool interactive_request, | 655 bool interactive_request, |
| 653 Status status, | 656 Status status, |
| 654 RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories) { | 657 RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories) { |
| 655 if (!ready()) { | 658 if (!ready()) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 720 auto content_it = category_contents_.find(articles_category_); | 723 auto content_it = category_contents_.find(articles_category_); |
| 721 DCHECK(content_it != category_contents_.end()); | 724 DCHECK(content_it != category_contents_.end()); |
| 722 const CategoryContent& content = content_it->second; | 725 const CategoryContent& content = content_it->second; |
| 723 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.Snippets.NumArticles", | 726 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.Snippets.NumArticles", |
| 724 content.suggestions.size()); | 727 content.suggestions.size()); |
| 725 if (content.suggestions.empty() && !content.dismissed.empty()) { | 728 if (content.suggestions.empty() && !content.dismissed.empty()) { |
| 726 UMA_HISTOGRAM_COUNTS("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded", | 729 UMA_HISTOGRAM_COUNTS("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded", |
| 727 content.dismissed.size()); | 730 content.dismissed.size()); |
| 728 } | 731 } |
| 729 | 732 |
| 733 if (interactive_request) { |
| 734 remote_suggestions_scheduler_->OnInteractiveFetchFinished(status); |
| 735 } |
| 736 |
| 730 if (callback) { | 737 if (callback) { |
| 731 callback->Run(status); | 738 callback->Run(status); |
| 732 } | 739 } |
| 733 } | 740 } |
| 734 | 741 |
| 735 void RemoteSuggestionsProviderImpl::ArchiveSuggestions( | 742 void RemoteSuggestionsProviderImpl::ArchiveSuggestions( |
| 736 CategoryContent* content, | 743 CategoryContent* content, |
| 737 RemoteSuggestion::PtrVector* to_archive) { | 744 RemoteSuggestion::PtrVector* to_archive) { |
| 738 // Archive previous suggestions - move them at the beginning of the list. | 745 // Archive previous suggestions - move them at the beginning of the list. |
| 739 content->archived.insert(content->archived.begin(), | 746 content->archived.insert(content->archived.begin(), |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 865 database_->GarbageCollectImages(std::move(alive_suggestions)); | 872 database_->GarbageCollectImages(std::move(alive_suggestions)); |
| 866 } | 873 } |
| 867 | 874 |
| 868 void RemoteSuggestionsProviderImpl::ClearHistoryDependentState() { | 875 void RemoteSuggestionsProviderImpl::ClearHistoryDependentState() { |
| 869 if (!initialized()) { | 876 if (!initialized()) { |
| 870 clear_history_dependent_state_when_initialized_ = true; | 877 clear_history_dependent_state_when_initialized_ = true; |
| 871 return; | 878 return; |
| 872 } | 879 } |
| 873 | 880 |
| 874 NukeAllSuggestions(); | 881 NukeAllSuggestions(); |
| 875 if (remote_suggestions_scheduler_) { | 882 remote_suggestions_scheduler_->OnHistoryCleared(); |
| 876 remote_suggestions_scheduler_->OnHistoryCleared(); | |
| 877 } | |
| 878 } | 883 } |
| 879 | 884 |
| 880 void RemoteSuggestionsProviderImpl::ClearSuggestions() { | 885 void RemoteSuggestionsProviderImpl::ClearSuggestions() { |
| 881 DCHECK(initialized()); | 886 DCHECK(initialized()); |
| 882 | 887 |
| 883 NukeAllSuggestions(); | 888 NukeAllSuggestions(); |
| 884 if (remote_suggestions_scheduler_) { | 889 remote_suggestions_scheduler_->OnSuggestionsCleared(); |
| 885 remote_suggestions_scheduler_->OnSuggestionsCleared(); | |
| 886 } | |
| 887 } | 890 } |
| 888 | 891 |
| 889 void RemoteSuggestionsProviderImpl::NukeAllSuggestions() { | 892 void RemoteSuggestionsProviderImpl::NukeAllSuggestions() { |
| 890 for (const auto& item : category_contents_) { | 893 for (const auto& item : category_contents_) { |
| 891 Category category = item.first; | 894 Category category = item.first; |
| 892 const CategoryContent& content = item.second; | 895 const CategoryContent& content = item.second; |
| 893 | 896 |
| 894 ClearCachedSuggestions(category); | 897 ClearCachedSuggestions(category); |
| 895 // Update listeners about the new (empty) state. | 898 // Update listeners about the new (empty) state. |
| 896 if (IsCategoryStatusAvailable(content.status)) { | 899 if (IsCategoryStatusAvailable(content.status)) { |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1063 EnterStateError(); | 1066 EnterStateError(); |
| 1064 break; | 1067 break; |
| 1065 | 1068 |
| 1066 case State::COUNT: | 1069 case State::COUNT: |
| 1067 NOTREACHED(); | 1070 NOTREACHED(); |
| 1068 break; | 1071 break; |
| 1069 } | 1072 } |
| 1070 } | 1073 } |
| 1071 | 1074 |
| 1072 void RemoteSuggestionsProviderImpl::NotifyStateChanged() { | 1075 void RemoteSuggestionsProviderImpl::NotifyStateChanged() { |
| 1073 if (!remote_suggestions_scheduler_) { | |
| 1074 return; | |
| 1075 } | |
| 1076 | |
| 1077 switch (state_) { | 1076 switch (state_) { |
| 1078 case State::NOT_INITED: | 1077 case State::NOT_INITED: |
| 1079 // Initial state, not sure yet whether active or not. | 1078 // Initial state, not sure yet whether active or not. |
| 1080 break; | 1079 break; |
| 1081 case State::READY: | 1080 case State::READY: |
| 1082 remote_suggestions_scheduler_->OnProviderActivated(); | 1081 remote_suggestions_scheduler_->OnProviderActivated(); |
| 1083 break; | 1082 break; |
| 1084 case State::DISABLED: | 1083 case State::DISABLED: |
| 1085 remote_suggestions_scheduler_->OnProviderDeactivated(); | 1084 remote_suggestions_scheduler_->OnProviderDeactivated(); |
| 1086 break; | 1085 break; |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1271 RemoteSuggestionsProviderImpl::CategoryContent::CategoryContent( | 1270 RemoteSuggestionsProviderImpl::CategoryContent::CategoryContent( |
| 1272 CategoryContent&&) = default; | 1271 CategoryContent&&) = default; |
| 1273 | 1272 |
| 1274 RemoteSuggestionsProviderImpl::CategoryContent::~CategoryContent() = default; | 1273 RemoteSuggestionsProviderImpl::CategoryContent::~CategoryContent() = default; |
| 1275 | 1274 |
| 1276 RemoteSuggestionsProviderImpl::CategoryContent& | 1275 RemoteSuggestionsProviderImpl::CategoryContent& |
| 1277 RemoteSuggestionsProviderImpl::CategoryContent::operator=(CategoryContent&&) = | 1276 RemoteSuggestionsProviderImpl::CategoryContent::operator=(CategoryContent&&) = |
| 1278 default; | 1277 default; |
| 1279 | 1278 |
| 1280 } // namespace ntp_snippets | 1279 } // namespace ntp_snippets |
| OLD | NEW |