Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / components / suggestions / blacklist_store.cc
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.
4
5 #include "components/suggestions/blacklist_store.h"
6
7 #include <set>
8 #include <string>
9
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"
15
16 namespace suggestions {
17
18 namespace {
19
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));
25   }
26 }
27
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);
34   }
35 }
36
37 }  // namespace
38
39 BlacklistStore::BlacklistStore(PrefService* profile_prefs)
40     : pref_service_(profile_prefs) {
41   DCHECK(pref_service_);
42
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());
49 }
50
51 BlacklistStore::~BlacklistStore() {}
52
53 bool BlacklistStore::BlacklistUrl(const GURL& url) {
54   if (!url.is_valid()) return false;
55
56   SuggestionsBlacklist blacklist_proto;
57   LoadBlacklist(&blacklist_proto);
58
59   std::set<std::string> blacklist_set;
60   PopulateBlacklistSet(blacklist_proto, &blacklist_set);
61
62   if (!blacklist_set.insert(url.spec()).second) {
63     // |url| was already in the blacklist.
64     return true;
65   }
66
67   PopulateBlacklistProto(blacklist_set, &blacklist_proto);
68   return StoreBlacklist(blacklist_proto);
69 }
70
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);
77   return true;
78 }
79
80 bool BlacklistStore::RemoveUrl(const GURL& url) {
81   if (!url.is_valid()) return false;
82   const std::string removal_candidate = url.spec();
83
84   SuggestionsBlacklist blacklist;
85   LoadBlacklist(&blacklist);
86
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));
91   }
92
93   return StoreBlacklist(updated_blacklist);
94 }
95
96 void BlacklistStore::FilterSuggestions(SuggestionsProfile* profile) {
97   if (!profile->suggestions_size())
98     return;  // Empty profile, nothing to filter.
99
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.
104     return;
105   }
106   if (!blacklist_proto.urls_size())
107     return;  // Empty blacklist, nothing to filter.
108
109   std::set<std::string> blacklist_set;
110   PopulateBlacklistSet(blacklist_proto, &blacklist_set);
111
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();
119       // Note: swapping!
120       suggestion->Swap(profile->mutable_suggestions(i));
121     }
122   }
123
124   // Swap |profile| and |filtered_profile|.
125   profile->Swap(&filtered_profile);
126 }
127
128 // static
129 void BlacklistStore::RegisterProfilePrefs(
130     user_prefs::PrefRegistrySyncable* registry) {
131   registry->RegisterStringPref(
132       prefs::kSuggestionsBlacklist, std::string(),
133       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
134 }
135
136 bool BlacklistStore::LoadBlacklist(SuggestionsBlacklist* blacklist) {
137   DCHECK(blacklist);
138
139   const std::string base64_blacklist_data =
140       pref_service_->GetString(prefs::kSuggestionsBlacklist);
141   if (base64_blacklist_data.empty()) {
142     blacklist->Clear();
143     return false;
144   }
145
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, "
151             << " clearing it.";
152     blacklist->Clear();
153     ClearBlacklist();
154     return false;
155   }
156
157   return true;
158 }
159
160 bool BlacklistStore::StoreBlacklist(const SuggestionsBlacklist& blacklist) {
161   std::string blacklist_data;
162   if (!blacklist.SerializeToString(&blacklist_data)) return false;
163
164   std::string base64_blacklist_data;
165   base::Base64Encode(blacklist_data, &base64_blacklist_data);
166
167   pref_service_->SetString(prefs::kSuggestionsBlacklist, base64_blacklist_data);
168   return true;
169 }
170
171 void BlacklistStore::ClearBlacklist() {
172   pref_service_->ClearPref(prefs::kSuggestionsBlacklist);
173 }
174
175 }  // namespace suggestions