| 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_ || |
| 322 !remote_suggestions_scheduler_->AcquireQuotaForInteractiveFetch()) { |
| 323 return; |
| 324 } |
| 327 FetchSuggestions(/*interactive_request=*/true, | 325 FetchSuggestions(/*interactive_request=*/true, |
| 328 /*callback=*/nullptr); | 326 /*callback=*/nullptr); |
| 329 } | 327 } |
| 330 | 328 |
| 331 void RemoteSuggestionsProviderImpl::RefetchInTheBackground( | 329 void RemoteSuggestionsProviderImpl::RefetchInTheBackground( |
| 332 std::unique_ptr<FetchStatusCallback> callback) { | 330 std::unique_ptr<FetchStatusCallback> callback) { |
| 333 FetchSuggestions(/*interactive_request=*/false, std::move(callback)); | 331 FetchSuggestions(/*interactive_request=*/false, std::move(callback)); |
| 334 } | 332 } |
| 335 | 333 |
| 336 const RemoteSuggestionsFetcher* | 334 const RemoteSuggestionsFetcher* |
| (...skipping 18 matching lines...) Expand all Loading... |
| 355 suggestions_fetcher_->FetchSnippets( | 353 suggestions_fetcher_->FetchSnippets( |
| 356 params, base::BindOnce(&RemoteSuggestionsProviderImpl::OnFetchFinished, | 354 params, base::BindOnce(&RemoteSuggestionsProviderImpl::OnFetchFinished, |
| 357 base::Unretained(this), std::move(callback), | 355 base::Unretained(this), std::move(callback), |
| 358 interactive_request)); | 356 interactive_request)); |
| 359 } | 357 } |
| 360 | 358 |
| 361 void RemoteSuggestionsProviderImpl::Fetch( | 359 void RemoteSuggestionsProviderImpl::Fetch( |
| 362 const Category& category, | 360 const Category& category, |
| 363 const std::set<std::string>& known_suggestion_ids, | 361 const std::set<std::string>& known_suggestion_ids, |
| 364 const FetchDoneCallback& callback) { | 362 const FetchDoneCallback& callback) { |
| 365 if (!ready()) { | 363 if (!ready() || !remote_suggestions_scheduler_) { |
| 366 CallWithEmptyResults(callback, | 364 CallWithEmptyResults(callback, |
| 367 Status(StatusCode::TEMPORARY_ERROR, | 365 Status(StatusCode::TEMPORARY_ERROR, |
| 368 "RemoteSuggestionsProvider is not ready!")); | 366 "RemoteSuggestionsProvider is not ready!")); |
| 369 return; | 367 return; |
| 370 } | 368 } |
| 369 if (!remote_suggestions_scheduler_->AcquireQuotaForInteractiveFetch()) { |
| 370 CallWithEmptyResults(callback, Status(StatusCode::TEMPORARY_ERROR, |
| 371 "Interactive quota exceeded!")); |
| 372 return; |
| 373 } |
| 371 RequestParams params = BuildFetchParams(); | 374 RequestParams params = BuildFetchParams(); |
| 372 params.excluded_ids.insert(known_suggestion_ids.begin(), | 375 params.excluded_ids.insert(known_suggestion_ids.begin(), |
| 373 known_suggestion_ids.end()); | 376 known_suggestion_ids.end()); |
| 374 params.interactive_request = true; | 377 params.interactive_request = true; |
| 375 params.exclusive_category = category; | 378 params.exclusive_category = category; |
| 376 | 379 |
| 377 suggestions_fetcher_->FetchSnippets( | 380 suggestions_fetcher_->FetchSnippets( |
| 378 params, | 381 params, |
| 379 base::BindOnce(&RemoteSuggestionsProviderImpl::OnFetchMoreFinished, | 382 base::BindOnce(&RemoteSuggestionsProviderImpl::OnFetchMoreFinished, |
| 380 base::Unretained(this), callback)); | 383 base::Unretained(this), callback)); |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 | 639 |
| 637 IntegrateSuggestions(existing_content, | 640 IntegrateSuggestions(existing_content, |
| 638 std::move(fetched_category.suggestions)); | 641 std::move(fetched_category.suggestions)); |
| 639 | 642 |
| 640 // TODO(tschumann): We should properly honor the existing category state, | 643 // 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: | 644 // 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 | 645 // Should Nuke also cancel outstanding requests, or do we want to check the |
| 643 // status? | 646 // status? |
| 644 UpdateCategoryStatus(category, CategoryStatus::AVAILABLE); | 647 UpdateCategoryStatus(category, CategoryStatus::AVAILABLE); |
| 645 // Notify callers and observers. | 648 // Notify callers and observers. |
| 649 remote_suggestions_scheduler_->OnInteractiveFetchFinished(status); |
| 646 fetching_callback.Run(Status::Success(), std::move(result)); | 650 fetching_callback.Run(Status::Success(), std::move(result)); |
| 647 NotifyNewSuggestions(category, *existing_content); | 651 NotifyNewSuggestions(category, *existing_content); |
| 648 } | 652 } |
| 649 | 653 |
| 650 void RemoteSuggestionsProviderImpl::OnFetchFinished( | 654 void RemoteSuggestionsProviderImpl::OnFetchFinished( |
| 651 std::unique_ptr<FetchStatusCallback> callback, | 655 std::unique_ptr<FetchStatusCallback> callback, |
| 652 bool interactive_request, | 656 bool interactive_request, |
| 653 Status status, | 657 Status status, |
| 654 RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories) { | 658 RemoteSuggestionsFetcher::OptionalFetchedCategories fetched_categories) { |
| 655 if (!ready()) { | 659 if (!ready()) { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 720 auto content_it = category_contents_.find(articles_category_); | 724 auto content_it = category_contents_.find(articles_category_); |
| 721 DCHECK(content_it != category_contents_.end()); | 725 DCHECK(content_it != category_contents_.end()); |
| 722 const CategoryContent& content = content_it->second; | 726 const CategoryContent& content = content_it->second; |
| 723 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.Snippets.NumArticles", | 727 UMA_HISTOGRAM_SPARSE_SLOWLY("NewTabPage.Snippets.NumArticles", |
| 724 content.suggestions.size()); | 728 content.suggestions.size()); |
| 725 if (content.suggestions.empty() && !content.dismissed.empty()) { | 729 if (content.suggestions.empty() && !content.dismissed.empty()) { |
| 726 UMA_HISTOGRAM_COUNTS("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded", | 730 UMA_HISTOGRAM_COUNTS("NewTabPage.Snippets.NumArticlesZeroDueToDiscarded", |
| 727 content.dismissed.size()); | 731 content.dismissed.size()); |
| 728 } | 732 } |
| 729 | 733 |
| 734 if (interactive_request) { |
| 735 remote_suggestions_scheduler_->OnInteractiveFetchFinished(status); |
| 736 } |
| 737 |
| 730 if (callback) { | 738 if (callback) { |
| 731 callback->Run(status); | 739 callback->Run(status); |
| 732 } | 740 } |
| 733 } | 741 } |
| 734 | 742 |
| 735 void RemoteSuggestionsProviderImpl::ArchiveSuggestions( | 743 void RemoteSuggestionsProviderImpl::ArchiveSuggestions( |
| 736 CategoryContent* content, | 744 CategoryContent* content, |
| 737 RemoteSuggestion::PtrVector* to_archive) { | 745 RemoteSuggestion::PtrVector* to_archive) { |
| 738 // Archive previous suggestions - move them at the beginning of the list. | 746 // Archive previous suggestions - move them at the beginning of the list. |
| 739 content->archived.insert(content->archived.begin(), | 747 content->archived.insert(content->archived.begin(), |
| (...skipping 531 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 |