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

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

Issue 2562073002: [NTP::Downloads] Limit number of dismissed IDs instead of pruning. (Closed)
Patch Set: rebase & treib@ comments. Created 4 years 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/time.h" 19 #include "base/time/time.h"
20 #include "base/values.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
33 using base::ContainsValue;
32 using content::DownloadItem; 34 using content::DownloadItem;
33 using content::DownloadManager; 35 using content::DownloadManager;
34 using ntp_snippets::Category; 36 using ntp_snippets::Category;
35 using ntp_snippets::CategoryInfo; 37 using ntp_snippets::CategoryInfo;
36 using ntp_snippets::CategoryStatus; 38 using ntp_snippets::CategoryStatus;
37 using ntp_snippets::ContentSuggestion; 39 using ntp_snippets::ContentSuggestion;
38 using ntp_snippets::prefs::kDismissedAssetDownloadSuggestions; 40 using ntp_snippets::prefs::kDismissedAssetDownloadSuggestions;
39 using ntp_snippets::prefs::kDismissedOfflinePageDownloadSuggestions; 41 using ntp_snippets::prefs::kDismissedOfflinePageDownloadSuggestions;
40 using offline_pages::OfflinePageItem; 42 using offline_pages::OfflinePageItem;
41 using offline_pages::OfflinePageModelQuery; 43 using offline_pages::OfflinePageModelQuery;
42 using offline_pages::OfflinePageModelQueryBuilder; 44 using offline_pages::OfflinePageModelQueryBuilder;
43 45
44 namespace { 46 namespace {
45 47
46 const int kDefaultMaxSuggestionsCount = 5; 48 const int kDefaultMaxSuggestionsCount = 5;
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";
51 53
54 // Maximal number of dismissed asset download IDs stored at any time.
55 const int kMaxDismissedIdCount = 100;
56
52 bool CompareOfflinePagesMostRecentlyCreatedFirst(const OfflinePageItem& left, 57 bool CompareOfflinePagesMostRecentlyCreatedFirst(const OfflinePageItem& left,
53 const OfflinePageItem& right) { 58 const OfflinePageItem& right) {
54 return left.creation_time > right.creation_time; 59 return left.creation_time > right.creation_time;
55 } 60 }
56 61
57 int GetMaxSuggestionsCount() { 62 int GetMaxSuggestionsCount() {
58 bool assets_enabled = 63 bool assets_enabled =
59 base::FeatureList::IsEnabled(features::kAssetDownloadSuggestionsFeature); 64 base::FeatureList::IsEnabled(features::kAssetDownloadSuggestionsFeature);
60 return variations::GetVariationParamByFeatureAsInt( 65 return variations::GetVariationParamByFeatureAsInt(
61 assets_enabled ? features::kAssetDownloadSuggestionsFeature 66 assets_enabled ? features::kAssetDownloadSuggestionsFeature
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
179 /*has_more_action=*/false, 184 /*has_more_action=*/false,
180 /*has_reload_action=*/false, 185 /*has_reload_action=*/false,
181 /*has_view_all_action=*/download_manager_ui_enabled_, 186 /*has_view_all_action=*/download_manager_ui_enabled_,
182 /*show_if_empty=*/false, 187 /*show_if_empty=*/false,
183 l10n_util::GetStringUTF16(IDS_NTP_DOWNLOADS_SUGGESTIONS_SECTION_EMPTY)); 188 l10n_util::GetStringUTF16(IDS_NTP_DOWNLOADS_SUGGESTIONS_SECTION_EMPTY));
184 } 189 }
185 190
186 void DownloadSuggestionsProvider::DismissSuggestion( 191 void DownloadSuggestionsProvider::DismissSuggestion(
187 const ContentSuggestion::ID& suggestion_id) { 192 const ContentSuggestion::ID& suggestion_id) {
188 DCHECK_EQ(provided_category_, suggestion_id.category()); 193 DCHECK_EQ(provided_category_, suggestion_id.category());
189 std::set<std::string> dismissed_ids =
190 ReadDismissedIDsFromPrefs(CorrespondsToOfflinePage(suggestion_id));
191 dismissed_ids.insert(suggestion_id.id_within_category());
192 StoreDismissedIDsToPrefs(CorrespondsToOfflinePage(suggestion_id),
193 dismissed_ids);
194 194
195 AddToDismissedStorageIfNeeded(suggestion_id);
195 RemoveSuggestionFromCacheAndRetrieveMoreIfNeeded(suggestion_id); 196 RemoveSuggestionFromCacheAndRetrieveMoreIfNeeded(suggestion_id);
196 } 197 }
197 198
198 void DownloadSuggestionsProvider::FetchSuggestionImage( 199 void DownloadSuggestionsProvider::FetchSuggestionImage(
199 const ContentSuggestion::ID& suggestion_id, 200 const ContentSuggestion::ID& suggestion_id,
200 const ntp_snippets::ImageFetchedCallback& callback) { 201 const ntp_snippets::ImageFetchedCallback& callback) {
201 // TODO(vitaliii): Fetch proper thumbnail from OfflinePageModel once it is 202 // TODO(vitaliii): Fetch proper thumbnail from OfflinePageModel once it is
202 // available there. 203 // available there.
203 // TODO(vitaliii): Provide site's favicon for assets downloads or file type. 204 // TODO(vitaliii): Provide site's favicon for assets downloads or file type.
204 // See crbug.com/631447. 205 // See crbug.com/631447.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 weak_ptr_factory_.GetWeakPtr(), callback)); 256 weak_ptr_factory_.GetWeakPtr(), callback));
256 } else { 257 } else {
257 GetPagesMatchingQueryCallbackForGetDismissedSuggestions( 258 GetPagesMatchingQueryCallbackForGetDismissedSuggestions(
258 callback, std::vector<OfflinePageItem>()); 259 callback, std::vector<OfflinePageItem>());
259 } 260 }
260 } 261 }
261 262
262 void DownloadSuggestionsProvider::ClearDismissedSuggestionsForDebugging( 263 void DownloadSuggestionsProvider::ClearDismissedSuggestionsForDebugging(
263 Category category) { 264 Category category) {
264 DCHECK_EQ(provided_category_, category); 265 DCHECK_EQ(provided_category_, category);
265 StoreAssetDismissedIDsToPrefs(std::set<std::string>()); 266 StoreAssetDismissedIDsToPrefs(std::vector<std::string>());
266 StoreOfflinePageDismissedIDsToPrefs(std::set<std::string>()); 267 StoreOfflinePageDismissedIDsToPrefs(std::set<std::string>());
267 AsynchronouslyFetchAllDownloadsAndSubmitSuggestions(); 268 AsynchronouslyFetchAllDownloadsAndSubmitSuggestions();
268 } 269 }
269 270
270 // static 271 // static
271 void DownloadSuggestionsProvider::RegisterProfilePrefs( 272 void DownloadSuggestionsProvider::RegisterProfilePrefs(
272 PrefRegistrySimple* registry) { 273 PrefRegistrySimple* registry) {
273 registry->RegisterListPref(kDismissedAssetDownloadSuggestions); 274 registry->RegisterListPref(kDismissedAssetDownloadSuggestions);
274 registry->RegisterListPref(kDismissedOfflinePageDownloadSuggestions); 275 registry->RegisterListPref(kDismissedOfflinePageDownloadSuggestions);
275 } 276 }
276 277
278 int DownloadSuggestionsProvider::GetMaxDismissedCountForTesting() {
279 return kMaxDismissedIdCount;
280 }
281
277 //////////////////////////////////////////////////////////////////////////////// 282 ////////////////////////////////////////////////////////////////////////////////
278 // Private methods 283 // Private methods
279 284
280 void DownloadSuggestionsProvider:: 285 void DownloadSuggestionsProvider::
281 GetPagesMatchingQueryCallbackForGetDismissedSuggestions( 286 GetPagesMatchingQueryCallbackForGetDismissedSuggestions(
282 const ntp_snippets::DismissedSuggestionsCallback& callback, 287 const ntp_snippets::DismissedSuggestionsCallback& callback,
283 const std::vector<OfflinePageItem>& offline_pages) const { 288 const std::vector<OfflinePageItem>& offline_pages) const {
284 std::set<std::string> dismissed_ids = ReadOfflinePageDismissedIDsFromPrefs(); 289 std::set<std::string> dismissed_offline_ids =
290 ReadOfflinePageDismissedIDsFromPrefs();
285 std::vector<ContentSuggestion> suggestions; 291 std::vector<ContentSuggestion> suggestions;
286 for (const OfflinePageItem& item : offline_pages) { 292 for (const OfflinePageItem& item : offline_pages) {
287 if (dismissed_ids.count(GetOfflinePagePerCategoryID(item.offline_id))) { 293 if (dismissed_offline_ids.count(
294 GetOfflinePagePerCategoryID(item.offline_id))) {
288 suggestions.push_back(ConvertOfflinePage(item)); 295 suggestions.push_back(ConvertOfflinePage(item));
289 } 296 }
290 } 297 }
291 298
292 if (download_manager_) { 299 if (download_manager_) {
293 std::vector<DownloadItem*> all_downloads; 300 std::vector<DownloadItem*> all_downloads;
294 download_manager_->GetAllDownloads(&all_downloads); 301 download_manager_->GetAllDownloads(&all_downloads);
295 302
296 dismissed_ids = ReadAssetDismissedIDsFromPrefs(); 303 std::vector<std::string> dismissed_asset_ids =
304 ReadAssetDismissedIDsFromPrefs();
297 305
298 for (const DownloadItem* item : all_downloads) { 306 for (const DownloadItem* item : all_downloads) {
299 if (dismissed_ids.count(GetAssetDownloadPerCategoryID(item->GetId()))) { 307 if (ContainsValue(dismissed_asset_ids,
308 GetAssetDownloadPerCategoryID(item->GetId()))) {
300 suggestions.push_back(ConvertDownloadItem(*item)); 309 suggestions.push_back(ConvertDownloadItem(*item));
301 } 310 }
302 } 311 }
303 } 312 }
304 313
305 callback.Run(std::move(suggestions)); 314 callback.Run(std::move(suggestions));
306 } 315 }
307 316
308 void DownloadSuggestionsProvider::OfflinePageModelLoaded( 317 void DownloadSuggestionsProvider::OfflinePageModelLoaded(
309 offline_pages::OfflinePageModel* model) { 318 offline_pages::OfflinePageModel* model) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 } 371 }
363 } 372 }
364 373
365 void DownloadSuggestionsProvider::ManagerGoingDown(DownloadManager* manager) { 374 void DownloadSuggestionsProvider::ManagerGoingDown(DownloadManager* manager) {
366 DCHECK_EQ(download_manager_, manager); 375 DCHECK_EQ(download_manager_, manager);
367 UnregisterDownloadItemObservers(); 376 UnregisterDownloadItemObservers();
368 download_manager_ = nullptr; 377 download_manager_ = nullptr;
369 } 378 }
370 379
371 void DownloadSuggestionsProvider::OnDownloadUpdated(DownloadItem* item) { 380 void DownloadSuggestionsProvider::OnDownloadUpdated(DownloadItem* item) {
372 if (base::ContainsValue(cached_asset_downloads_, item)) { 381 if (ContainsValue(cached_asset_downloads_, item)) {
373 if (item->GetFileExternallyRemoved()) { 382 if (item->GetFileExternallyRemoved()) {
374 InvalidateSuggestion(GetAssetDownloadPerCategoryID(item->GetId())); 383 InvalidateSuggestion(GetAssetDownloadPerCategoryID(item->GetId()));
375 } else { 384 } else {
376 // The download may have changed. 385 // The download may have changed.
377 SubmitContentSuggestions(); 386 SubmitContentSuggestions();
378 } 387 }
379 } else { 388 } else {
380 // Unfinished downloads may become completed. 389 // Unfinished downloads may become completed.
381 if (CacheAssetDownloadIfNeeded(item)) { 390 if (CacheAssetDownloadIfNeeded(item)) {
382 SubmitContentSuggestions(); 391 SubmitContentSuggestions();
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 } 452 }
444 453
445 void DownloadSuggestionsProvider::FetchAssetsDownloads() { 454 void DownloadSuggestionsProvider::FetchAssetsDownloads() {
446 if (!download_manager_) { 455 if (!download_manager_) {
447 // The manager has gone down or was explicitly turned off. 456 // The manager has gone down or was explicitly turned off.
448 return; 457 return;
449 } 458 }
450 459
451 std::vector<DownloadItem*> all_downloads; 460 std::vector<DownloadItem*> all_downloads;
452 download_manager_->GetAllDownloads(&all_downloads); 461 download_manager_->GetAllDownloads(&all_downloads);
453 std::set<std::string> old_dismissed_ids = ReadAssetDismissedIDsFromPrefs(); 462 std::vector<std::string> old_dismissed_ids = ReadAssetDismissedIDsFromPrefs();
454 std::set<std::string> retained_dismissed_ids;
455 cached_asset_downloads_.clear(); 463 cached_asset_downloads_.clear();
456 for (const DownloadItem* item : all_downloads) { 464 for (const DownloadItem* item : all_downloads) {
457 std::string within_category_id = 465 std::string within_category_id =
458 GetAssetDownloadPerCategoryID(item->GetId()); 466 GetAssetDownloadPerCategoryID(item->GetId());
459 if (!old_dismissed_ids.count(within_category_id)) { 467 if (!ContainsValue(old_dismissed_ids, within_category_id)) {
460 if (IsDownloadCompleted(*item)) { 468 if (IsDownloadCompleted(*item)) {
461 cached_asset_downloads_.push_back(item); 469 cached_asset_downloads_.push_back(item);
462 } 470 }
463 } else {
464 retained_dismissed_ids.insert(within_category_id);
465 } 471 }
466 } 472 }
467 473
468 if (old_dismissed_ids.size() != retained_dismissed_ids.size()) { 474 // We do not prune dismissed IDs, because it is not possible to ensure that
469 StoreAssetDismissedIDsToPrefs(retained_dismissed_ids); 475 // the list of downloads is complete (i.e. DownloadManager has finished
470 } 476 // reading them).
471 477 // TODO(vitaliii): Prune dismissed IDs once the |OnLoaded| notification is
478 // provided. See crbug.com/672758.
472 const int max_suggestions_count = GetMaxSuggestionsCount(); 479 const int max_suggestions_count = GetMaxSuggestionsCount();
473 if (static_cast<int>(cached_asset_downloads_.size()) > 480 if (static_cast<int>(cached_asset_downloads_.size()) >
474 max_suggestions_count) { 481 max_suggestions_count) {
475 // Partially sorts |downloads| such that: 482 // Partially sorts |downloads| such that:
476 // 1) The element at the index |max_suggestions_count| is changed to the 483 // 1) The element at the index |max_suggestions_count| is changed to the
477 // element which would occur on this position if |downloads| was sorted; 484 // element which would occur on this position if |downloads| was sorted;
478 // 2) All of the elements before index |max_suggestions_count| are less than 485 // 2) All of the elements before index |max_suggestions_count| are less than
479 // or equal to the elements after it. 486 // or equal to the elements after it.
480 std::nth_element(cached_asset_downloads_.begin(), 487 std::nth_element(cached_asset_downloads_.begin(),
481 cached_asset_downloads_.begin() + max_suggestions_count, 488 cached_asset_downloads_.begin() + max_suggestions_count,
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 suggestion.set_download_suggestion_extra(std::move(extra)); 566 suggestion.set_download_suggestion_extra(std::move(extra));
560 return suggestion; 567 return suggestion;
561 } 568 }
562 569
563 bool DownloadSuggestionsProvider::CacheAssetDownloadIfNeeded( 570 bool DownloadSuggestionsProvider::CacheAssetDownloadIfNeeded(
564 const content::DownloadItem* item) { 571 const content::DownloadItem* item) {
565 if (!IsDownloadCompleted(*item)) { 572 if (!IsDownloadCompleted(*item)) {
566 return false; 573 return false;
567 } 574 }
568 575
569 if (base::ContainsValue(cached_asset_downloads_, item)) { 576 if (ContainsValue(cached_asset_downloads_, item)) {
570 return false; 577 return false;
571 } 578 }
572 579
573 std::set<std::string> dismissed_ids = ReadAssetDismissedIDsFromPrefs(); 580 std::vector<std::string> dismissed_ids = ReadAssetDismissedIDsFromPrefs();
574 if (dismissed_ids.count(GetAssetDownloadPerCategoryID(item->GetId()))) { 581 if (ContainsValue(dismissed_ids,
582 GetAssetDownloadPerCategoryID(item->GetId()))) {
575 return false; 583 return false;
576 } 584 }
577 585
578 DCHECK_LE(static_cast<int>(cached_asset_downloads_.size()), 586 DCHECK_LE(static_cast<int>(cached_asset_downloads_.size()),
579 GetMaxSuggestionsCount()); 587 GetMaxSuggestionsCount());
580 if (static_cast<int>(cached_asset_downloads_.size()) == 588 if (static_cast<int>(cached_asset_downloads_.size()) ==
581 GetMaxSuggestionsCount()) { 589 GetMaxSuggestionsCount()) {
582 auto oldest = std::max_element( 590 auto oldest = std::max_element(
583 cached_asset_downloads_.begin(), cached_asset_downloads_.end(), 591 cached_asset_downloads_.begin(), cached_asset_downloads_.end(),
584 &CompareDownloadsMostRecentlyDownloadedFirst); 592 &CompareDownloadsMostRecentlyDownloadedFirst);
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
702 if (notify) { 710 if (notify) {
703 SubmitContentSuggestions(); 711 SubmitContentSuggestions();
704 } 712 }
705 } 713 }
706 714
707 void DownloadSuggestionsProvider::InvalidateSuggestion( 715 void DownloadSuggestionsProvider::InvalidateSuggestion(
708 const std::string& id_within_category) { 716 const std::string& id_within_category) {
709 ContentSuggestion::ID suggestion_id(provided_category_, id_within_category); 717 ContentSuggestion::ID suggestion_id(provided_category_, id_within_category);
710 observer()->OnSuggestionInvalidated(this, suggestion_id); 718 observer()->OnSuggestionInvalidated(this, suggestion_id);
711 719
712 std::set<std::string> dismissed_ids = 720 RemoveFromDismissedStorageIfNeeded(suggestion_id);
713 ReadDismissedIDsFromPrefs(CorrespondsToOfflinePage(suggestion_id));
714 auto it = dismissed_ids.find(id_within_category);
715 if (it != dismissed_ids.end()) {
716 dismissed_ids.erase(it);
717 StoreDismissedIDsToPrefs(CorrespondsToOfflinePage(suggestion_id),
718 dismissed_ids);
719 }
720
721 RemoveSuggestionFromCacheAndRetrieveMoreIfNeeded(suggestion_id); 721 RemoveSuggestionFromCacheAndRetrieveMoreIfNeeded(suggestion_id);
722 } 722 }
723 723
724 std::set<std::string> 724 // TODO(vitaliii): Do not use std::vector, when we ensure that pruning happens
725 // at the right time (crbug.com/672758).
726 std::vector<std::string>
725 DownloadSuggestionsProvider::ReadAssetDismissedIDsFromPrefs() const { 727 DownloadSuggestionsProvider::ReadAssetDismissedIDsFromPrefs() const {
726 return ntp_snippets::prefs::ReadDismissedIDsFromPrefs( 728 std::vector<std::string> dismissed_ids;
727 *pref_service_, kDismissedAssetDownloadSuggestions); 729 const base::ListValue* list =
730 pref_service_->GetList(kDismissedAssetDownloadSuggestions);
731 for (const std::unique_ptr<base::Value>& value : *list) {
732 std::string dismissed_id;
733 bool success = value->GetAsString(&dismissed_id);
734 DCHECK(success) << "Failed to parse dismissed id from prefs param "
735 << kDismissedAssetDownloadSuggestions << " into string.";
736 dismissed_ids.push_back(dismissed_id);
737 }
738 return dismissed_ids;
728 } 739 }
729 740
730 void DownloadSuggestionsProvider::StoreAssetDismissedIDsToPrefs( 741 void DownloadSuggestionsProvider::StoreAssetDismissedIDsToPrefs(
731 const std::set<std::string>& dismissed_ids) { 742 const std::vector<std::string>& dismissed_ids) {
732 DCHECK(std::all_of( 743 DCHECK(std::all_of(
733 dismissed_ids.begin(), dismissed_ids.end(), 744 dismissed_ids.begin(), dismissed_ids.end(),
734 [](const std::string& id) { return id[0] == kAssetDownloadsPrefix; })); 745 [](const std::string& id) { return id[0] == kAssetDownloadsPrefix; }));
735 ntp_snippets::prefs::StoreDismissedIDsToPrefs( 746
736 pref_service_, kDismissedAssetDownloadSuggestions, dismissed_ids); 747 base::ListValue list;
748 for (const std::string& dismissed_id : dismissed_ids) {
749 list.AppendString(dismissed_id);
750 }
751 pref_service_->Set(kDismissedAssetDownloadSuggestions, list);
737 } 752 }
738 753
739 std::set<std::string> 754 std::set<std::string>
740 DownloadSuggestionsProvider::ReadOfflinePageDismissedIDsFromPrefs() const { 755 DownloadSuggestionsProvider::ReadOfflinePageDismissedIDsFromPrefs() const {
741 return ntp_snippets::prefs::ReadDismissedIDsFromPrefs( 756 return ntp_snippets::prefs::ReadDismissedIDsFromPrefs(
742 *pref_service_, kDismissedOfflinePageDownloadSuggestions); 757 *pref_service_, kDismissedOfflinePageDownloadSuggestions);
743 } 758 }
744 759
745 void DownloadSuggestionsProvider::StoreOfflinePageDismissedIDsToPrefs( 760 void DownloadSuggestionsProvider::StoreOfflinePageDismissedIDsToPrefs(
746 const std::set<std::string>& dismissed_ids) { 761 const std::set<std::string>& dismissed_ids) {
747 DCHECK(std::all_of(dismissed_ids.begin(), dismissed_ids.end(), 762 DCHECK(std::all_of(dismissed_ids.begin(), dismissed_ids.end(),
748 [](const std::string& id) { 763 [](const std::string& id) {
749 return id[0] == kOfflinePageDownloadsPrefix; 764 return id[0] == kOfflinePageDownloadsPrefix;
750 })); 765 }));
751 ntp_snippets::prefs::StoreDismissedIDsToPrefs( 766 ntp_snippets::prefs::StoreDismissedIDsToPrefs(
752 pref_service_, kDismissedOfflinePageDownloadSuggestions, dismissed_ids); 767 pref_service_, kDismissedOfflinePageDownloadSuggestions, dismissed_ids);
753 } 768 }
754 769
755 std::set<std::string> DownloadSuggestionsProvider::ReadDismissedIDsFromPrefs( 770 void DownloadSuggestionsProvider::AddToDismissedStorageIfNeeded(
756 bool for_offline_page_downloads) const { 771 const ContentSuggestion::ID& suggestion_id) {
757 if (for_offline_page_downloads) { 772 if (CorrespondsToOfflinePage(suggestion_id)) {
758 return ReadOfflinePageDismissedIDsFromPrefs(); 773 std::set<std::string> dismissed_ids =
759 } 774 ReadOfflinePageDismissedIDsFromPrefs();
760 return ReadAssetDismissedIDsFromPrefs(); 775 dismissed_ids.insert(suggestion_id.id_within_category());
761 }
762
763 // TODO(vitaliii): Store one set instead of two. See crbug.com/656024.
764 void DownloadSuggestionsProvider::StoreDismissedIDsToPrefs(
765 bool for_offline_page_downloads,
766 const std::set<std::string>& dismissed_ids) {
767 if (for_offline_page_downloads) {
768 StoreOfflinePageDismissedIDsToPrefs(dismissed_ids); 776 StoreOfflinePageDismissedIDsToPrefs(dismissed_ids);
769 } else { 777 } else {
770 StoreAssetDismissedIDsToPrefs(dismissed_ids); 778 std::vector<std::string> dismissed_ids = ReadAssetDismissedIDsFromPrefs();
779 // The suggestion may be double dismissed from previously opened NTPs.
780 if (!ContainsValue(dismissed_ids, suggestion_id.id_within_category())) {
781 dismissed_ids.push_back(suggestion_id.id_within_category());
782 // TODO(vitaliii): Remove this workaround once the dismissed ids are
783 // pruned. See crbug.com/672758.
784 while (dismissed_ids.size() > kMaxDismissedIdCount) {
785 dismissed_ids.erase(dismissed_ids.begin());
786 }
787 StoreAssetDismissedIDsToPrefs(dismissed_ids);
788 }
771 } 789 }
772 } 790 }
773 791
792 void DownloadSuggestionsProvider::RemoveFromDismissedStorageIfNeeded(
793 const ContentSuggestion::ID& suggestion_id) {
794 if (CorrespondsToOfflinePage(suggestion_id)) {
795 std::set<std::string> dismissed_ids =
796 ReadOfflinePageDismissedIDsFromPrefs();
797 if (dismissed_ids.count(suggestion_id.id_within_category())) {
798 dismissed_ids.erase(suggestion_id.id_within_category());
799 StoreOfflinePageDismissedIDsToPrefs(dismissed_ids);
800 }
801 } else {
802 std::vector<std::string> dismissed_ids = ReadAssetDismissedIDsFromPrefs();
803 auto it = std::find(dismissed_ids.begin(), dismissed_ids.end(),
804 suggestion_id.id_within_category());
805 if (it != dismissed_ids.end()) {
806 dismissed_ids.erase(it);
807 StoreAssetDismissedIDsToPrefs(dismissed_ids);
808 }
809 }
810 }
811
774 void DownloadSuggestionsProvider::UnregisterDownloadItemObservers() { 812 void DownloadSuggestionsProvider::UnregisterDownloadItemObservers() {
775 DCHECK_NE(download_manager_, nullptr); 813 DCHECK_NE(download_manager_, nullptr);
776 814
777 std::vector<DownloadItem*> all_downloads; 815 std::vector<DownloadItem*> all_downloads;
778 download_manager_->GetAllDownloads(&all_downloads); 816 download_manager_->GetAllDownloads(&all_downloads);
779 817
780 for (DownloadItem* item : all_downloads) { 818 for (DownloadItem* item : all_downloads) {
781 item->RemoveObserver(this); 819 item->RemoveObserver(this);
782 } 820 }
783 } 821 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698