Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Side by Side Diff: chrome/browser/ntp_snippets/download_suggestions_provider.cc

Issue 2673633002: [NTP::Downloads] Do not show old downloads. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
11 #include "base/feature_list.h" 11 #include "base/feature_list.h"
12 #include "base/guid.h" 12 #include "base/guid.h"
13 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
14 #include "base/stl_util.h" 14 #include "base/stl_util.h"
15 #include "base/strings/string_number_conversions.h" 15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/string_util.h" 16 #include "base/strings/string_util.h"
17 #include "base/strings/utf_string_conversions.h" 17 #include "base/strings/utf_string_conversions.h"
18 #include "base/threading/thread_task_runner_handle.h" 18 #include "base/threading/thread_task_runner_handle.h"
19 #include "base/time/clock.h"
19 #include "base/time/time.h" 20 #include "base/time/time.h"
20 #include "chrome/common/chrome_features.h" 21 #include "chrome/common/chrome_features.h"
21 #include "chrome/grit/generated_resources.h" 22 #include "chrome/grit/generated_resources.h"
22 #include "components/ntp_snippets/features.h" 23 #include "components/ntp_snippets/features.h"
23 #include "components/ntp_snippets/pref_names.h" 24 #include "components/ntp_snippets/pref_names.h"
24 #include "components/ntp_snippets/pref_util.h" 25 #include "components/ntp_snippets/pref_util.h"
25 #include "components/offline_pages/core/offline_page_model_query.h" 26 #include "components/offline_pages/core/offline_page_model_query.h"
26 #include "components/prefs/pref_registry_simple.h" 27 #include "components/prefs/pref_registry_simple.h"
27 #include "components/prefs/pref_service.h" 28 #include "components/prefs/pref_service.h"
28 #include "components/variations/variations_associated_data.h" 29 #include "components/variations/variations_associated_data.h"
29 #include "ui/base/l10n/l10n_util.h" 30 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/gfx/image/image.h" 31 #include "ui/gfx/image/image.h"
31 32
32 using content::DownloadItem; 33 using content::DownloadItem;
33 using content::DownloadManager; 34 using content::DownloadManager;
34 using ntp_snippets::Category; 35 using ntp_snippets::Category;
35 using ntp_snippets::CategoryInfo; 36 using ntp_snippets::CategoryInfo;
36 using ntp_snippets::CategoryStatus; 37 using ntp_snippets::CategoryStatus;
37 using ntp_snippets::ContentSuggestion; 38 using ntp_snippets::ContentSuggestion;
38 using ntp_snippets::prefs::kDismissedAssetDownloadSuggestions; 39 using ntp_snippets::prefs::kDismissedAssetDownloadSuggestions;
39 using ntp_snippets::prefs::kDismissedOfflinePageDownloadSuggestions; 40 using ntp_snippets::prefs::kDismissedOfflinePageDownloadSuggestions;
40 using offline_pages::OfflinePageItem; 41 using offline_pages::OfflinePageItem;
41 using offline_pages::OfflinePageModelQuery; 42 using offline_pages::OfflinePageModelQuery;
42 using offline_pages::OfflinePageModelQueryBuilder; 43 using offline_pages::OfflinePageModelQueryBuilder;
43 44
44 namespace { 45 namespace {
45 46
46 const int kDefaultMaxSuggestionsCount = 5; 47 const int kDefaultMaxSuggestionsCount = 5;
48 const int kDefaultMaxDownloadAgeDays = 6 * 7; // 6 weeks
47 const char kAssetDownloadsPrefix = 'D'; 49 const char kAssetDownloadsPrefix = 'D';
48 const char kOfflinePageDownloadsPrefix = 'O'; 50 const char kOfflinePageDownloadsPrefix = 'O';
49 51
50 const char* kMaxSuggestionsCountParamName = "downloads_max_count"; 52 const char* kMaxSuggestionsCountParamName = "downloads_max_count";
53 const char* kMaxDownloadAgeDaysParamName = "downloads_max_age_days";
51 54
52 bool CompareOfflinePagesMostRecentlyCreatedFirst(const OfflinePageItem& left, 55 base::Time GetOfflinePagePublishedTime(const OfflinePageItem& item) {
53 const OfflinePageItem& right) { 56 return item.creation_time;
54 return left.creation_time > right.creation_time; 57 }
58
59 bool CompareOfflinePagesMostRecentlyPublishedFirst(
60 const OfflinePageItem& left,
61 const OfflinePageItem& right) {
62 return GetOfflinePagePublishedTime(left) > GetOfflinePagePublishedTime(right);
55 } 63 }
56 64
57 int GetMaxSuggestionsCount() { 65 int GetMaxSuggestionsCount() {
58 bool assets_enabled = 66 bool assets_enabled =
59 base::FeatureList::IsEnabled(features::kAssetDownloadSuggestionsFeature); 67 base::FeatureList::IsEnabled(features::kAssetDownloadSuggestionsFeature);
60 return variations::GetVariationParamByFeatureAsInt( 68 return variations::GetVariationParamByFeatureAsInt(
61 assets_enabled ? features::kAssetDownloadSuggestionsFeature 69 assets_enabled ? features::kAssetDownloadSuggestionsFeature
62 : features::kOfflinePageDownloadSuggestionsFeature, 70 : features::kOfflinePageDownloadSuggestionsFeature,
63 kMaxSuggestionsCountParamName, kDefaultMaxSuggestionsCount); 71 kMaxSuggestionsCountParamName, kDefaultMaxSuggestionsCount);
64 } 72 }
65 73
74 int GetMaxDownloadAgeDays() {
75 bool assets_enabled =
76 base::FeatureList::IsEnabled(features::kAssetDownloadSuggestionsFeature);
77 return variations::GetVariationParamByFeatureAsInt(
78 assets_enabled ? features::kAssetDownloadSuggestionsFeature
tschumann 2017/02/02 14:30:33 +Jan, can you double-check this is sane? It's the
jkrcal 2017/02/02 16:06:16 After offline discussion, this is sane, please add
vitaliii 2017/02/07 10:26:05 Done. I added comments. |GetVariationParamByFea
79 : features::kOfflinePageDownloadSuggestionsFeature,
80 kMaxDownloadAgeDaysParamName, kDefaultMaxDownloadAgeDays);
81 }
82
66 std::string GetOfflinePagePerCategoryID(int64_t raw_offline_page_id) { 83 std::string GetOfflinePagePerCategoryID(int64_t raw_offline_page_id) {
67 // Raw ID is prefixed in order to avoid conflicts with asset downloads. 84 // Raw ID is prefixed in order to avoid conflicts with asset downloads.
68 return std::string(1, kOfflinePageDownloadsPrefix) + 85 return std::string(1, kOfflinePageDownloadsPrefix) +
69 base::IntToString(raw_offline_page_id); 86 base::IntToString(raw_offline_page_id);
70 } 87 }
71 88
72 std::string GetAssetDownloadPerCategoryID(uint32_t raw_download_id) { 89 std::string GetAssetDownloadPerCategoryID(uint32_t raw_download_id) {
73 // Raw ID is prefixed in order to avoid conflicts with offline page downloads. 90 // Raw ID is prefixed in order to avoid conflicts with offline page downloads.
74 return std::string(1, kAssetDownloadsPrefix) + 91 return std::string(1, kAssetDownloadsPrefix) +
75 base::UintToString(raw_download_id); 92 base::UintToString(raw_download_id);
76 } 93 }
77 94
78 // Determines whether |suggestion_id| corresponds to offline page suggestion or 95 // Determines whether |suggestion_id| corresponds to offline page suggestion or
79 // asset download based on |id_within_category| prefix. 96 // asset download based on |id_within_category| prefix.
80 bool CorrespondsToOfflinePage(const ContentSuggestion::ID& suggestion_id) { 97 bool CorrespondsToOfflinePage(const ContentSuggestion::ID& suggestion_id) {
81 const std::string& id_within_category = suggestion_id.id_within_category(); 98 const std::string& id_within_category = suggestion_id.id_within_category();
82 if (!id_within_category.empty()) { 99 if (!id_within_category.empty()) {
83 if (id_within_category[0] == kOfflinePageDownloadsPrefix) { 100 if (id_within_category[0] == kOfflinePageDownloadsPrefix) {
84 return true; 101 return true;
85 } 102 }
86 if (id_within_category[0] == kAssetDownloadsPrefix) { 103 if (id_within_category[0] == kAssetDownloadsPrefix) {
87 return false; 104 return false;
88 } 105 }
89 } 106 }
90 NOTREACHED() << "Unknown id_within_category " << id_within_category; 107 NOTREACHED() << "Unknown id_within_category " << id_within_category;
91 return false; 108 return false;
92 } 109 }
93 110
94 bool IsDownloadCompleted(const DownloadItem& item) { 111 bool IsAssetDownloadCompleted(const DownloadItem& item) {
95 return item.GetState() == DownloadItem::DownloadState::COMPLETE && 112 return item.GetState() == DownloadItem::DownloadState::COMPLETE &&
96 !item.GetFileExternallyRemoved(); 113 !item.GetFileExternallyRemoved();
97 } 114 }
98 115
99 base::Time GetAssetDownloadPublishedTime(const DownloadItem& item) { 116 base::Time GetAssetDownloadPublishedTime(const DownloadItem& item) {
100 return item.GetStartTime(); 117 return item.GetStartTime();
101 } 118 }
102 119
103 bool CompareDownloadsMostRecentlyDownloadedFirst(const DownloadItem* left, 120 bool CompareDownloadsMostRecentlyPublishedFirst(const DownloadItem* left,
104 const DownloadItem* right) { 121 const DownloadItem* right) {
105 return GetAssetDownloadPublishedTime(*left) > 122 return GetAssetDownloadPublishedTime(*left) >
106 GetAssetDownloadPublishedTime(*right); 123 GetAssetDownloadPublishedTime(*right);
107 } 124 }
108 125
109 bool IsClientIdForOfflinePageDownload( 126 bool IsClientIdForOfflinePageDownload(
110 offline_pages::ClientPolicyController* policy_controller, 127 offline_pages::ClientPolicyController* policy_controller,
111 const offline_pages::ClientId& client_id) { 128 const offline_pages::ClientId& client_id) {
112 return policy_controller->IsSupportedByDownload(client_id.name_space); 129 return policy_controller->IsSupportedByDownload(client_id.name_space);
113 } 130 }
114 131
115 std::unique_ptr<OfflinePageModelQuery> BuildOfflinePageDownloadsQuery( 132 std::unique_ptr<OfflinePageModelQuery> BuildOfflinePageDownloadsQuery(
116 offline_pages::OfflinePageModel* model) { 133 offline_pages::OfflinePageModel* model) {
117 OfflinePageModelQueryBuilder builder; 134 OfflinePageModelQueryBuilder builder;
118 builder.RequireSupportedByDownload( 135 builder.RequireSupportedByDownload(
119 OfflinePageModelQuery::Requirement::INCLUDE_MATCHING); 136 OfflinePageModelQuery::Requirement::INCLUDE_MATCHING);
120 return builder.Build(model->GetPolicyController()); 137 return builder.Build(model->GetPolicyController());
121 } 138 }
122 139
123 } // namespace 140 } // namespace
124 141
125 DownloadSuggestionsProvider::DownloadSuggestionsProvider( 142 DownloadSuggestionsProvider::DownloadSuggestionsProvider(
126 ContentSuggestionsProvider::Observer* observer, 143 ContentSuggestionsProvider::Observer* observer,
127 offline_pages::OfflinePageModel* offline_page_model, 144 offline_pages::OfflinePageModel* offline_page_model,
128 content::DownloadManager* download_manager, 145 content::DownloadManager* download_manager,
129 DownloadHistory* download_history, 146 DownloadHistory* download_history,
130 PrefService* pref_service) 147 PrefService* pref_service,
148 std::unique_ptr<base::Clock> clock)
131 : ContentSuggestionsProvider(observer), 149 : ContentSuggestionsProvider(observer),
132 category_status_(CategoryStatus::AVAILABLE_LOADING), 150 category_status_(CategoryStatus::AVAILABLE_LOADING),
133 provided_category_(Category::FromKnownCategory( 151 provided_category_(Category::FromKnownCategory(
134 ntp_snippets::KnownCategories::DOWNLOADS)), 152 ntp_snippets::KnownCategories::DOWNLOADS)),
135 offline_page_model_(offline_page_model), 153 offline_page_model_(offline_page_model),
136 download_manager_(download_manager), 154 download_manager_(download_manager),
137 download_history_(download_history), 155 download_history_(download_history),
138 pref_service_(pref_service), 156 pref_service_(pref_service),
157 clock_(std::move(clock)),
139 is_asset_downloads_initialization_complete_(false), 158 is_asset_downloads_initialization_complete_(false),
140 weak_ptr_factory_(this) { 159 weak_ptr_factory_(this) {
141 observer->OnCategoryStatusChanged(this, provided_category_, category_status_); 160 observer->OnCategoryStatusChanged(this, provided_category_, category_status_);
142 161
143 DCHECK(offline_page_model_ || download_manager_); 162 DCHECK(offline_page_model_ || download_manager_);
144 if (offline_page_model_) { 163 if (offline_page_model_) {
145 offline_page_model_->AddObserver(this); 164 offline_page_model_->AddObserver(this);
146 } 165 }
147 166
148 if (download_manager_) { 167 if (download_manager_) {
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
338 0U); 357 0U);
339 358
340 int max_suggestions_count = GetMaxSuggestionsCount(); 359 int max_suggestions_count = GetMaxSuggestionsCount();
341 if (static_cast<int>(cached_offline_page_downloads_.size()) < 360 if (static_cast<int>(cached_offline_page_downloads_.size()) <
342 max_suggestions_count) { 361 max_suggestions_count) {
343 cached_offline_page_downloads_.push_back(added_page); 362 cached_offline_page_downloads_.push_back(added_page);
344 } else if (max_suggestions_count > 0) { 363 } else if (max_suggestions_count > 0) {
345 auto oldest_page_iterator = 364 auto oldest_page_iterator =
346 std::max_element(cached_offline_page_downloads_.begin(), 365 std::max_element(cached_offline_page_downloads_.begin(),
347 cached_offline_page_downloads_.end(), 366 cached_offline_page_downloads_.end(),
348 &CompareOfflinePagesMostRecentlyCreatedFirst); 367 &CompareOfflinePagesMostRecentlyPublishedFirst);
349 *oldest_page_iterator = added_page; 368 *oldest_page_iterator = added_page;
350 } 369 }
351 370
352 SubmitContentSuggestions(); 371 SubmitContentSuggestions();
353 } 372 }
354 373
355 void DownloadSuggestionsProvider::OfflinePageDeleted( 374 void DownloadSuggestionsProvider::OfflinePageDeleted(
356 int64_t offline_id, 375 int64_t offline_id,
357 const offline_pages::ClientId& client_id) { 376 const offline_pages::ClientId& client_id) {
358 DCHECK(offline_page_model_); 377 DCHECK(offline_page_model_);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 // we may need to retrieve all downloads, but |OnDownloadRemoved| is called 430 // we may need to retrieve all downloads, but |OnDownloadRemoved| is called
412 // before the download is removed from the list. 431 // before the download is removed from the list.
413 } 432 }
414 433
415 void DownloadSuggestionsProvider::OnDownloadDestroyed( 434 void DownloadSuggestionsProvider::OnDownloadDestroyed(
416 content::DownloadItem* item) { 435 content::DownloadItem* item) {
417 DCHECK(is_asset_downloads_initialization_complete_); 436 DCHECK(is_asset_downloads_initialization_complete_);
418 437
419 item->RemoveObserver(this); 438 item->RemoveObserver(this);
420 439
421 if (!IsDownloadCompleted(*item)) { 440 if (!IsAssetDownloadCompleted(*item)) {
422 return; 441 return;
423 } 442 }
424 // TODO(vitaliii): Implement a better way to clean up dismissed IDs (in case 443 // TODO(vitaliii): Implement a better way to clean up dismissed IDs (in case
425 // some calls are missed). 444 // some calls are missed).
426 InvalidateSuggestion(GetAssetDownloadPerCategoryID(item->GetId())); 445 InvalidateSuggestion(GetAssetDownloadPerCategoryID(item->GetId()));
427 } 446 }
428 447
429 void DownloadSuggestionsProvider::OnHistoryQueryComplete() { 448 void DownloadSuggestionsProvider::OnHistoryQueryComplete() {
430 is_asset_downloads_initialization_complete_ = true; 449 is_asset_downloads_initialization_complete_ = true;
431 if (download_manager_) { 450 if (download_manager_) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 std::vector<DownloadItem*> all_downloads; 504 std::vector<DownloadItem*> all_downloads;
486 download_manager_->GetAllDownloads(&all_downloads); 505 download_manager_->GetAllDownloads(&all_downloads);
487 std::set<std::string> old_dismissed_ids = ReadAssetDismissedIDsFromPrefs(); 506 std::set<std::string> old_dismissed_ids = ReadAssetDismissedIDsFromPrefs();
488 std::set<std::string> retained_dismissed_ids; 507 std::set<std::string> retained_dismissed_ids;
489 cached_asset_downloads_.clear(); 508 cached_asset_downloads_.clear();
490 for (DownloadItem* item : all_downloads) { 509 for (DownloadItem* item : all_downloads) {
491 std::string within_category_id = 510 std::string within_category_id =
492 GetAssetDownloadPerCategoryID(item->GetId()); 511 GetAssetDownloadPerCategoryID(item->GetId());
493 if (old_dismissed_ids.count(within_category_id)) { 512 if (old_dismissed_ids.count(within_category_id)) {
494 retained_dismissed_ids.insert(within_category_id); 513 retained_dismissed_ids.insert(within_category_id);
495 } else if (IsDownloadCompleted(*item)) { 514 } else if (IsAssetDownloadCompleted(*item) &&
515 !IsDownloadOld(GetAssetDownloadPublishedTime(*item))) {
496 cached_asset_downloads_.push_back(item); 516 cached_asset_downloads_.push_back(item);
497 // We may already observe this item and, therefore, we remove the 517 // We may already observe this item and, therefore, we remove the
498 // observer first. 518 // observer first.
499 item->RemoveObserver(this); 519 item->RemoveObserver(this);
500 item->AddObserver(this); 520 item->AddObserver(this);
501 } 521 }
502 } 522 }
503 523
504 if (old_dismissed_ids.size() != retained_dismissed_ids.size()) { 524 if (old_dismissed_ids.size() != retained_dismissed_ids.size()) {
505 StoreAssetDismissedIDsToPrefs(retained_dismissed_ids); 525 StoreAssetDismissedIDsToPrefs(retained_dismissed_ids);
506 } 526 }
507 527
508 const int max_suggestions_count = GetMaxSuggestionsCount(); 528 const int max_suggestions_count = GetMaxSuggestionsCount();
509 if (static_cast<int>(cached_asset_downloads_.size()) > 529 if (static_cast<int>(cached_asset_downloads_.size()) >
510 max_suggestions_count) { 530 max_suggestions_count) {
511 // Partially sorts |downloads| such that: 531 // Partially sorts |downloads| such that:
512 // 1) The element at the index |max_suggestions_count| is changed to the 532 // 1) The element at the index |max_suggestions_count| is changed to the
513 // element which would occur on this position if |downloads| was sorted; 533 // element which would occur on this position if |downloads| was sorted;
514 // 2) All of the elements before index |max_suggestions_count| are less than 534 // 2) All of the elements before index |max_suggestions_count| are less than
515 // or equal to the elements after it. 535 // or equal to the elements after it.
516 std::nth_element(cached_asset_downloads_.begin(), 536 std::nth_element(cached_asset_downloads_.begin(),
517 cached_asset_downloads_.begin() + max_suggestions_count, 537 cached_asset_downloads_.begin() + max_suggestions_count,
518 cached_asset_downloads_.end(), 538 cached_asset_downloads_.end(),
519 &CompareDownloadsMostRecentlyDownloadedFirst); 539 &CompareDownloadsMostRecentlyPublishedFirst);
520 cached_asset_downloads_.resize(max_suggestions_count); 540 cached_asset_downloads_.resize(max_suggestions_count);
521 } 541 }
522 } 542 }
523 543
524 void DownloadSuggestionsProvider:: 544 void DownloadSuggestionsProvider::
525 AsynchronouslyFetchAllDownloadsAndSubmitSuggestions() { 545 AsynchronouslyFetchAllDownloadsAndSubmitSuggestions() {
526 FetchAssetsDownloads(); 546 FetchAssetsDownloads();
527 AsynchronouslyFetchOfflinePagesDownloads(/*notify=*/true); 547 AsynchronouslyFetchOfflinePagesDownloads(/*notify=*/true);
528 } 548 }
529 549
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 offline_page.offline_id)), 581 offline_page.offline_id)),
562 offline_page.url); 582 offline_page.url);
563 583
564 if (offline_page.title.empty()) { 584 if (offline_page.title.empty()) {
565 // TODO(vitaliii): Remove this fallback once the OfflinePageModel provides 585 // TODO(vitaliii): Remove this fallback once the OfflinePageModel provides
566 // titles for all (relevant) OfflinePageItems. 586 // titles for all (relevant) OfflinePageItems.
567 suggestion.set_title(base::UTF8ToUTF16(offline_page.url.spec())); 587 suggestion.set_title(base::UTF8ToUTF16(offline_page.url.spec()));
568 } else { 588 } else {
569 suggestion.set_title(offline_page.title); 589 suggestion.set_title(offline_page.title);
570 } 590 }
571 suggestion.set_publish_date(offline_page.creation_time); 591 suggestion.set_publish_date(GetOfflinePagePublishedTime(offline_page));
572 suggestion.set_publisher_name(base::UTF8ToUTF16(offline_page.url.host())); 592 suggestion.set_publisher_name(base::UTF8ToUTF16(offline_page.url.host()));
573 auto extra = base::MakeUnique<ntp_snippets::DownloadSuggestionExtra>(); 593 auto extra = base::MakeUnique<ntp_snippets::DownloadSuggestionExtra>();
574 extra->is_download_asset = false; 594 extra->is_download_asset = false;
575 extra->offline_page_id = offline_page.offline_id; 595 extra->offline_page_id = offline_page.offline_id;
576 suggestion.set_download_suggestion_extra(std::move(extra)); 596 suggestion.set_download_suggestion_extra(std::move(extra));
577 return suggestion; 597 return suggestion;
578 } 598 }
579 599
580 ContentSuggestion DownloadSuggestionsProvider::ConvertDownloadItem( 600 ContentSuggestion DownloadSuggestionsProvider::ConvertDownloadItem(
581 const DownloadItem& download_item) const { 601 const DownloadItem& download_item) const {
582 ContentSuggestion suggestion( 602 ContentSuggestion suggestion(
583 ContentSuggestion::ID(provided_category_, GetAssetDownloadPerCategoryID( 603 ContentSuggestion::ID(provided_category_, GetAssetDownloadPerCategoryID(
584 download_item.GetId())), 604 download_item.GetId())),
585 download_item.GetOriginalUrl()); 605 download_item.GetOriginalUrl());
586 suggestion.set_title( 606 suggestion.set_title(
587 download_item.GetTargetFilePath().BaseName().LossyDisplayName()); 607 download_item.GetTargetFilePath().BaseName().LossyDisplayName());
588 suggestion.set_publish_date(GetAssetDownloadPublishedTime(download_item)); 608 suggestion.set_publish_date(GetAssetDownloadPublishedTime(download_item));
589 suggestion.set_publisher_name( 609 suggestion.set_publisher_name(
590 base::UTF8ToUTF16(download_item.GetURL().host())); 610 base::UTF8ToUTF16(download_item.GetURL().host()));
591 auto extra = base::MakeUnique<ntp_snippets::DownloadSuggestionExtra>(); 611 auto extra = base::MakeUnique<ntp_snippets::DownloadSuggestionExtra>();
592 extra->target_file_path = download_item.GetTargetFilePath(); 612 extra->target_file_path = download_item.GetTargetFilePath();
593 extra->mime_type = download_item.GetMimeType(); 613 extra->mime_type = download_item.GetMimeType();
594 extra->is_download_asset = true; 614 extra->is_download_asset = true;
595 suggestion.set_download_suggestion_extra(std::move(extra)); 615 suggestion.set_download_suggestion_extra(std::move(extra));
596 return suggestion; 616 return suggestion;
597 } 617 }
598 618
619 bool DownloadSuggestionsProvider::IsDownloadOld(
620 const base::Time& published_time) {
621 // TODO(vitaliii): Also consider last access time here once it is collected
622 // for asset downloads.
623 return published_time <
624 clock_->Now() - base::TimeDelta::FromDays(GetMaxDownloadAgeDays());
625 }
626
599 bool DownloadSuggestionsProvider::CacheAssetDownloadIfNeeded( 627 bool DownloadSuggestionsProvider::CacheAssetDownloadIfNeeded(
600 const content::DownloadItem* item) { 628 const content::DownloadItem* item) {
601 if (!IsDownloadCompleted(*item)) { 629 if (!IsAssetDownloadCompleted(*item)) {
602 return false; 630 return false;
603 } 631 }
604 632
605 if (base::ContainsValue(cached_asset_downloads_, item)) { 633 if (base::ContainsValue(cached_asset_downloads_, item)) {
606 return false; 634 return false;
607 } 635 }
608 636
609 std::set<std::string> dismissed_ids = ReadAssetDismissedIDsFromPrefs(); 637 std::set<std::string> dismissed_ids = ReadAssetDismissedIDsFromPrefs();
610 if (dismissed_ids.count(GetAssetDownloadPerCategoryID(item->GetId()))) { 638 if (dismissed_ids.count(GetAssetDownloadPerCategoryID(item->GetId()))) {
611 return false; 639 return false;
612 } 640 }
613 641
614 DCHECK_LE(static_cast<int>(cached_asset_downloads_.size()), 642 DCHECK_LE(static_cast<int>(cached_asset_downloads_.size()),
615 GetMaxSuggestionsCount()); 643 GetMaxSuggestionsCount());
616 if (static_cast<int>(cached_asset_downloads_.size()) == 644 if (static_cast<int>(cached_asset_downloads_.size()) ==
617 GetMaxSuggestionsCount()) { 645 GetMaxSuggestionsCount()) {
618 auto oldest = std::max_element( 646 auto oldest = std::max_element(cached_asset_downloads_.begin(),
619 cached_asset_downloads_.begin(), cached_asset_downloads_.end(), 647 cached_asset_downloads_.end(),
620 &CompareDownloadsMostRecentlyDownloadedFirst); 648 &CompareDownloadsMostRecentlyPublishedFirst);
621 if (GetAssetDownloadPublishedTime(*item) <= 649 if (GetAssetDownloadPublishedTime(*item) <=
622 GetAssetDownloadPublishedTime(**oldest)) { 650 GetAssetDownloadPublishedTime(**oldest)) {
623 return false; 651 return false;
624 } 652 }
625 653
626 *oldest = item; 654 *oldest = item;
627 } else { 655 } else {
628 cached_asset_downloads_.push_back(item); 656 cached_asset_downloads_.push_back(item);
629 } 657 }
630 658
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
697 DCHECK(!offline_page_model_ || offline_page_model_->is_loaded()); 725 DCHECK(!offline_page_model_ || offline_page_model_->is_loaded());
698 726
699 std::set<std::string> old_dismissed_ids = 727 std::set<std::string> old_dismissed_ids =
700 ReadOfflinePageDismissedIDsFromPrefs(); 728 ReadOfflinePageDismissedIDsFromPrefs();
701 std::set<std::string> retained_dismissed_ids; 729 std::set<std::string> retained_dismissed_ids;
702 std::vector<const OfflinePageItem*> items; 730 std::vector<const OfflinePageItem*> items;
703 // Filtering out dismissed items and pruning dismissed IDs. 731 // Filtering out dismissed items and pruning dismissed IDs.
704 for (const OfflinePageItem& item : all_download_offline_pages) { 732 for (const OfflinePageItem& item : all_download_offline_pages) {
705 std::string id_within_category = 733 std::string id_within_category =
706 GetOfflinePagePerCategoryID(item.offline_id); 734 GetOfflinePagePerCategoryID(item.offline_id);
707 if (!old_dismissed_ids.count(id_within_category)) { 735 if (!old_dismissed_ids.count(id_within_category)) {
tschumann 2017/02/02 14:30:33 nit: It's now harder to get the context of the the
vitaliii 2017/02/07 10:26:05 Done. I've inversed the outer |if|.
708 items.push_back(&item); 736 if (!IsDownloadOld(GetOfflinePagePublishedTime(item))) {
vitaliii 2017/02/02 14:06:55 tschumann@, do we want to use last access time for
tschumann 2017/02/02 14:30:33 i'm fine doing this in one CL.
vitaliii 2017/02/07 10:26:05 Acknowledged.
737 items.push_back(&item);
738 }
709 } else { 739 } else {
710 retained_dismissed_ids.insert(id_within_category); 740 retained_dismissed_ids.insert(id_within_category);
711 } 741 }
712 } 742 }
713 743
714 const int max_suggestions_count = GetMaxSuggestionsCount(); 744 const int max_suggestions_count = GetMaxSuggestionsCount();
715 if (static_cast<int>(items.size()) > max_suggestions_count) { 745 if (static_cast<int>(items.size()) > max_suggestions_count) {
716 // Partially sorts |items| such that: 746 // Partially sorts |items| such that:
717 // 1) The element at the index |max_suggestions_count| is changed to the 747 // 1) The element at the index |max_suggestions_count| is changed to the
718 // element which would occur on this position if |items| was sorted; 748 // element which would occur on this position if |items| was sorted;
719 // 2) All of the elements before index |max_suggestions_count| are less than 749 // 2) All of the elements before index |max_suggestions_count| are less than
720 // or equal to the elements after it. 750 // or equal to the elements after it.
721 std::nth_element( 751 std::nth_element(
722 items.begin(), items.begin() + max_suggestions_count, items.end(), 752 items.begin(), items.begin() + max_suggestions_count, items.end(),
723 [](const OfflinePageItem* left, const OfflinePageItem* right) { 753 [](const OfflinePageItem* left, const OfflinePageItem* right) {
724 return CompareOfflinePagesMostRecentlyCreatedFirst(*left, *right); 754 return CompareOfflinePagesMostRecentlyPublishedFirst(*left, *right);
725 }); 755 });
726 items.resize(max_suggestions_count); 756 items.resize(max_suggestions_count);
727 } 757 }
728 758
729 cached_offline_page_downloads_.clear(); 759 cached_offline_page_downloads_.clear();
730 for (const OfflinePageItem* item : items) { 760 for (const OfflinePageItem* item : items) {
731 cached_offline_page_downloads_.push_back(*item); 761 cached_offline_page_downloads_.push_back(*item);
732 } 762 }
733 763
734 if (old_dismissed_ids.size() != retained_dismissed_ids.size()) { 764 if (old_dismissed_ids.size() != retained_dismissed_ids.size()) {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
809 void DownloadSuggestionsProvider::UnregisterDownloadItemObservers() { 839 void DownloadSuggestionsProvider::UnregisterDownloadItemObservers() {
810 DCHECK_NE(download_manager_, nullptr); 840 DCHECK_NE(download_manager_, nullptr);
811 841
812 std::vector<DownloadItem*> all_downloads; 842 std::vector<DownloadItem*> all_downloads;
813 download_manager_->GetAllDownloads(&all_downloads); 843 download_manager_->GetAllDownloads(&all_downloads);
814 844
815 for (DownloadItem* item : all_downloads) { 845 for (DownloadItem* item : all_downloads) {
816 item->RemoveObserver(this); 846 item->RemoveObserver(this);
817 } 847 }
818 } 848 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698