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

Unified Diff: components/ntp_snippets/content_suggestions_service.cc

Issue 2406573002: 📰 Persist category dismissals (Closed)
Patch Set: fix nits Created 4 years, 2 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 side-by-side diff with in-line comments
Download patch
Index: components/ntp_snippets/content_suggestions_service.cc
diff --git a/components/ntp_snippets/content_suggestions_service.cc b/components/ntp_snippets/content_suggestions_service.cc
index 56497a741f085725b8ad2b232d2c69e70fdf0cdf..58dd4333c6ad17dad2244882a60ef242d8394295 100644
--- a/components/ntp_snippets/content_suggestions_service.cc
+++ b/components/ntp_snippets/content_suggestions_service.cc
@@ -13,6 +13,10 @@
#include "base/location.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "base/values.h"
+#include "components/ntp_snippets/pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
#include "ui/gfx/image/image.h"
namespace ntp_snippets {
@@ -24,10 +28,13 @@ ContentSuggestionsService::ContentSuggestionsService(
: state_(state),
history_service_observer_(this),
ntp_snippets_service_(nullptr),
+ pref_service_(pref_service),
user_classifier_(pref_service) {
// Can be null in tests.
if (history_service)
history_service_observer_.Add(history_service);
+
+ RestoreDismissedCategoriesFromPrefs();
}
ContentSuggestionsService::~ContentSuggestionsService() = default;
@@ -42,6 +49,12 @@ void ContentSuggestionsService::Shutdown() {
FOR_EACH_OBSERVER(Observer, observers_, ContentSuggestionsServiceShutdown());
}
+// static
+void ContentSuggestionsService::RegisterProfilePrefs(
+ PrefRegistrySimple* registry) {
+ registry->RegisterListPref(prefs::kDismissedCategories);
+}
+
CategoryStatus ContentSuggestionsService::GetCategoryStatus(
Category category) const {
if (state_ == State::DISABLED) {
@@ -150,11 +163,11 @@ void ContentSuggestionsService::DismissCategory(Category category) {
if (providers_it == providers_by_category_.end())
return;
- suggestions_by_category_[category].clear();
- dismissed_providers_by_category_[providers_it->first] = providers_it->second;
- providers_by_category_.erase(providers_it);
- categories_.erase(
- std::find(categories_.begin(), categories_.end(), category));
+ ContentSuggestionsProvider* provider = providers_it->second;
+ UnregisterCategory(category, provider);
+
+ dismissed_providers_by_category_[category] = provider;
+ StoreDismissedCategoriesToPrefs();
}
void ContentSuggestionsService::RestoreDismissedCategories() {
@@ -162,9 +175,9 @@ void ContentSuggestionsService::RestoreDismissedCategories() {
auto dismissed_providers_by_category_copy = dismissed_providers_by_category_;
for (const auto& category_provider_pair :
dismissed_providers_by_category_copy) {
- RegisterCategoryIfRequired(category_provider_pair.second,
- category_provider_pair.first);
+ RestoreDismissedCategory(category_provider_pair.first);
}
+ StoreDismissedCategoriesToPrefs();
DCHECK(dismissed_providers_by_category_.empty());
}
@@ -189,8 +202,19 @@ void ContentSuggestionsService::OnNewSuggestions(
ContentSuggestionsProvider* provider,
Category category,
std::vector<ContentSuggestion> suggestions) {
- if (RegisterCategoryIfRequired(provider, category))
+ if (TryRegisterProviderForCategory(provider, category)) {
+ NotifyCategoryStatusChanged(category);
+ } else if (IsCategoryDismissed(category)) {
+ // The category has been registered as a dismissed one. We need to
+ // check if the dismissal can be cleared now that we received new data.
+ if (suggestions.empty())
+ return;
+
+ RestoreDismissedCategory(category);
+ StoreDismissedCategoriesToPrefs();
+
NotifyCategoryStatusChanged(category);
+ }
if (!IsCategoryStatusAvailable(provider->GetCategoryStatus(category))) {
// A provider shouldn't send us suggestions while it's not available.
@@ -212,19 +236,17 @@ void ContentSuggestionsService::OnCategoryStatusChanged(
ContentSuggestionsProvider* provider,
Category category,
CategoryStatus new_status) {
- if (!IsCategoryStatusAvailable(new_status)) {
- suggestions_by_category_.erase(category);
- }
if (new_status == CategoryStatus::NOT_PROVIDED) {
- DCHECK(providers_by_category_.find(category) !=
- providers_by_category_.end());
- DCHECK_EQ(provider, providers_by_category_.find(category)->second);
- DismissCategory(category);
+ UnregisterCategory(category, provider);
} else {
- RegisterCategoryIfRequired(provider, category);
+ if (!IsCategoryStatusAvailable(new_status))
+ suggestions_by_category_.erase(category);
+ TryRegisterProviderForCategory(provider, category);
DCHECK_EQ(new_status, provider->GetCategoryStatus(category));
}
- NotifyCategoryStatusChanged(category);
+
+ if (!IsCategoryDismissed(category))
+ NotifyCategoryStatusChanged(category);
}
void ContentSuggestionsService::OnSuggestionInvalidated(
@@ -281,7 +303,7 @@ void ContentSuggestionsService::HistoryServiceBeingDeleted(
history_service_observer_.RemoveAll();
}
-bool ContentSuggestionsService::RegisterCategoryIfRequired(
+bool ContentSuggestionsService::TryRegisterProviderForCategory(
ContentSuggestionsProvider* provider,
Category category) {
auto it = providers_by_category_.find(category);
@@ -292,10 +314,27 @@ bool ContentSuggestionsService::RegisterCategoryIfRequired(
auto dismissed_it = dismissed_providers_by_category_.find(category);
if (dismissed_it != dismissed_providers_by_category_.end()) {
- DCHECK_EQ(dismissed_it->second, provider);
- dismissed_providers_by_category_.erase(dismissed_it);
+ // The initialisation of dismissed categories registers them with |nullptr|
+ // for providers, we need to check for that to see if the provider is
+ // already registered or not.
+ if (!dismissed_it->second) {
+ dismissed_it->second = provider;
+ } else {
+ DCHECK_EQ(dismissed_it->second, provider);
+ }
+ return false;
}
+ RegisterCategory(category, provider);
+ return true;
+}
+
+void ContentSuggestionsService::RegisterCategory(
+ Category category,
+ ContentSuggestionsProvider* provider) {
+ DCHECK(!base::ContainsKey(providers_by_category_, category));
+ DCHECK(!IsCategoryDismissed(category));
+
providers_by_category_[category] = provider;
categories_.push_back(category);
SortCategories();
@@ -303,7 +342,22 @@ bool ContentSuggestionsService::RegisterCategoryIfRequired(
suggestions_by_category_.insert(
std::make_pair(category, std::vector<ContentSuggestion>()));
}
- return true;
+}
+
+void ContentSuggestionsService::UnregisterCategory(
+ Category category,
+ ContentSuggestionsProvider* provider) {
+ auto providers_it = providers_by_category_.find(category);
+ if (providers_it == providers_by_category_.end()) {
+ DCHECK(IsCategoryDismissed(category));
+ return;
+ }
+
+ DCHECK_EQ(provider, providers_it->second);
+ providers_by_category_.erase(providers_it);
+ categories_.erase(
+ std::find(categories_.begin(), categories_.end(), category));
+ suggestions_by_category_.erase(category);
}
bool ContentSuggestionsService::RemoveSuggestionByID(
@@ -353,4 +407,50 @@ void ContentSuggestionsService::SortCategories() {
});
}
+bool ContentSuggestionsService::IsCategoryDismissed(Category category) const {
+ return base::ContainsKey(dismissed_providers_by_category_, category);
+}
+
+void ContentSuggestionsService::RestoreDismissedCategory(Category category) {
+ auto dismissed_it = dismissed_providers_by_category_.find(category);
+ DCHECK(base::ContainsKey(dismissed_providers_by_category_, category));
+
+ // Keep the reference to the provider and remove it from the dismissed ones,
+ // because the category registration enforces that it's not dismissed.
+ ContentSuggestionsProvider* provider = dismissed_it->second;
+ dismissed_providers_by_category_.erase(dismissed_it);
+
+ if (provider)
+ RegisterCategory(category, provider);
+}
+
+void ContentSuggestionsService::RestoreDismissedCategoriesFromPrefs() {
+ // This must only be called at startup.
+ DCHECK(dismissed_providers_by_category_.empty());
+ DCHECK(providers_by_category_.empty());
+
+ const base::ListValue* list =
+ pref_service_->GetList(prefs::kDismissedCategories);
+ for (const std::unique_ptr<base::Value>& entry : *list) {
+ int id = 0;
+ if (!entry->GetAsInteger(&id)) {
+ DLOG(WARNING) << "Invalid category pref value: " << *entry;
+ continue;
+ }
+
+ // When the provider is registered, it will be stored in this map.
+ dismissed_providers_by_category_[category_factory()->FromIDValue(id)] =
+ nullptr;
+ }
+}
+
+void ContentSuggestionsService::StoreDismissedCategoriesToPrefs() {
+ base::ListValue list;
+ for (const auto& category_provider_pair : dismissed_providers_by_category_) {
+ list.AppendInteger(category_provider_pair.first.id());
+ }
+
+ pref_service_->Set(prefs::kDismissedCategories, list);
+}
+
} // namespace ntp_snippets
« no previous file with comments | « components/ntp_snippets/content_suggestions_service.h ('k') | components/ntp_snippets/content_suggestions_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698