| Index: chrome/browser/browsing_data/browsing_data_filter_builder_impl.cc
|
| diff --git a/chrome/browser/browsing_data/browsing_data_filter_builder_impl.cc b/chrome/browser/browsing_data/browsing_data_filter_builder_impl.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e1627565f76de7d2fb0216b8c7e8683c238d5c9f
|
| --- /dev/null
|
| +++ b/chrome/browser/browsing_data/browsing_data_filter_builder_impl.cc
|
| @@ -0,0 +1,216 @@
|
| +// Copyright 2017 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/browsing_data/browsing_data_filter_builder_impl.h"
|
| +
|
| +#include <string>
|
| +#include <vector>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/callback.h"
|
| +#include "base/memory/ptr_util.h"
|
| +#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
|
| +#include "net/cookies/canonical_cookie.h"
|
| +#include "url/origin.h"
|
| +
|
| +using net::registry_controlled_domains::GetDomainAndRegistry;
|
| +using net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES;
|
| +
|
| +namespace {
|
| +
|
| +// Whether this is a subdomain of a registrable domain.
|
| +bool IsSubdomainOfARegistrableDomain(const std::string& domain) {
|
| + std::string registrable_domain =
|
| + GetDomainAndRegistry(domain, INCLUDE_PRIVATE_REGISTRIES);
|
| + return registrable_domain != domain && registrable_domain != "";
|
| +}
|
| +
|
| +// Note that for every domain, exactly one of the following holds:
|
| +// 1. GetDomainAndRegistry(domain, _) == "" - e.g. localhost, 127.0.0.1
|
| +// 2. GetDomainAndRegistry(domain, _) == domain - e.g. google.com
|
| +// 3. IsSubdomainOfARegistrableDomain(domain) - e.g. www.google.com
|
| +// Types 1 and 2 are supported by RegistrableDomainFilterBuilder. Type 3 is not.
|
| +
|
| +
|
| +// True if the domain of |url| is in the whitelist, or isn't in the blacklist.
|
| +// The whitelist or blacklist is represented as |origins|,
|
| +// |registerable_domains|, and |mode|.
|
| +bool MatchesURL(
|
| + const std::set<url::Origin>& origins,
|
| + const std::set<std::string>& registerable_domains,
|
| + BrowsingDataFilterBuilder::Mode mode,
|
| + const GURL& url) {
|
| + std::string url_registerable_domain =
|
| + GetDomainAndRegistry(url, INCLUDE_PRIVATE_REGISTRIES);
|
| + bool found_domain =
|
| + (registerable_domains.find(
|
| + url_registerable_domain != "" ? url_registerable_domain
|
| + : url.host()) !=
|
| + registerable_domains.end());
|
| +
|
| + bool found_origin = (origins.find(url::Origin(url)) != origins.end());
|
| +
|
| + return ((found_domain || found_origin) ==
|
| + (mode == BrowsingDataFilterBuilder::WHITELIST));
|
| +}
|
| +
|
| +// True if no domains can see the given cookie and we're a blacklist, or any
|
| +// domains can see the cookie and we're a whitelist.
|
| +// The whitelist or blacklist is represented as |domains_and_ips| and |mode|.
|
| +bool MatchesCookieForRegisterableDomainsAndIPs(
|
| + const std::set<std::string>& domains_and_ips,
|
| + BrowsingDataFilterBuilder::Mode mode,
|
| + const net::CanonicalCookie& cookie) {
|
| + if (domains_and_ips.empty())
|
| + return mode == BrowsingDataFilterBuilder::BLACKLIST;
|
| + std::string cookie_domain = cookie.Domain();
|
| + if (cookie.IsDomainCookie())
|
| + cookie_domain = cookie_domain.substr(1);
|
| + std::string parsed_cookie_domain =
|
| + GetDomainAndRegistry(cookie_domain, INCLUDE_PRIVATE_REGISTRIES);
|
| + // This means we're an IP address or an internal hostname.
|
| + if (parsed_cookie_domain.empty())
|
| + parsed_cookie_domain = cookie_domain;
|
| + return (mode == BrowsingDataFilterBuilder::WHITELIST) ==
|
| + (domains_and_ips.find(parsed_cookie_domain) != domains_and_ips.end());
|
| +}
|
| +
|
| +// True if none of the supplied domains matches this Channel ID's server ID
|
| +// and we're a blacklist, or one of them does and we're a whitelist.
|
| +// The whitelist or blacklist is represented as |domains_and_ips| and |mode|.
|
| +bool MatchesChannelIDForRegisterableDomainsAndIPs(
|
| + const std::set<std::string>& domains_and_ips,
|
| + BrowsingDataFilterBuilder::Mode mode,
|
| + const std::string& channel_id_server_id) {
|
| + return ((mode == BrowsingDataFilterBuilder::WHITELIST) ==
|
| + (domains_and_ips.find(channel_id_server_id) != domains_and_ips.end()));
|
| +}
|
| +
|
| +// True if none of the supplied domains matches this plugin's |site| and we're
|
| +// a blacklist, or one of them does and we're a whitelist. The whitelist or
|
| +// blacklist is represented by |domains_and_ips| and |mode|.
|
| +bool MatchesPluginSiteForRegisterableDomainsAndIPs(
|
| + const std::set<std::string>& domains_and_ips,
|
| + BrowsingDataFilterBuilder::Mode mode,
|
| + const std::string& site) {
|
| + // If |site| is a third- or lower-level domain, find the corresponding eTLD+1.
|
| + std::string domain_or_ip =
|
| + GetDomainAndRegistry(site, INCLUDE_PRIVATE_REGISTRIES);
|
| + if (domain_or_ip.empty())
|
| + domain_or_ip = site;
|
| +
|
| + return ((mode == BrowsingDataFilterBuilder::WHITELIST) ==
|
| + (domains_and_ips.find(domain_or_ip) != domains_and_ips.end()));
|
| +}
|
| +
|
| +bool NoopFilter(const GURL& url) {
|
| + return true;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +// static
|
| +std::unique_ptr<BrowsingDataFilterBuilder>
|
| +BrowsingDataFilterBuilder::Create(Mode mode) {
|
| + return base::MakeUnique<BrowsingDataFilterBuilderImpl>(mode);
|
| +}
|
| +
|
| +// static
|
| +base::Callback<bool(const GURL&)> BrowsingDataFilterBuilder::BuildNoopFilter() {
|
| + return base::Bind(&NoopFilter);
|
| +}
|
| +
|
| +BrowsingDataFilterBuilderImpl::BrowsingDataFilterBuilderImpl(Mode mode)
|
| + : mode_(mode) {}
|
| +
|
| +BrowsingDataFilterBuilderImpl::~BrowsingDataFilterBuilderImpl() {}
|
| +
|
| +void BrowsingDataFilterBuilderImpl::AddOrigin(const url::Origin& origin) {
|
| + // TODO(msramek): Optimize OriginFilterBuilder for larger filters if needed.
|
| + DCHECK_LE(origins_.size(), 10U) << "OriginFilterBuilder is only suitable "
|
| + "for creating small filters.";
|
| +
|
| + // By limiting the filter to non-unique origins, we can guarantee that
|
| + // origin1 < origin2 && origin1 > origin2 <=> origin1.isSameOrigin(origin2).
|
| + // This means that std::set::find() will use the same semantics for
|
| + // origin comparison as Origin::IsSameOriginWith(). Furthermore, this
|
| + // means that two filters are equal iff they are equal element-wise.
|
| + DCHECK(!origin.unique()) << "Invalid origin passed into OriginFilter.";
|
| +
|
| + // TODO(msramek): All urls with file scheme currently map to the same
|
| + // origin. This is currently not a problem, but if it becomes one,
|
| + // consider recognizing the URL path.
|
| +
|
| + origins_.insert(origin);
|
| +}
|
| +
|
| +void BrowsingDataFilterBuilderImpl::AddRegisterableDomain(
|
| + const std::string& domain) {
|
| + // We check that the domain we're given is actually a eTLD+1, an IP address,
|
| + // or an internal hostname.
|
| + DCHECK(!IsSubdomainOfARegistrableDomain(domain));
|
| + domains_.insert(domain);
|
| +}
|
| +
|
| +bool BrowsingDataFilterBuilderImpl::IsEmptyBlacklist() const {
|
| + return mode_ == Mode::BLACKLIST && origins_.empty() && domains_.empty();
|
| +}
|
| +
|
| +base::RepeatingCallback<bool(const GURL&)>
|
| +BrowsingDataFilterBuilderImpl::BuildGeneralFilter() const {
|
| + return base::BindRepeating(&MatchesURL, origins_, domains_, mode_);
|
| +}
|
| +
|
| +base::RepeatingCallback<bool(const net::CanonicalCookie& cookie)>
|
| +BrowsingDataFilterBuilderImpl::BuildCookieFilter() const {
|
| + DCHECK(origins_.empty()) <<
|
| + "Origin-based deletion is not suitable for cookies. Please use "
|
| + "different scoping, such as RegistrableDomainFilterBuilder.";
|
| + return base::BindRepeating(&MatchesCookieForRegisterableDomainsAndIPs,
|
| + domains_, mode_);
|
| +}
|
| +
|
| +base::RepeatingCallback<bool(const std::string& channel_id_server_id)>
|
| +BrowsingDataFilterBuilderImpl::BuildChannelIDFilter() const {
|
| + DCHECK(origins_.empty()) <<
|
| + "Origin-based deletion is not suitable for channel IDs. Please use "
|
| + "different scoping, such as RegistrableDomainFilterBuilder.";
|
| + return base::BindRepeating(&MatchesChannelIDForRegisterableDomainsAndIPs,
|
| + domains_, mode_);
|
| +}
|
| +
|
| +base::RepeatingCallback<bool(const std::string& site)>
|
| +BrowsingDataFilterBuilderImpl::BuildPluginFilter() const {
|
| + DCHECK(origins_.empty()) <<
|
| + "Origin-based deletion is not suitable for plugins. Please use "
|
| + "different scoping, such as RegistrableDomainFilterBuilder.";
|
| + return base::BindRepeating(&MatchesPluginSiteForRegisterableDomainsAndIPs,
|
| + domains_, mode_);
|
| +}
|
| +
|
| +BrowsingDataFilterBuilderImpl::Mode
|
| +BrowsingDataFilterBuilderImpl::GetMode() const {
|
| + return mode_;
|
| +}
|
| +
|
| +std::unique_ptr<BrowsingDataFilterBuilder>
|
| +BrowsingDataFilterBuilderImpl::Copy() const {
|
| + std::unique_ptr<BrowsingDataFilterBuilderImpl> copy =
|
| + base::MakeUnique<BrowsingDataFilterBuilderImpl>(mode_);
|
| + copy->origins_ = origins_;
|
| + copy->domains_ = domains_;
|
| + return std::move(copy);
|
| +}
|
| +
|
| +bool BrowsingDataFilterBuilderImpl::operator==(
|
| + const BrowsingDataFilterBuilder& other) const {
|
| + // This is the only implementation of BrowsingDataFilterBuilder, so we can
|
| + // downcast |other|.
|
| + const BrowsingDataFilterBuilderImpl* other_impl =
|
| + static_cast<const BrowsingDataFilterBuilderImpl*>(&other);
|
| +
|
| + return origins_ == other_impl->origins_ &&
|
| + domains_ == other_impl->domains_ &&
|
| + mode_ == other_impl->mode_;
|
| +}
|
|
|