1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/suggestions/blacklist_store.h"
10 #include "base/base64.h"
11 #include "base/metrics/histogram.h"
12 #include "base/prefs/pref_service.h"
13 #include "components/pref_registry/pref_registry_syncable.h"
14 #include "components/suggestions/suggestions_pref_names.h"
16 namespace suggestions
{
20 void PopulateBlacklistSet(const SuggestionsBlacklist
& blacklist_proto
,
21 std::set
<std::string
>* blacklist_set
) {
22 blacklist_set
->clear();
23 for (int i
= 0; i
< blacklist_proto
.urls_size(); ++i
) {
24 blacklist_set
->insert(blacklist_proto
.urls(i
));
28 void PopulateBlacklistProto(const std::set
<std::string
>& blacklist_set
,
29 SuggestionsBlacklist
* blacklist_proto
) {
30 blacklist_proto
->Clear();
31 for (std::set
<std::string
>::const_iterator it
= blacklist_set
.begin();
32 it
!= blacklist_set
.end(); ++it
) {
33 blacklist_proto
->add_urls(*it
);
39 BlacklistStore::BlacklistStore(PrefService
* profile_prefs
)
40 : pref_service_(profile_prefs
) {
41 DCHECK(pref_service_
);
43 // Log the blacklist's size. A single BlacklistStore is created for the
44 // SuggestionsService; this will run once.
45 SuggestionsBlacklist blacklist_proto
;
46 LoadBlacklist(&blacklist_proto
);
47 UMA_HISTOGRAM_COUNTS_10000("Suggestions.LocalBlacklistSize",
48 blacklist_proto
.urls_size());
51 BlacklistStore::~BlacklistStore() {}
53 bool BlacklistStore::BlacklistUrl(const GURL
& url
) {
54 if (!url
.is_valid()) return false;
56 SuggestionsBlacklist blacklist_proto
;
57 LoadBlacklist(&blacklist_proto
);
59 std::set
<std::string
> blacklist_set
;
60 PopulateBlacklistSet(blacklist_proto
, &blacklist_set
);
62 if (!blacklist_set
.insert(url
.spec()).second
) {
63 // |url| was already in the blacklist.
67 PopulateBlacklistProto(blacklist_set
, &blacklist_proto
);
68 return StoreBlacklist(blacklist_proto
);
71 bool BlacklistStore::GetFirstUrlFromBlacklist(GURL
* url
) {
72 SuggestionsBlacklist blacklist
;
73 LoadBlacklist(&blacklist
);
74 if (!blacklist
.urls_size()) return false;
75 GURL
blacklisted(blacklist
.urls(0));
76 url
->Swap(&blacklisted
);
80 bool BlacklistStore::RemoveUrl(const GURL
& url
) {
81 if (!url
.is_valid()) return false;
82 const std::string removal_candidate
= url
.spec();
84 SuggestionsBlacklist blacklist
;
85 LoadBlacklist(&blacklist
);
87 SuggestionsBlacklist updated_blacklist
;
88 for (int i
= 0; i
< blacklist
.urls_size(); ++i
) {
89 if (blacklist
.urls(i
) != removal_candidate
)
90 updated_blacklist
.add_urls(blacklist
.urls(i
));
93 return StoreBlacklist(updated_blacklist
);
96 void BlacklistStore::FilterSuggestions(SuggestionsProfile
* profile
) {
97 if (!profile
->suggestions_size())
98 return; // Empty profile, nothing to filter.
100 SuggestionsBlacklist blacklist_proto
;
101 if (!LoadBlacklist(&blacklist_proto
)) {
102 // There was an error loading the blacklist. The blacklist was cleared and
103 // there's nothing to be done about it.
106 if (!blacklist_proto
.urls_size())
107 return; // Empty blacklist, nothing to filter.
109 std::set
<std::string
> blacklist_set
;
110 PopulateBlacklistSet(blacklist_proto
, &blacklist_set
);
112 // Populate the filtered suggestions.
113 SuggestionsProfile filtered_profile
;
114 for (int i
= 0; i
< profile
->suggestions_size(); ++i
) {
115 if (blacklist_set
.find(profile
->suggestions(i
).url()) ==
116 blacklist_set
.end()) {
117 // This suggestion is not blacklisted.
118 ChromeSuggestion
* suggestion
= filtered_profile
.add_suggestions();
120 suggestion
->Swap(profile
->mutable_suggestions(i
));
124 // Swap |profile| and |filtered_profile|.
125 profile
->Swap(&filtered_profile
);
129 void BlacklistStore::RegisterProfilePrefs(
130 user_prefs::PrefRegistrySyncable
* registry
) {
131 registry
->RegisterStringPref(
132 prefs::kSuggestionsBlacklist
, std::string(),
133 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
136 bool BlacklistStore::LoadBlacklist(SuggestionsBlacklist
* blacklist
) {
139 const std::string base64_blacklist_data
=
140 pref_service_
->GetString(prefs::kSuggestionsBlacklist
);
141 if (base64_blacklist_data
.empty()) {
146 // If the decode process fails, assume the pref value is corrupt and clear it.
147 std::string blacklist_data
;
148 if (!base::Base64Decode(base64_blacklist_data
, &blacklist_data
) ||
149 !blacklist
->ParseFromString(blacklist_data
)) {
150 VLOG(1) << "Suggestions blacklist data in profile pref is corrupt, "
160 bool BlacklistStore::StoreBlacklist(const SuggestionsBlacklist
& blacklist
) {
161 std::string blacklist_data
;
162 if (!blacklist
.SerializeToString(&blacklist_data
)) return false;
164 std::string base64_blacklist_data
;
165 base::Base64Encode(blacklist_data
, &base64_blacklist_data
);
167 pref_service_
->SetString(prefs::kSuggestionsBlacklist
, base64_blacklist_data
);
171 void BlacklistStore::ClearBlacklist() {
172 pref_service_
->ClearPref(prefs::kSuggestionsBlacklist
);
175 } // namespace suggestions