blob: 937b5984826abfa1dfe3ae35aed31515501b853c [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_PUBLIC_BROWSER_FIRST_PARTY_SETS_HANDLER_H_
#define CONTENT_PUBLIC_BROWSER_FIRST_PARTY_SETS_HANDLER_H_
#include <set>
#include <string>
#include "base/files/file.h"
#include "base/functional/callback.h"
#include "base/types/expected.h"
#include "base/values.h"
#include "base/version.h"
#include "content/common/content_export.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace net {
class FirstPartySetsCacheFilter;
class FirstPartySetsContextConfig;
class FirstPartySetEntry;
class FirstPartySetMetadata;
class SchemefulSite;
} // namespace net
namespace content {
class BrowserContext;
// The FirstPartySetsHandler class allows an embedder to provide
// First-Party Sets inputs from custom sources.
class CONTENT_EXPORT FirstPartySetsHandler {
public:
enum class ParseErrorType {
// The set definition was not the correct data type.
kInvalidType,
// A string in the set could not be parsed as a URL or origin.
kInvalidOrigin,
// An origin in the set was specified using a scheme other than HTTPS.
kNonHttpsScheme,
// A origin in the set did not use a valid a registrable domain.
kInvalidDomain,
// The set had no members.
kSingletonSet,
// The set was non-disjoint with other pre-existing sets.
kNonDisjointSets,
// The set repeated the same domain more than once in its definition.
kRepeatedDomain,
};
enum class ParseWarningType {
// The "ccTLDs" map has a key that isn't a canonical site (present in the
// set).
kCctldKeyNotCanonical,
// The "ccTLDs" maps a site that differs from its canonical key beyond just
// TLD.
kAliasNotCctldVariant,
};
// Contains metadata about an <T> issue for later use in outputting
// descriptive messages about the issue.
template <typename T>
class IssueWithMetadata {
public:
IssueWithMetadata(
const T& issue_type,
const std::vector<absl::variant<int, std::string>>& issue_path)
: issue_type_(issue_type), issue_path_(issue_path) {}
~IssueWithMetadata() = default;
IssueWithMetadata(const IssueWithMetadata<T>&) = default;
bool operator==(const IssueWithMetadata<T>& other) const {
return std::tie(issue_type_, issue_path_) ==
std::tie(other.issue_type_, other.issue_path_);
}
// Inserts path_prefix at the beginning of the path stored for this issue.
void PrependPath(
const std::vector<absl::variant<int, std::string>>& path_prefix) {
issue_path_.insert(issue_path_.begin(), path_prefix.begin(),
path_prefix.end());
}
// The type of issue that was found when parsing the policy sets.
T type() const { return issue_type_; }
// The path within the policy that was being parsed when the issue was
// found. Based on the policy::PolicyErrorPath type defined in
// components/policy.
std::vector<absl::variant<int, std::string>> path() const {
return issue_path_;
}
private:
T issue_type_;
std::vector<absl::variant<int, std::string>> issue_path_;
};
using ParseError = IssueWithMetadata<ParseErrorType>;
using ParseWarning = IssueWithMetadata<ParseWarningType>;
virtual ~FirstPartySetsHandler() = default;
// Overrides the singleton with caller-owned |test_instance|. Callers in tests
// are responsible for resetting this to null on cleanup.
static void SetInstanceForTesting(FirstPartySetsHandler* test_instance);
// Returns the singleton instance.
static FirstPartySetsHandler* GetInstance();
// Validates the First-Party Sets Overrides enterprise policy in `policy`,
// and outputs warnings that arise when parsing and an optional error that is
// present if `policy` was invalid.
//
// This validation only checks that all sets in this policy are valid
// First-Party Sets and disjoint from each other. It doesn't require
// disjointness with other sources, such as the public sets, since this policy
// will be used override First-Party Sets in those sources.
static std::pair<absl::optional<ParseError>, std::vector<ParseWarning>>
ValidateEnterprisePolicy(const base::Value::Dict& policy);
// Returns whether First-Party Sets is enabled.
//
// Embedders can use this method to guard First-Party Sets related changes.
virtual bool IsEnabled() const = 0;
// Sets the First-Party Sets data from `sets_file` to initialize the
// FirstPartySets instance. `sets_file` is expected to contain a sequence of
// newline-delimited JSON records. Each record is a set declaration in the
// format specified here: https://github.com/privacycg/first-party-sets.
// `version` is the version of the sets file used for comparison. If the
// file changed between browser runs, those files must have different
// associated `base::Version`.
//
// Embedder should call this method as early as possible during browser
// startup if First-Party Sets are enabled, since no First-Party Sets queries
// are answered until initialization is complete. Must not be called if
// `ContentBrowserClient::WillProvidePublicFirstPartySets` returns false or
// `ContentBrowserClient::IsFrstpartySetsEnabled` returns false.
//
// Must be called at most once.
virtual void SetPublicFirstPartySets(const base::Version& version,
base::File sets_file) = 0;
// Looks up `site` in the global First-Party Sets and `config` to find its
// associated FirstPartySetEntry.
//
// This will return nullopt if:
// - First-Party Sets is disabled or
// - the list of First-Party Sets isn't initialized yet or
// - `site` isn't in the global First-Party Sets or `config`
virtual absl::optional<net::FirstPartySetEntry> FindEntry(
const net::SchemefulSite& site,
const net::FirstPartySetsContextConfig& config) const = 0;
// Computes a representation of the changes that need to be made to the
// browser's list of First-Party Sets to respect the `policy` value of the
// First-Party Sets Overrides enterprise policy. If `policy` is nullptr,
// `callback` is immediately invoked with an empty config.
//
// Otherwise, the context config will be returned via `callback` since the
// context config must be computed after the list of First-Party Sets is
// initialized which occurs asynchronously.
virtual void GetContextConfigForPolicy(
const base::Value::Dict* policy,
base::OnceCallback<void(net::FirstPartySetsContextConfig)> callback) = 0;
// Clear site state of sites that have a FPS membership change for the browser
// context represented by `browser_context_id`. Sites joining FPSs for the
// first time will not be cleared.
//
// `browser_context_getter` is needed to get a BrowsingDataRemover to handle
// the clearing work. `context_config` should be the return value from
// `GetContextConfigForPolicy` if an Overrides enterprise policy is provided,
// or null if one is not provided. `callback` will be invoked once the
// clearing is done.
//
// Embedder must call this before First-Party Sets queries can be answered.
//
// If the First-Party Sets feature is disabled, this is a no-op.
virtual void ClearSiteDataOnChangedSetsForContext(
base::RepeatingCallback<BrowserContext*()> browser_context_getter,
const std::string& browser_context_id,
net::FirstPartySetsContextConfig context_config,
base::OnceCallback<void(net::FirstPartySetsContextConfig,
net::FirstPartySetsCacheFilter)> callback) = 0;
// Computes the First-Party Set metadata related to the given request context,
// and invokes `callback` with the result.
//
// This may invoke `callback` synchronously.
virtual void ComputeFirstPartySetMetadata(
const net::SchemefulSite& site,
const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context,
const net::FirstPartySetsContextConfig& config,
base::OnceCallback<void(net::FirstPartySetMetadata)> callback) = 0;
};
} // namespace content
#endif // CONTENT_PUBLIC_BROWSER_FIRST_PARTY_SETS_HANDLER_H_