| 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 "chrome/browser/ntp_snippets/download_suggestions_provider.h" | 5 #include "chrome/browser/ntp_snippets/download_suggestions_provider.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 30 matching lines...) Expand all Loading... |
| 41 using offline_pages::OfflinePageModelQueryBuilder; | 41 using offline_pages::OfflinePageModelQueryBuilder; |
| 42 | 42 |
| 43 namespace { | 43 namespace { |
| 44 | 44 |
| 45 const int kDefaultMaxSuggestionsCount = 5; | 45 const int kDefaultMaxSuggestionsCount = 5; |
| 46 const char kAssetDownloadsPrefix = 'D'; | 46 const char kAssetDownloadsPrefix = 'D'; |
| 47 const char kOfflinePageDownloadsPrefix = 'O'; | 47 const char kOfflinePageDownloadsPrefix = 'O'; |
| 48 | 48 |
| 49 const char* kMaxSuggestionsCountParamName = "downloads_max_count"; | 49 const char* kMaxSuggestionsCountParamName = "downloads_max_count"; |
| 50 | 50 |
| 51 bool CompareOfflinePagesMostRecentlyCreatedFirst(const OfflinePageItem& left, |
| 52 const OfflinePageItem& right) { |
| 53 return left.creation_time > right.creation_time; |
| 54 } |
| 55 |
| 51 int GetMaxSuggestionsCount() { | 56 int GetMaxSuggestionsCount() { |
| 52 bool assets_enabled = | 57 bool assets_enabled = |
| 53 base::FeatureList::IsEnabled(features::kAssetDownloadSuggestionsFeature); | 58 base::FeatureList::IsEnabled(features::kAssetDownloadSuggestionsFeature); |
| 54 return ntp_snippets::GetParamAsInt( | 59 return ntp_snippets::GetParamAsInt( |
| 55 assets_enabled ? features::kAssetDownloadSuggestionsFeature | 60 assets_enabled ? features::kAssetDownloadSuggestionsFeature |
| 56 : features::kOfflinePageDownloadSuggestionsFeature, | 61 : features::kOfflinePageDownloadSuggestionsFeature, |
| 57 kMaxSuggestionsCountParamName, kDefaultMaxSuggestionsCount); | 62 kMaxSuggestionsCountParamName, kDefaultMaxSuggestionsCount); |
| 58 } | 63 } |
| 59 | 64 |
| 60 std::string GetOfflinePagePerCategoryID(int64_t raw_offline_page_id) { | 65 std::string GetOfflinePagePerCategoryID(int64_t raw_offline_page_id) { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 87 | 92 |
| 88 bool IsDownloadCompleted(const DownloadItem& item) { | 93 bool IsDownloadCompleted(const DownloadItem& item) { |
| 89 return item.GetState() == DownloadItem::DownloadState::COMPLETE && | 94 return item.GetState() == DownloadItem::DownloadState::COMPLETE && |
| 90 !item.GetFileExternallyRemoved(); | 95 !item.GetFileExternallyRemoved(); |
| 91 } | 96 } |
| 92 | 97 |
| 93 base::Time GetAssetDownloadPublishedTime(const DownloadItem& item) { | 98 base::Time GetAssetDownloadPublishedTime(const DownloadItem& item) { |
| 94 return item.GetStartTime(); | 99 return item.GetStartTime(); |
| 95 } | 100 } |
| 96 | 101 |
| 97 struct OrderDownloadsMostRecentlyDownloadedFirst { | 102 bool CompareDownloadsMostRecentlyDownloadedFirst(const DownloadItem* left, |
| 98 bool operator()(const DownloadItem* left, const DownloadItem* right) const { | 103 const DownloadItem* right) { |
| 99 return GetAssetDownloadPublishedTime(*left) > | 104 return GetAssetDownloadPublishedTime(*left) > |
| 100 GetAssetDownloadPublishedTime(*right); | 105 GetAssetDownloadPublishedTime(*right); |
| 101 } | 106 } |
| 102 }; | |
| 103 | 107 |
| 104 bool IsClientIdForOfflinePageDownload( | 108 bool IsClientIdForOfflinePageDownload( |
| 105 offline_pages::ClientPolicyController* policy_controller, | 109 offline_pages::ClientPolicyController* policy_controller, |
| 106 const offline_pages::ClientId& client_id) { | 110 const offline_pages::ClientId& client_id) { |
| 107 return policy_controller->IsSupportedByDownload(client_id.name_space); | 111 return policy_controller->IsSupportedByDownload(client_id.name_space); |
| 108 } | 112 } |
| 109 | 113 |
| 110 std::unique_ptr<OfflinePageModelQuery> BuildOfflinePageDownloadsQuery( | 114 std::unique_ptr<OfflinePageModelQuery> BuildOfflinePageDownloadsQuery( |
| 111 offline_pages::OfflinePageModel* model) { | 115 offline_pages::OfflinePageModel* model) { |
| 112 OfflinePageModelQueryBuilder builder; | 116 OfflinePageModelQueryBuilder builder; |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 | 306 |
| 303 void DownloadSuggestionsProvider::OfflinePageModelLoaded( | 307 void DownloadSuggestionsProvider::OfflinePageModelLoaded( |
| 304 offline_pages::OfflinePageModel* model) { | 308 offline_pages::OfflinePageModel* model) { |
| 305 DCHECK_EQ(offline_page_model_, model); | 309 DCHECK_EQ(offline_page_model_, model); |
| 306 AsynchronouslyFetchOfflinePagesDownloads(/*notify=*/true); | 310 AsynchronouslyFetchOfflinePagesDownloads(/*notify=*/true); |
| 307 } | 311 } |
| 308 | 312 |
| 309 void DownloadSuggestionsProvider::OfflinePageAdded( | 313 void DownloadSuggestionsProvider::OfflinePageAdded( |
| 310 offline_pages::OfflinePageModel* model, | 314 offline_pages::OfflinePageModel* model, |
| 311 const offline_pages::OfflinePageItem& added_page) { | 315 const offline_pages::OfflinePageItem& added_page) { |
| 312 // TODO(dewittj, vitaliii): Don't refetch everything when this is called. | |
| 313 DCHECK_EQ(offline_page_model_, model); | 316 DCHECK_EQ(offline_page_model_, model); |
| 314 AsynchronouslyFetchOfflinePagesDownloads(/*notify=*/true); | 317 if (!IsClientIdForOfflinePageDownload(model->GetPolicyController(), |
| 318 added_page.client_id)) { |
| 319 return; |
| 320 } |
| 321 |
| 322 // This is all in one statement so that it is completely compiled out in |
| 323 // release builds. |
| 324 DCHECK_EQ(ReadOfflinePageDismissedIDsFromPrefs().count( |
| 325 GetOfflinePagePerCategoryID(added_page.offline_id)), |
| 326 0U); |
| 327 |
| 328 int max_suggestions_count = GetMaxSuggestionsCount(); |
| 329 if (static_cast<int>(cached_offline_page_downloads_.size()) < |
| 330 max_suggestions_count) { |
| 331 cached_offline_page_downloads_.push_back(added_page); |
| 332 } else if (max_suggestions_count > 0) { |
| 333 auto oldest_page_iterator = |
| 334 std::max_element(cached_offline_page_downloads_.begin(), |
| 335 cached_offline_page_downloads_.end(), |
| 336 &CompareOfflinePagesMostRecentlyCreatedFirst); |
| 337 *oldest_page_iterator = added_page; |
| 338 } |
| 339 |
| 340 SubmitContentSuggestions(); |
| 315 } | 341 } |
| 316 | 342 |
| 317 void DownloadSuggestionsProvider::OfflinePageDeleted( | 343 void DownloadSuggestionsProvider::OfflinePageDeleted( |
| 318 int64_t offline_id, | 344 int64_t offline_id, |
| 319 const offline_pages::ClientId& client_id) { | 345 const offline_pages::ClientId& client_id) { |
| 320 DCHECK(offline_page_model_); | 346 DCHECK(offline_page_model_); |
| 321 if (IsClientIdForOfflinePageDownload( | 347 if (IsClientIdForOfflinePageDownload( |
| 322 offline_page_model_->GetPolicyController(), client_id)) { | 348 offline_page_model_->GetPolicyController(), client_id)) { |
| 323 InvalidateSuggestion(GetOfflinePagePerCategoryID(offline_id)); | 349 InvalidateSuggestion(GetOfflinePagePerCategoryID(offline_id)); |
| 324 } | 350 } |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 if (static_cast<int>(cached_asset_downloads_.size()) > | 472 if (static_cast<int>(cached_asset_downloads_.size()) > |
| 447 max_suggestions_count) { | 473 max_suggestions_count) { |
| 448 // Partially sorts |downloads| such that: | 474 // Partially sorts |downloads| such that: |
| 449 // 1) The element at the index |max_suggestions_count| is changed to the | 475 // 1) The element at the index |max_suggestions_count| is changed to the |
| 450 // element which would occur on this position if |downloads| was sorted; | 476 // element which would occur on this position if |downloads| was sorted; |
| 451 // 2) All of the elements before index |max_suggestions_count| are less than | 477 // 2) All of the elements before index |max_suggestions_count| are less than |
| 452 // or equal to the elements after it. | 478 // or equal to the elements after it. |
| 453 std::nth_element(cached_asset_downloads_.begin(), | 479 std::nth_element(cached_asset_downloads_.begin(), |
| 454 cached_asset_downloads_.begin() + max_suggestions_count, | 480 cached_asset_downloads_.begin() + max_suggestions_count, |
| 455 cached_asset_downloads_.end(), | 481 cached_asset_downloads_.end(), |
| 456 OrderDownloadsMostRecentlyDownloadedFirst()); | 482 &CompareDownloadsMostRecentlyDownloadedFirst); |
| 457 cached_asset_downloads_.resize(max_suggestions_count); | 483 cached_asset_downloads_.resize(max_suggestions_count); |
| 458 } | 484 } |
| 459 } | 485 } |
| 460 | 486 |
| 461 void DownloadSuggestionsProvider:: | 487 void DownloadSuggestionsProvider:: |
| 462 AsynchronouslyFetchAllDownloadsAndSubmitSuggestions() { | 488 AsynchronouslyFetchAllDownloadsAndSubmitSuggestions() { |
| 463 FetchAssetsDownloads(); | 489 FetchAssetsDownloads(); |
| 464 AsynchronouslyFetchOfflinePagesDownloads(/*notify=*/true); | 490 AsynchronouslyFetchOfflinePagesDownloads(/*notify=*/true); |
| 465 } | 491 } |
| 466 | 492 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 | 571 |
| 546 std::set<std::string> dismissed_ids = ReadAssetDismissedIDsFromPrefs(); | 572 std::set<std::string> dismissed_ids = ReadAssetDismissedIDsFromPrefs(); |
| 547 if (dismissed_ids.count(GetAssetDownloadPerCategoryID(item->GetId()))) { | 573 if (dismissed_ids.count(GetAssetDownloadPerCategoryID(item->GetId()))) { |
| 548 return false; | 574 return false; |
| 549 } | 575 } |
| 550 | 576 |
| 551 DCHECK_LE(static_cast<int>(cached_asset_downloads_.size()), | 577 DCHECK_LE(static_cast<int>(cached_asset_downloads_.size()), |
| 552 GetMaxSuggestionsCount()); | 578 GetMaxSuggestionsCount()); |
| 553 if (static_cast<int>(cached_asset_downloads_.size()) == | 579 if (static_cast<int>(cached_asset_downloads_.size()) == |
| 554 GetMaxSuggestionsCount()) { | 580 GetMaxSuggestionsCount()) { |
| 555 auto oldest = std::max_element(cached_asset_downloads_.begin(), | 581 auto oldest = std::max_element( |
| 556 cached_asset_downloads_.end(), | 582 cached_asset_downloads_.begin(), cached_asset_downloads_.end(), |
| 557 OrderDownloadsMostRecentlyDownloadedFirst()); | 583 &CompareDownloadsMostRecentlyDownloadedFirst); |
| 558 if (GetAssetDownloadPublishedTime(*item) <= | 584 if (GetAssetDownloadPublishedTime(*item) <= |
| 559 GetAssetDownloadPublishedTime(**oldest)) { | 585 GetAssetDownloadPublishedTime(**oldest)) { |
| 560 return false; | 586 return false; |
| 561 } | 587 } |
| 562 | 588 |
| 563 *oldest = item; | 589 *oldest = item; |
| 564 } else { | 590 } else { |
| 565 cached_asset_downloads_.push_back(item); | 591 cached_asset_downloads_.push_back(item); |
| 566 } | 592 } |
| 567 | 593 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 651 const int max_suggestions_count = GetMaxSuggestionsCount(); | 677 const int max_suggestions_count = GetMaxSuggestionsCount(); |
| 652 if (static_cast<int>(items.size()) > max_suggestions_count) { | 678 if (static_cast<int>(items.size()) > max_suggestions_count) { |
| 653 // Partially sorts |items| such that: | 679 // Partially sorts |items| such that: |
| 654 // 1) The element at the index |max_suggestions_count| is changed to the | 680 // 1) The element at the index |max_suggestions_count| is changed to the |
| 655 // element which would occur on this position if |items| was sorted; | 681 // element which would occur on this position if |items| was sorted; |
| 656 // 2) All of the elements before index |max_suggestions_count| are less than | 682 // 2) All of the elements before index |max_suggestions_count| are less than |
| 657 // or equal to the elements after it. | 683 // or equal to the elements after it. |
| 658 std::nth_element( | 684 std::nth_element( |
| 659 items.begin(), items.begin() + max_suggestions_count, items.end(), | 685 items.begin(), items.begin() + max_suggestions_count, items.end(), |
| 660 [](const OfflinePageItem* left, const OfflinePageItem* right) { | 686 [](const OfflinePageItem* left, const OfflinePageItem* right) { |
| 661 return left->creation_time > right->creation_time; | 687 return CompareOfflinePagesMostRecentlyCreatedFirst(*left, *right); |
| 662 }); | 688 }); |
| 663 items.resize(max_suggestions_count); | 689 items.resize(max_suggestions_count); |
| 664 } | 690 } |
| 665 | 691 |
| 666 cached_offline_page_downloads_.clear(); | 692 cached_offline_page_downloads_.clear(); |
| 667 for (const OfflinePageItem* item : items) { | 693 for (const OfflinePageItem* item : items) { |
| 668 cached_offline_page_downloads_.push_back(*item); | 694 cached_offline_page_downloads_.push_back(*item); |
| 669 } | 695 } |
| 670 | 696 |
| 671 if (old_dismissed_ids.size() != retained_dismissed_ids.size()) { | 697 if (old_dismissed_ids.size() != retained_dismissed_ids.size()) { |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 747 void DownloadSuggestionsProvider::UnregisterDownloadItemObservers() { | 773 void DownloadSuggestionsProvider::UnregisterDownloadItemObservers() { |
| 748 DCHECK_NE(download_manager_, nullptr); | 774 DCHECK_NE(download_manager_, nullptr); |
| 749 | 775 |
| 750 std::vector<DownloadItem*> all_downloads; | 776 std::vector<DownloadItem*> all_downloads; |
| 751 download_manager_->GetAllDownloads(&all_downloads); | 777 download_manager_->GetAllDownloads(&all_downloads); |
| 752 | 778 |
| 753 for (DownloadItem* item : all_downloads) { | 779 for (DownloadItem* item : all_downloads) { |
| 754 item->RemoveObserver(this); | 780 item->RemoveObserver(this); |
| 755 } | 781 } |
| 756 } | 782 } |
| OLD | NEW |