| 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() { |
| 327 FetchSuggestions(/*interactive_request=*/true, | 321 if (!remote_suggestions_scheduler_->AcquireQuotaForInteractiveFetch()) { |
| 328 /*callback=*/nullptr); | 322 return; |
| 323 } |
| 324 FetchSuggestions( |
| 325 /*interactive_request=*/true, |
| 326 base::MakeUnique<FetchStatusCallback>(base::Bind( |
| 327 [](RemoteSuggestionsScheduler* scheduler, Status status_code) { |
| 328 scheduler->OnInteractiveFetchFinished(status_code); |
| 329 }, |
| 330 base::Unretained(remote_suggestions_scheduler_)))); |
| 329 } | 331 } |
| 330 | 332 |
| 331 void RemoteSuggestionsProviderImpl::RefetchInTheBackground( | 333 void RemoteSuggestionsProviderImpl::RefetchInTheBackground( |
| 332 std::unique_ptr<FetchStatusCallback> callback) { | 334 std::unique_ptr<FetchStatusCallback> callback) { |
| 333 FetchSuggestions(/*interactive_request=*/false, std::move(callback)); | 335 FetchSuggestions(/*interactive_request=*/false, std::move(callback)); |
| 334 } | 336 } |
| 335 | 337 |
| 336 const RemoteSuggestionsFetcher* | 338 const RemoteSuggestionsFetcher* |
| 337 RemoteSuggestionsProviderImpl::suggestions_fetcher_for_debugging() const { | 339 RemoteSuggestionsProviderImpl::suggestions_fetcher_for_debugging() const { |
| 338 return suggestions_fetcher_.get(); | 340 return suggestions_fetcher_.get(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 361 void RemoteSuggestionsProviderImpl::Fetch( | 363 void RemoteSuggestionsProviderImpl::Fetch( |
| 362 const Category& category, | 364 const Category& category, |
| 363 const std::set<std::string>& known_suggestion_ids, | 365 const std::set<std::string>& known_suggestion_ids, |
| 364 const FetchDoneCallback& callback) { | 366 const FetchDoneCallback& callback) { |
| 365 if (!ready()) { | 367 if (!ready()) { |
| 366 CallWithEmptyResults(callback, | 368 CallWithEmptyResults(callback, |
| 367 Status(StatusCode::TEMPORARY_ERROR, | 369 Status(StatusCode::TEMPORARY_ERROR, |
| 368 "RemoteSuggestionsProvider is not ready!")); | 370 "RemoteSuggestionsProvider is not ready!")); |
| 369 return; | 371 return; |
| 370 } | 372 } |
| 373 if (!remote_suggestions_scheduler_->AcquireQuotaForInteractiveFetch()) { |
| 374 CallWithEmptyResults(callback, Status(StatusCode::TEMPORARY_ERROR, |
| 375 "Interactive quota exceeded!")); |
| 376 return; |
| 377 } |
| 378 // Make sure after the fetch, the scheduler is informed about the status. |
| 379 FetchDoneCallback callback_wrapper = base::Bind( |
| 380 [](RemoteSuggestionsScheduler* scheduler, |
| 381 const FetchDoneCallback& callback, Status status_code, |
| 382 std::vector<ContentSuggestion> suggestions) { |
| 383 scheduler->OnInteractiveFetchFinished(status_code); |
| 384 callback.Run(status_code, std::move(suggestions)); |
| 385 }, |
| 386 base::Unretained(remote_suggestions_scheduler_), callback); |
| 387 |
| 371 RequestParams params = BuildFetchParams(); | 388 RequestParams params = BuildFetchParams(); |
| 372 params.excluded_ids.insert(known_suggestion_ids.begin(), | 389 params.excluded_ids.insert(known_suggestion_ids.begin(), |
| 373 known_suggestion_ids.end()); | 390 known_suggestion_ids.end()); |
| 374 params.interactive_request = true; | 391 params.interactive_request = true; |
| 375 params.exclusive_category = category; | 392 params.exclusive_category = category; |
| 376 | 393 |
| 377 suggestions_fetcher_->FetchSnippets( | 394 suggestions_fetcher_->FetchSnippets( |
| 378 params, | 395 params, |
| 379 base::BindOnce(&RemoteSuggestionsProviderImpl::OnFetchMoreFinished, | 396 base::BindOnce(&RemoteSuggestionsProviderImpl::OnFetchMoreFinished, |
| 380 base::Unretained(this), callback)); | 397 base::Unretained(this), callback_wrapper)); |
| 381 } | 398 } |
| 382 | 399 |
| 383 // Builds default fetcher params. | 400 // Builds default fetcher params. |
| 384 RequestParams RemoteSuggestionsProviderImpl::BuildFetchParams() const { | 401 RequestParams RemoteSuggestionsProviderImpl::BuildFetchParams() const { |
| 385 RequestParams result; | 402 RequestParams result; |
| 386 result.language_code = application_language_code_; | 403 result.language_code = application_language_code_; |
| 387 result.count_to_fetch = kMaxSuggestionCount; | 404 result.count_to_fetch = kMaxSuggestionCount; |
| 388 for (const auto& map_entry : category_contents_) { | 405 for (const auto& map_entry : category_contents_) { |
| 389 const CategoryContent& content = map_entry.second; | 406 const CategoryContent& content = map_entry.second; |
| 390 for (const auto& dismissed_suggestion : content.dismissed) { | 407 for (const auto& dismissed_suggestion : content.dismissed) { |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 635 DCHECK(existing_content->suggestions.empty()); | 652 DCHECK(existing_content->suggestions.empty()); |
| 636 | 653 |
| 637 IntegrateSuggestions(existing_content, | 654 IntegrateSuggestions(existing_content, |
| 638 std::move(fetched_category.suggestions)); | 655 std::move(fetched_category.suggestions)); |
| 639 | 656 |
| 640 // TODO(tschumann): We should properly honor the existing category state, | 657 // 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: | 658 // 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 | 659 // Should Nuke also cancel outstanding requests, or do we want to check the |
| 643 // status? | 660 // status? |
| 644 UpdateCategoryStatus(category, CategoryStatus::AVAILABLE); | 661 UpdateCategoryStatus(category, CategoryStatus::AVAILABLE); |
| 645 // Notify callers and observers. | |
| 646 fetching_callback.Run(Status::Success(), std::move(result)); | 662 fetching_callback.Run(Status::Success(), std::move(result)); |
| 647 NotifyNewSuggestions(category, *existing_content); | 663 NotifyNewSuggestions(category, *existing_content); |
| 648 } | 664 } |
| 649 | 665 |
| 650 void RemoteSuggestionsProviderImpl::OnFetchFinished( | 666 void RemoteSuggestionsProviderImpl::OnFetchFinished( |
| 651 std::unique_ptr<FetchStatusCallback> callback, | 667 std::unique_ptr<FetchStatusCallback> callback, |
| 652 bool interactive_request, | 668 bool interactive_request, |
| 653 Status status, | 669 Status status, |
| 654 RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories) { | 670 RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories) { |
| 655 if (!ready()) { | 671 if (!ready()) { |
| (...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 865 database_->GarbageCollectImages(std::move(alive_suggestions)); | 881 database_->GarbageCollectImages(std::move(alive_suggestions)); |
| 866 } | 882 } |
| 867 | 883 |
| 868 void RemoteSuggestionsProviderImpl::ClearHistoryDependentState() { | 884 void RemoteSuggestionsProviderImpl::ClearHistoryDependentState() { |
| 869 if (!initialized()) { | 885 if (!initialized()) { |
| 870 clear_history_dependent_state_when_initialized_ = true; | 886 clear_history_dependent_state_when_initialized_ = true; |
| 871 return; | 887 return; |
| 872 } | 888 } |
| 873 | 889 |
| 874 NukeAllSuggestions(); | 890 NukeAllSuggestions(); |
| 875 if (remote_suggestions_scheduler_) { | 891 remote_suggestions_scheduler_->OnHistoryCleared(); |
| 876 remote_suggestions_scheduler_->OnHistoryCleared(); | |
| 877 } | |
| 878 } | 892 } |
| 879 | 893 |
| 880 void RemoteSuggestionsProviderImpl::ClearSuggestions() { | 894 void RemoteSuggestionsProviderImpl::ClearSuggestions() { |
| 881 DCHECK(initialized()); | 895 DCHECK(initialized()); |
| 882 | 896 |
| 883 NukeAllSuggestions(); | 897 NukeAllSuggestions(); |
| 884 if (remote_suggestions_scheduler_) { | 898 remote_suggestions_scheduler_->OnSuggestionsCleared(); |
| 885 remote_suggestions_scheduler_->OnSuggestionsCleared(); | |
| 886 } | |
| 887 } | 899 } |
| 888 | 900 |
| 889 void RemoteSuggestionsProviderImpl::NukeAllSuggestions() { | 901 void RemoteSuggestionsProviderImpl::NukeAllSuggestions() { |
| 890 for (const auto& item : category_contents_) { | 902 for (const auto& item : category_contents_) { |
| 891 Category category = item.first; | 903 Category category = item.first; |
| 892 const CategoryContent& content = item.second; | 904 const CategoryContent& content = item.second; |
| 893 | 905 |
| 894 ClearCachedSuggestions(category); | 906 ClearCachedSuggestions(category); |
| 895 // Update listeners about the new (empty) state. | 907 // Update listeners about the new (empty) state. |
| 896 if (IsCategoryStatusAvailable(content.status)) { | 908 if (IsCategoryStatusAvailable(content.status)) { |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1063 EnterStateError(); | 1075 EnterStateError(); |
| 1064 break; | 1076 break; |
| 1065 | 1077 |
| 1066 case State::COUNT: | 1078 case State::COUNT: |
| 1067 NOTREACHED(); | 1079 NOTREACHED(); |
| 1068 break; | 1080 break; |
| 1069 } | 1081 } |
| 1070 } | 1082 } |
| 1071 | 1083 |
| 1072 void RemoteSuggestionsProviderImpl::NotifyStateChanged() { | 1084 void RemoteSuggestionsProviderImpl::NotifyStateChanged() { |
| 1073 if (!remote_suggestions_scheduler_) { | |
| 1074 return; | |
| 1075 } | |
| 1076 | |
| 1077 switch (state_) { | 1085 switch (state_) { |
| 1078 case State::NOT_INITED: | 1086 case State::NOT_INITED: |
| 1079 // Initial state, not sure yet whether active or not. | 1087 // Initial state, not sure yet whether active or not. |
| 1080 break; | 1088 break; |
| 1081 case State::READY: | 1089 case State::READY: |
| 1082 remote_suggestions_scheduler_->OnProviderActivated(); | 1090 remote_suggestions_scheduler_->OnProviderActivated(); |
| 1083 break; | 1091 break; |
| 1084 case State::DISABLED: | 1092 case State::DISABLED: |
| 1085 remote_suggestions_scheduler_->OnProviderDeactivated(); | 1093 remote_suggestions_scheduler_->OnProviderDeactivated(); |
| 1086 break; | 1094 break; |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1271 RemoteSuggestionsProviderImpl::CategoryContent::CategoryContent( | 1279 RemoteSuggestionsProviderImpl::CategoryContent::CategoryContent( |
| 1272 CategoryContent&&) = default; | 1280 CategoryContent&&) = default; |
| 1273 | 1281 |
| 1274 RemoteSuggestionsProviderImpl::CategoryContent::~CategoryContent() = default; | 1282 RemoteSuggestionsProviderImpl::CategoryContent::~CategoryContent() = default; |
| 1275 | 1283 |
| 1276 RemoteSuggestionsProviderImpl::CategoryContent& | 1284 RemoteSuggestionsProviderImpl::CategoryContent& |
| 1277 RemoteSuggestionsProviderImpl::CategoryContent::operator=(CategoryContent&&) = | 1285 RemoteSuggestionsProviderImpl::CategoryContent::operator=(CategoryContent&&) = |
| 1278 default; | 1286 default; |
| 1279 | 1287 |
| 1280 } // namespace ntp_snippets | 1288 } // namespace ntp_snippets |
| OLD | NEW |