| Index: chrome/browser/search/suggestions/blacklist_store.cc
|
| diff --git a/chrome/browser/search/suggestions/blacklist_store.cc b/chrome/browser/search/suggestions/blacklist_store.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..85209724b5003fc69809148746e04e41c54e4f2d
|
| --- /dev/null
|
| +++ b/chrome/browser/search/suggestions/blacklist_store.cc
|
| @@ -0,0 +1,175 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/search/suggestions/blacklist_store.h"
|
| +
|
| +#include <set>
|
| +#include <string>
|
| +
|
| +#include "base/base64.h"
|
| +#include "base/metrics/histogram.h"
|
| +#include "base/prefs/pref_service.h"
|
| +#include "chrome/common/pref_names.h"
|
| +#include "components/pref_registry/pref_registry_syncable.h"
|
| +
|
| +namespace suggestions {
|
| +
|
| +namespace {
|
| +
|
| +void PopulateBlacklistSet(const SuggestionsBlacklist& blacklist_proto,
|
| + std::set<std::string>* blacklist_set) {
|
| + blacklist_set->clear();
|
| + for (int i = 0; i < blacklist_proto.urls_size(); ++i) {
|
| + blacklist_set->insert(blacklist_proto.urls(i));
|
| + }
|
| +}
|
| +
|
| +void PopulateBlacklistProto(const std::set<std::string>& blacklist_set,
|
| + SuggestionsBlacklist* blacklist_proto) {
|
| + blacklist_proto->Clear();
|
| + for (std::set<std::string>::const_iterator it = blacklist_set.begin();
|
| + it != blacklist_set.end(); ++it) {
|
| + blacklist_proto->add_urls(*it);
|
| + }
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +BlacklistStore::BlacklistStore(PrefService* profile_prefs)
|
| + : pref_service_(profile_prefs) {
|
| + DCHECK(pref_service_);
|
| +
|
| + // Log the blacklist's size. A single BlacklistStore is created for the
|
| + // SuggestionsService; this will run once.
|
| + SuggestionsBlacklist blacklist_proto;
|
| + LoadBlacklist(&blacklist_proto);
|
| + UMA_HISTOGRAM_COUNTS_10000("Suggestions.LocalBlacklistSize",
|
| + blacklist_proto.urls_size());
|
| +}
|
| +
|
| +BlacklistStore::~BlacklistStore() {}
|
| +
|
| +bool BlacklistStore::BlacklistUrl(const GURL& url) {
|
| + if (!url.is_valid()) return false;
|
| +
|
| + SuggestionsBlacklist blacklist_proto;
|
| + LoadBlacklist(&blacklist_proto);
|
| +
|
| + std::set<std::string> blacklist_set;
|
| + PopulateBlacklistSet(blacklist_proto, &blacklist_set);
|
| +
|
| + if (!blacklist_set.insert(url.spec()).second) {
|
| + // |url| was already in the blacklist.
|
| + return true;
|
| + }
|
| +
|
| + PopulateBlacklistProto(blacklist_set, &blacklist_proto);
|
| + return StoreBlacklist(blacklist_proto);
|
| +}
|
| +
|
| +bool BlacklistStore::GetFirstUrlFromBlacklist(GURL* url) {
|
| + SuggestionsBlacklist blacklist;
|
| + LoadBlacklist(&blacklist);
|
| + if (!blacklist.urls_size()) return false;
|
| + GURL blacklisted(blacklist.urls(0));
|
| + url->Swap(&blacklisted);
|
| + return true;
|
| +}
|
| +
|
| +bool BlacklistStore::RemoveUrl(const GURL& url) {
|
| + if (!url.is_valid()) return false;
|
| + const std::string removal_candidate = url.spec();
|
| +
|
| + SuggestionsBlacklist blacklist;
|
| + LoadBlacklist(&blacklist);
|
| +
|
| + SuggestionsBlacklist updated_blacklist;
|
| + for (int i = 0; i < blacklist.urls_size(); ++i) {
|
| + if (blacklist.urls(i) != removal_candidate)
|
| + updated_blacklist.add_urls(blacklist.urls(i));
|
| + }
|
| +
|
| + return StoreBlacklist(updated_blacklist);
|
| +}
|
| +
|
| +void BlacklistStore::FilterSuggestions(SuggestionsProfile* profile) {
|
| + if (!profile->suggestions_size())
|
| + return; // Empty profile, nothing to filter.
|
| +
|
| + SuggestionsBlacklist blacklist_proto;
|
| + if (!LoadBlacklist(&blacklist_proto)) {
|
| + // There was an error loading the blacklist. The blacklist was cleared and
|
| + // there's nothing to be done about it.
|
| + return;
|
| + }
|
| + if (!blacklist_proto.urls_size())
|
| + return; // Empty blacklist, nothing to filter.
|
| +
|
| + std::set<std::string> blacklist_set;
|
| + PopulateBlacklistSet(blacklist_proto, &blacklist_set);
|
| +
|
| + // Populate the filtered suggestions.
|
| + SuggestionsProfile filtered_profile;
|
| + for (int i = 0; i < profile->suggestions_size(); ++i) {
|
| + if (blacklist_set.find(profile->suggestions(i).url()) ==
|
| + blacklist_set.end()) {
|
| + // This suggestion is not blacklisted.
|
| + ChromeSuggestion* suggestion = filtered_profile.add_suggestions();
|
| + // Note: swapping!
|
| + suggestion->Swap(profile->mutable_suggestions(i));
|
| + }
|
| + }
|
| +
|
| + // Swap |profile| and |filtered_profile|.
|
| + profile->Swap(&filtered_profile);
|
| +}
|
| +
|
| +// static
|
| +void BlacklistStore::RegisterProfilePrefs(
|
| + user_prefs::PrefRegistrySyncable* registry) {
|
| + registry->RegisterStringPref(
|
| + prefs::kSuggestionsBlacklist, std::string(),
|
| + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
|
| +}
|
| +
|
| +bool BlacklistStore::LoadBlacklist(SuggestionsBlacklist* blacklist) {
|
| + DCHECK(blacklist);
|
| +
|
| + const std::string base64_blacklist_data =
|
| + pref_service_->GetString(prefs::kSuggestionsBlacklist);
|
| + if (base64_blacklist_data.empty()) {
|
| + blacklist->Clear();
|
| + return false;
|
| + }
|
| +
|
| + // If the decode process fails, assume the pref value is corrupt and clear it.
|
| + std::string blacklist_data;
|
| + if (!base::Base64Decode(base64_blacklist_data, &blacklist_data) ||
|
| + !blacklist->ParseFromString(blacklist_data)) {
|
| + VLOG(1) << "Suggestions blacklist data in profile pref is corrupt, "
|
| + << " clearing it.";
|
| + blacklist->Clear();
|
| + ClearBlacklist();
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool BlacklistStore::StoreBlacklist(const SuggestionsBlacklist& blacklist) {
|
| + std::string blacklist_data;
|
| + if (!blacklist.SerializeToString(&blacklist_data)) return false;
|
| +
|
| + std::string base64_blacklist_data;
|
| + base::Base64Encode(blacklist_data, &base64_blacklist_data);
|
| +
|
| + pref_service_->SetString(prefs::kSuggestionsBlacklist, base64_blacklist_data);
|
| + return true;
|
| +}
|
| +
|
| +void BlacklistStore::ClearBlacklist() {
|
| + pref_service_->ClearPref(prefs::kSuggestionsBlacklist);
|
| +}
|
| +
|
| +} // namespace suggestions
|
|
|