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

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

Powered by Google App Engine
This is Rietveld 408576698