1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// found in the LICENSE file.
4116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/suggestions/blacklist_store.h"
6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
7116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <set>
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <string>
9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/base64.h"
11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/metrics/histogram.h"
12116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/prefs/pref_service.h"
13116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "components/pref_registry/pref_registry_syncable.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/suggestions/suggestions_pref_names.h"
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
16116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace suggestions {
17116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
18116680a4aac90f2aa7413d9095a592090648e557Ben Murdochnamespace {
19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
20116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid PopulateBlacklistSet(const SuggestionsBlacklist& blacklist_proto,
21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                          std::set<std::string>* blacklist_set) {
22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  blacklist_set->clear();
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (int i = 0; i < blacklist_proto.urls_size(); ++i) {
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    blacklist_set->insert(blacklist_proto.urls(i));
25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
26116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
28116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid PopulateBlacklistProto(const std::set<std::string>& blacklist_set,
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                            SuggestionsBlacklist* blacklist_proto) {
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  blacklist_proto->Clear();
31116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (std::set<std::string>::const_iterator it = blacklist_set.begin();
32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       it != blacklist_set.end(); ++it) {
33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    blacklist_proto->add_urls(*it);
34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}  // namespace
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
39116680a4aac90f2aa7413d9095a592090648e557Ben MurdochBlacklistStore::BlacklistStore(PrefService* profile_prefs)
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    : pref_service_(profile_prefs) {
41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(pref_service_);
42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Log the blacklist's size. A single BlacklistStore is created for the
44116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // SuggestionsService; this will run once.
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SuggestionsBlacklist blacklist_proto;
46116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LoadBlacklist(&blacklist_proto);
47116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  UMA_HISTOGRAM_COUNTS_10000("Suggestions.LocalBlacklistSize",
48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                             blacklist_proto.urls_size());
49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
51116680a4aac90f2aa7413d9095a592090648e557Ben MurdochBlacklistStore::~BlacklistStore() {}
52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
53116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool BlacklistStore::BlacklistUrl(const GURL& url) {
54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!url.is_valid()) return false;
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SuggestionsBlacklist blacklist_proto;
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LoadBlacklist(&blacklist_proto);
58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::set<std::string> blacklist_set;
60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PopulateBlacklistSet(blacklist_proto, &blacklist_set);
61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!blacklist_set.insert(url.spec()).second) {
63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // |url| was already in the blacklist.
64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return true;
65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PopulateBlacklistProto(blacklist_set, &blacklist_proto);
68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return StoreBlacklist(blacklist_proto);
69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
71116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool BlacklistStore::GetFirstUrlFromBlacklist(GURL* url) {
72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SuggestionsBlacklist blacklist;
73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LoadBlacklist(&blacklist);
74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!blacklist.urls_size()) return false;
75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  GURL blacklisted(blacklist.urls(0));
76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  url->Swap(&blacklisted);
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
80116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool BlacklistStore::RemoveUrl(const GURL& url) {
81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!url.is_valid()) return false;
82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const std::string removal_candidate = url.spec();
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SuggestionsBlacklist blacklist;
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  LoadBlacklist(&blacklist);
86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SuggestionsBlacklist updated_blacklist;
88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (int i = 0; i < blacklist.urls_size(); ++i) {
89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (blacklist.urls(i) != removal_candidate)
90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      updated_blacklist.add_urls(blacklist.urls(i));
91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return StoreBlacklist(updated_blacklist);
94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
96116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid BlacklistStore::FilterSuggestions(SuggestionsProfile* profile) {
97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!profile->suggestions_size())
98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;  // Empty profile, nothing to filter.
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SuggestionsBlacklist blacklist_proto;
101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!LoadBlacklist(&blacklist_proto)) {
102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // There was an error loading the blacklist. The blacklist was cleared and
103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // there's nothing to be done about it.
104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;
105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!blacklist_proto.urls_size())
107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return;  // Empty blacklist, nothing to filter.
108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::set<std::string> blacklist_set;
110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  PopulateBlacklistSet(blacklist_proto, &blacklist_set);
111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Populate the filtered suggestions.
113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  SuggestionsProfile filtered_profile;
114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (int i = 0; i < profile->suggestions_size(); ++i) {
115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    if (blacklist_set.find(profile->suggestions(i).url()) ==
116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        blacklist_set.end()) {
117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // This suggestion is not blacklisted.
118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      ChromeSuggestion* suggestion = filtered_profile.add_suggestions();
119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      // Note: swapping!
120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      suggestion->Swap(profile->mutable_suggestions(i));
121116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
122116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
123116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Swap |profile| and |filtered_profile|.
125116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  profile->Swap(&filtered_profile);
126116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
127116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// static
129116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid BlacklistStore::RegisterProfilePrefs(
130116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    user_prefs::PrefRegistrySyncable* registry) {
131116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  registry->RegisterStringPref(
132116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      prefs::kSuggestionsBlacklist, std::string(),
133116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
136116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool BlacklistStore::LoadBlacklist(SuggestionsBlacklist* blacklist) {
137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DCHECK(blacklist);
138116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const std::string base64_blacklist_data =
140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      pref_service_->GetString(prefs::kSuggestionsBlacklist);
141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (base64_blacklist_data.empty()) {
142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    blacklist->Clear();
143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // If the decode process fails, assume the pref value is corrupt and clear it.
147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string blacklist_data;
148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!base::Base64Decode(base64_blacklist_data, &blacklist_data) ||
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      !blacklist->ParseFromString(blacklist_data)) {
150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    VLOG(1) << "Suggestions blacklist data in profile pref is corrupt, "
151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            << " clearing it.";
152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    blacklist->Clear();
153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    ClearBlacklist();
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return false;
155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
160116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool BlacklistStore::StoreBlacklist(const SuggestionsBlacklist& blacklist) {
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string blacklist_data;
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!blacklist.SerializeToString(&blacklist_data)) return false;
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string base64_blacklist_data;
165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::Base64Encode(blacklist_data, &base64_blacklist_data);
166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  pref_service_->SetString(prefs::kSuggestionsBlacklist, base64_blacklist_data);
168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  return true;
169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
171116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid BlacklistStore::ClearBlacklist() {
172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  pref_service_->ClearPref(prefs::kSuggestionsBlacklist);
173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}  // namespace suggestions
176