diff options
Diffstat (limited to 'chromium/components/blacklist/opt_out_blacklist/opt_out_blacklist_data.cc')
-rw-r--r-- | chromium/components/blacklist/opt_out_blacklist/opt_out_blacklist_data.cc | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/chromium/components/blacklist/opt_out_blacklist/opt_out_blacklist_data.cc b/chromium/components/blacklist/opt_out_blacklist/opt_out_blacklist_data.cc new file mode 100644 index 00000000000..8b519016629 --- /dev/null +++ b/chromium/components/blacklist/opt_out_blacklist/opt_out_blacklist_data.cc @@ -0,0 +1,176 @@ +// Copyright 2018 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 "components/blacklist/opt_out_blacklist/opt_out_blacklist_data.h" + +#include "base/memory/ptr_util.h" + +namespace blacklist { + +BlacklistData::BlacklistData(std::unique_ptr<Policy> session_policy, + std::unique_ptr<Policy> persistent_policy, + std::unique_ptr<Policy> host_policy, + std::unique_ptr<Policy> type_policy, + size_t max_hosts, + AllowedTypesAndVersions allowed_types) + : session_policy_(std::move(session_policy)), + persistent_policy_(std::move(persistent_policy)), + host_policy_(std::move(host_policy)), + max_hosts_(max_hosts), + type_policy_(std::move(type_policy)), + allowed_types_(std::move(allowed_types)) { + DCHECK_GE(100u, max_hosts); +} +BlacklistData::~BlacklistData() {} + +void BlacklistData::ClearData() { + session_black_list_item_.reset(); + persistent_black_list_item_.reset(); + black_list_item_host_map_.clear(); + black_list_item_type_map_.clear(); +} + +void BlacklistData::AddEntry(const std::string& host_name, + bool opt_out, + int type, + base::Time time, + bool is_from_persistent_storage) { + // Add to the session based rule if it is enabled. + if (session_policy_ && !is_from_persistent_storage) { + if (!session_black_list_item_) { + session_black_list_item_ = std::make_unique<OptOutBlacklistItem>( + session_policy_->history, session_policy_->threshold, + session_policy_->duration); + } + session_black_list_item_->AddEntry(opt_out, time); + } + + // Add to the persistent rule if it is enabled. + if (persistent_policy_) { + if (!persistent_black_list_item_) { + persistent_black_list_item_ = std::make_unique<OptOutBlacklistItem>( + persistent_policy_->history, persistent_policy_->threshold, + persistent_policy_->duration); + } + persistent_black_list_item_->AddEntry(opt_out, time); + } + + // Add to the host rule if it is enabled. Remove hosts if there are more than + // |max_hosts_| in the map. + if (host_policy_) { + auto item = black_list_item_host_map_.find(host_name); + if (item == black_list_item_host_map_.end()) { + auto value = black_list_item_host_map_.emplace( + std::piecewise_construct, std::forward_as_tuple(host_name), + std::forward_as_tuple(host_policy_->history, host_policy_->threshold, + host_policy_->duration)); + DCHECK(value.second); + item = value.first; + } + item->second.AddEntry(opt_out, time); + if (max_hosts_ > 0 && black_list_item_host_map_.size() > max_hosts_) + EvictOldestHost(); + } + + // Only allowed types should be recorded. + DCHECK(allowed_types_.find(type) != allowed_types_.end()); + + if (type_policy_) { + auto item = black_list_item_type_map_.find(type); + if (item == black_list_item_type_map_.end()) { + auto value = black_list_item_type_map_.emplace( + std::piecewise_construct, std::forward_as_tuple(type), + std::forward_as_tuple(type_policy_->history, type_policy_->threshold, + type_policy_->duration)); + DCHECK(value.second); + item = value.first; + } + item->second.AddEntry(opt_out, time); + } +} + +BlacklistReason BlacklistData::IsAllowed( + const std::string& host_name, + int type, + bool ignore_long_term_black_list_rules, + base::Time time, + std::vector<BlacklistReason>* passed_reasons) const { + // Check the session rule. + if (session_policy_) { + if (session_black_list_item_ && + session_black_list_item_->IsBlackListed(time)) { + return BlacklistReason::kUserOptedOutInSession; + } + passed_reasons->push_back(BlacklistReason::kUserOptedOutInSession); + } + + // Check whether the persistent rules should be checked this time. + if (ignore_long_term_black_list_rules) + return BlacklistReason::kAllowed; + + // Check the persistent rule. + if (persistent_policy_) { + if (IsUserOptedOutInGeneral(time)) { + return BlacklistReason::kUserOptedOutInGeneral; + } + passed_reasons->push_back(BlacklistReason::kUserOptedOutInGeneral); + } + + // Check the host rule. + if (host_policy_) { + if (IsHostBlacklisted(host_name, time)) + return BlacklistReason::kUserOptedOutOfHost; + passed_reasons->push_back(BlacklistReason::kUserOptedOutOfHost); + } + + // Only allowed types should be recorded. + DCHECK(allowed_types_.find(type) != allowed_types_.end()); + + // Check the type rule. + if (type_policy_) { + auto item = black_list_item_type_map_.find(type); + if (item != black_list_item_type_map_.end() && + item->second.IsBlackListed(time)) { + return BlacklistReason::kUserOptedOutOfType; + } + passed_reasons->push_back(BlacklistReason::kUserOptedOutOfType); + } + + return BlacklistReason::kAllowed; +} + +void BlacklistData::EvictOldestHost() { + DCHECK_LT(max_hosts_, black_list_item_host_map_.size()); + base::Optional<base::Time> oldest_opt_out; + std::string key_to_delete; + for (auto& item : black_list_item_host_map_) { + base::Optional<base::Time> most_recent_opt_out = + item.second.most_recent_opt_out_time(); + if (!most_recent_opt_out) { + // If there is no opt out time, this is a good choice to evict. + key_to_delete = item.first; + break; + } + if (!oldest_opt_out || + most_recent_opt_out.value() < oldest_opt_out.value()) { + oldest_opt_out = most_recent_opt_out.value(); + key_to_delete = item.first; + } + } + black_list_item_host_map_.erase(key_to_delete); +} + +bool BlacklistData::IsHostBlacklisted(const std::string& host_name, + base::Time time) const { + auto item = black_list_item_host_map_.find(host_name); + return item != black_list_item_host_map_.end() && + item->second.IsBlackListed(time); +} + +bool BlacklistData::IsUserOptedOutInGeneral(base::Time time) const { + return persistent_black_list_item_ && + persistent_black_list_item_->IsBlackListed(time); +} + +} // namespace blacklist |