0

Query FPSs info correctly if FPS is disabled for a profile.

Add a FirstPartySetsContextConfig class to hold the configuration to be
used in the query context, in order to make sure it works correctly
after queries to FirstPartySetsManager being controlled by per-profile
settings for the network context. If FPS is not enabled for the network
context, queries will run as if the FPSs map is empty.

Bug: 1325050
Change-Id: Ie0e8a542de05bd6c6989281d921e4e905137e009
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3647723
Reviewed-by: Maks Orlovich <morlovich@chromium.org>
Reviewed-by: Chris Fredrickson <cfredric@chromium.org>
Commit-Queue: Shuran Huang <shuuran@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1004802}
This commit is contained in:
Shuran Huang
2022-05-18 16:28:05 +00:00
committed by Chromium LUCI CQ
parent 16d5837572
commit fe8c01d468
8 changed files with 296 additions and 105 deletions

@ -13,6 +13,7 @@
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_util.h"
#include "net/cookies/first_party_set_metadata.h"
#include "services/network/first_party_sets/first_party_sets_context_config.h"
#include "services/network/first_party_sets/first_party_sets_manager.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@ -25,7 +26,12 @@ CookieAccessDelegateImpl::CookieAccessDelegateImpl(
const CookieSettings* cookie_settings)
: type_(type),
cookie_settings_(cookie_settings),
first_party_sets_manager_(first_party_sets_manager) {
first_party_sets_manager_(first_party_sets_manager),
// TODO(crbug.com/1325050): Will be replaced in a follow up change.
// Currently have context config set to true to maintain the existing
// behavior.
first_party_sets_context_config_(
FirstPartySetsContextConfig(/*enabled=*/true)) {
if (type == mojom::CookieAccessDelegateType::USE_CONTENT_SETTINGS) {
DCHECK(cookie_settings);
}
@ -70,7 +76,8 @@ CookieAccessDelegateImpl::ComputeFirstPartySetMetadataMaybeAsync(
if (!first_party_sets_manager_)
return {net::FirstPartySetMetadata()};
return first_party_sets_manager_->ComputeMetadata(
site, top_frame_site, party_context, std::move(callback));
site, top_frame_site, party_context, first_party_sets_context_config_,
std::move(callback));
}
absl::optional<FirstPartySetsManager::OwnerResult>
@ -80,7 +87,8 @@ CookieAccessDelegateImpl::FindFirstPartySetOwner(
const {
if (!first_party_sets_manager_)
return {absl::nullopt};
return first_party_sets_manager_->FindOwner(site, std::move(callback));
return first_party_sets_manager_->FindOwner(
site, first_party_sets_context_config_, std::move(callback));
}
absl::optional<FirstPartySetsManager::OwnersResult>
@ -90,7 +98,8 @@ CookieAccessDelegateImpl::FindFirstPartySetOwners(
const {
if (!first_party_sets_manager_)
return {{}};
return first_party_sets_manager_->FindOwners(sites, std::move(callback));
return first_party_sets_manager_->FindOwners(
sites, first_party_sets_context_config_, std::move(callback));
}
absl::optional<FirstPartySetsManager::SetsByOwner>
@ -99,7 +108,8 @@ CookieAccessDelegateImpl::RetrieveFirstPartySets(
const {
if (!first_party_sets_manager_)
return {{}};
return first_party_sets_manager_->Sets(std::move(callback));
return first_party_sets_manager_->Sets(first_party_sets_context_config_,
std::move(callback));
}
} // namespace network

@ -81,6 +81,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CookieAccessDelegateImpl
const mojom::CookieAccessDelegateType type_;
const raw_ptr<const CookieSettings> cookie_settings_;
const raw_ptr<FirstPartySetsManager> first_party_sets_manager_;
const FirstPartySetsContextConfig first_party_sets_context_config_;
};
} // namespace network

@ -14,6 +14,8 @@ source_set("first_party_sets_manager") {
defines = [ "IS_NETWORK_SERVICE_IMPL" ]
sources = [
"first_party_sets_context_config.cc",
"first_party_sets_context_config.h",
"first_party_sets_manager.cc",
"first_party_sets_manager.h",
]

@ -0,0 +1,12 @@
// Copyright 2022 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 "services/network/first_party_sets/first_party_sets_context_config.h"
namespace network {
FirstPartySetsContextConfig::FirstPartySetsContextConfig(bool enabled)
: enabled_(enabled) {}
} // namespace network

@ -0,0 +1,25 @@
// Copyright 2022 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.
#ifndef SERVICES_NETWORK_FIRST_PARTY_SETS_FIRST_PARTY_SETS_CONTEXT_CONFIG_H_
#define SERVICES_NETWORK_FIRST_PARTY_SETS_FIRST_PARTY_SETS_CONTEXT_CONFIG_H_
namespace network {
// This struct bundles together the customized settings to First-Party Sets
// info in the given network context.
class FirstPartySetsContextConfig {
public:
FirstPartySetsContextConfig() = default;
explicit FirstPartySetsContextConfig(bool enabled);
bool is_enabled() const { return enabled_; }
private:
bool enabled_ = true;
};
} // namespace network
#endif // SERVICES_NETWORK_FIRST_PARTY_SETS_FIRST_PARTY_SETS_CONTEXT_CONFIG_H_

@ -55,18 +55,19 @@ bool FirstPartySetsManager::IsContextSamePartyWithSite(
const net::SchemefulSite& site,
const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context,
const FirstPartySetsContextConfig& fps_context_config,
bool infer_singleton_sets) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const FirstPartySetsManager::OwnerResult site_owner =
FindOwnerInternal(site, infer_singleton_sets);
FindOwnerInternal(site, fps_context_config, infer_singleton_sets);
if (!site_owner.has_value())
return false;
const auto is_owned_by_site_owner =
[this, &site_owner,
infer_singleton_sets](const net::SchemefulSite& context_site) -> bool {
const FirstPartySetsManager::OwnerResult context_owner =
FindOwnerInternal(context_site, infer_singleton_sets);
[this, &site_owner, infer_singleton_sets,
&fps_context_config](const net::SchemefulSite& context_site) -> bool {
const FirstPartySetsManager::OwnerResult context_owner = FindOwnerInternal(
context_site, fps_context_config, infer_singleton_sets);
return context_owner.has_value() && *context_owner == *site_owner;
};
@ -81,6 +82,7 @@ FirstPartySetsManager::ComputeMetadata(
const net::SchemefulSite& site,
const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context,
const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(net::FirstPartySetMetadata)> callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@ -88,17 +90,19 @@ FirstPartySetsManager::ComputeMetadata(
EnqueuePendingQuery(base::BindOnce(
&FirstPartySetsManager::ComputeMetadataAndInvoke,
weak_factory_.GetWeakPtr(), site, top_frame_site, party_context,
std::move(callback), base::TimeTicks::Now()));
fps_context_config, std::move(callback), base::TimeTicks::Now()));
return absl::nullopt;
}
return ComputeMetadataInternal(site, top_frame_site, party_context);
return ComputeMetadataInternal(site, top_frame_site, party_context,
fps_context_config);
}
void FirstPartySetsManager::ComputeMetadataAndInvoke(
const net::SchemefulSite& site,
const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context,
const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(net::FirstPartySetMetadata)> callback,
base::TimeTicks enqueued_at) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@ -107,27 +111,30 @@ void FirstPartySetsManager::ComputeMetadataAndInvoke(
UMA_HISTOGRAM_TIMES("Cookie.FirstPartySets.EnqueueingDelay.ComputeMetadata",
base::TimeTicks::Now() - enqueued_at);
std::move(callback).Run(
ComputeMetadataInternal(site, top_frame_site, party_context));
std::move(callback).Run(ComputeMetadataInternal(
site, top_frame_site, party_context, fps_context_config));
}
net::FirstPartySetMetadata FirstPartySetsManager::ComputeMetadataInternal(
const net::SchemefulSite& site,
const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context) const {
const std::set<net::SchemefulSite>& party_context,
const FirstPartySetsContextConfig& fps_context_config) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(sets_.has_value());
const base::ElapsedTimer timer;
net::SamePartyContext::Type context_type = ContextTypeFromBool(
IsContextSamePartyWithSite(site, top_frame_site, party_context,
/*infer_singleton_sets=*/false));
net::SamePartyContext::Type ancestors = ContextTypeFromBool(
IsContextSamePartyWithSite(site, top_frame_site, party_context,
/*infer_singleton_sets=*/true));
net::SamePartyContext::Type top_resource =
net::SamePartyContext::Type context_type =
ContextTypeFromBool(IsContextSamePartyWithSite(
site, top_frame_site, {}, /*infer_singleton_sets=*/true));
site, top_frame_site, party_context, fps_context_config,
/*infer_singleton_sets=*/false));
net::SamePartyContext::Type ancestors =
ContextTypeFromBool(IsContextSamePartyWithSite(
site, top_frame_site, party_context, fps_context_config,
/*infer_singleton_sets=*/true));
net::SamePartyContext::Type top_resource = ContextTypeFromBool(
IsContextSamePartyWithSite(site, top_frame_site, {}, fps_context_config,
/*infer_singleton_sets=*/true));
net::SamePartyContext context(context_type, ancestors, top_resource);
@ -136,43 +143,46 @@ net::FirstPartySetMetadata FirstPartySetsManager::ComputeMetadataInternal(
base::Microseconds(1), base::Milliseconds(100), 50);
net::FirstPartySetsContextType first_party_sets_context_type =
ComputeContextType(site, top_frame_site, party_context);
ComputeContextType(site, top_frame_site, party_context,
fps_context_config);
FirstPartySetsManager::OwnerResult top_frame_owner =
top_frame_site ? FindOwnerInternal(*top_frame_site,
top_frame_site ? FindOwnerInternal(*top_frame_site, fps_context_config,
/*infer_singleton_sets=*/false)
: absl::nullopt;
return net::FirstPartySetMetadata(context,
base::OptionalOrNullptr(FindOwnerInternal(
site, /*infer_singleton_sets=*/false)),
base::OptionalOrNullptr(top_frame_owner),
first_party_sets_context_type);
return net::FirstPartySetMetadata(
context,
base::OptionalOrNullptr(FindOwnerInternal(
site, fps_context_config, /*infer_singleton_sets=*/false)),
base::OptionalOrNullptr(top_frame_owner), first_party_sets_context_type);
}
net::FirstPartySetsContextType FirstPartySetsManager::ComputeContextType(
const net::SchemefulSite& site,
const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context) const {
const std::set<net::SchemefulSite>& party_context,
const FirstPartySetsContextConfig& fps_context_config) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(sets_.has_value());
constexpr bool infer_singleton_sets = true;
const FirstPartySetsManager::OwnerResult site_owner =
FindOwnerInternal(site, infer_singleton_sets);
FindOwnerInternal(site, fps_context_config, infer_singleton_sets);
// Note: the `party_context` consists of the intermediate frames (for frame
// requests) or intermediate frames and current frame for subresource
// requests.
const bool is_homogeneous = base::ranges::all_of(
party_context, [&](const net::SchemefulSite& middle_site) {
return *FindOwnerInternal(middle_site, infer_singleton_sets) ==
*site_owner;
return *FindOwnerInternal(middle_site, fps_context_config,
infer_singleton_sets) == *site_owner;
});
if (top_frame_site == nullptr) {
return is_homogeneous
? net::FirstPartySetsContextType::kTopFrameIgnoredHomogeneous
: net::FirstPartySetsContextType::kTopFrameIgnoredMixed;
}
if (*FindOwnerInternal(*top_frame_site, infer_singleton_sets) != *site_owner)
if (*FindOwnerInternal(*top_frame_site, fps_context_config,
infer_singleton_sets) != *site_owner)
return net::FirstPartySetsContextType::kTopResourceMismatch;
return is_homogeneous
@ -181,8 +191,10 @@ net::FirstPartySetsContextType FirstPartySetsManager::ComputeContextType(
}
const FirstPartySetsManager::OwnerResult
FirstPartySetsManager::FindOwnerInternal(const net::SchemefulSite& site,
bool infer_singleton_sets) const {
FirstPartySetsManager::FindOwnerInternal(
const net::SchemefulSite& site,
const FirstPartySetsContextConfig& fps_context_config,
bool infer_singleton_sets) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(sets_.has_value());
const base::ElapsedTimer timer;
@ -191,10 +203,14 @@ FirstPartySetsManager::FindOwnerInternal(const net::SchemefulSite& site,
normalized_site.ConvertWebSocketToHttp();
FirstPartySetsManager::OwnerResult owner;
const auto it = sets_->find(normalized_site);
if (it != sets_->end()) {
owner = it->second;
} else if (infer_singleton_sets) {
if (fps_context_config.is_enabled()) {
if (const auto it = sets_->find(normalized_site); it != sets_->end()) {
owner = it->second;
}
}
if (!owner.has_value() && infer_singleton_sets) {
owner = normalized_site;
}
@ -207,21 +223,24 @@ FirstPartySetsManager::FindOwnerInternal(const net::SchemefulSite& site,
absl::optional<FirstPartySetsManager::OwnerResult>
FirstPartySetsManager::FindOwner(
const net::SchemefulSite& site,
const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(FirstPartySetsManager::OwnerResult)> callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!sets_.has_value()) {
EnqueuePendingQuery(base::BindOnce(
&FirstPartySetsManager::FindOwnerAndInvoke, weak_factory_.GetWeakPtr(),
site, std::move(callback), base::TimeTicks::Now()));
site, fps_context_config, std::move(callback), base::TimeTicks::Now()));
return absl::nullopt;
}
return FindOwnerInternal(site, /*infer_singleton_sets=*/false);
return FindOwnerInternal(site, fps_context_config,
/*infer_singleton_sets=*/false);
}
void FirstPartySetsManager::FindOwnerAndInvoke(
const net::SchemefulSite& site,
const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(FirstPartySetsManager::OwnerResult)> callback,
base::TimeTicks enqueued_at) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@ -230,28 +249,31 @@ void FirstPartySetsManager::FindOwnerAndInvoke(
UMA_HISTOGRAM_TIMES("Cookie.FirstPartySets.EnqueueingDelay.FindOwner",
base::TimeTicks::Now() - enqueued_at);
std::move(callback).Run(
FindOwnerInternal(site, /*infer_singleton_sets=*/false));
std::move(callback).Run(FindOwnerInternal(site, fps_context_config,
/*infer_singleton_sets=*/false));
}
absl::optional<FirstPartySetsManager::OwnersResult>
FirstPartySetsManager::FindOwners(
const base::flat_set<net::SchemefulSite>& sites,
const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(FirstPartySetsManager::OwnersResult)> callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!sets_.has_value()) {
EnqueuePendingQuery(base::BindOnce(
&FirstPartySetsManager::FindOwnersAndInvoke, weak_factory_.GetWeakPtr(),
sites, std::move(callback), base::TimeTicks::Now()));
EnqueuePendingQuery(
base::BindOnce(&FirstPartySetsManager::FindOwnersAndInvoke,
weak_factory_.GetWeakPtr(), sites, fps_context_config,
std::move(callback), base::TimeTicks::Now()));
return absl::nullopt;
}
return FindOwnersInternal(sites);
return FindOwnersInternal(sites, fps_context_config);
}
void FirstPartySetsManager::FindOwnersAndInvoke(
const base::flat_set<net::SchemefulSite>& sites,
const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(FirstPartySetsManager::OwnersResult)> callback,
base::TimeTicks enqueued_at) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@ -260,19 +282,23 @@ void FirstPartySetsManager::FindOwnersAndInvoke(
UMA_HISTOGRAM_TIMES("Cookie.FirstPartySets.EnqueueingDelay.FindOwners",
base::TimeTicks::Now() - enqueued_at);
std::move(callback).Run(FindOwnersInternal(sites));
std::move(callback).Run(FindOwnersInternal(sites, fps_context_config));
}
FirstPartySetsManager::OwnersResult FirstPartySetsManager::FindOwnersInternal(
const base::flat_set<net::SchemefulSite>& sites) const {
const base::flat_set<net::SchemefulSite>& sites,
const FirstPartySetsContextConfig& fps_context_config) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(sets_.has_value());
if (!fps_context_config.is_enabled())
return {};
std::vector<std::pair<net::SchemefulSite, net::SchemefulSite>>
sites_to_owners;
for (const net::SchemefulSite& site : sites) {
const FirstPartySetsManager::OwnerResult owner =
FindOwnerInternal(site, /*infer_singleton_sets=*/false);
const FirstPartySetsManager::OwnerResult owner = FindOwnerInternal(
site, fps_context_config, /*infer_singleton_sets=*/false);
if (owner.has_value()) {
sites_to_owners.emplace_back(site, owner.value());
}
@ -281,20 +307,22 @@ FirstPartySetsManager::OwnersResult FirstPartySetsManager::FindOwnersInternal(
}
absl::optional<FirstPartySetsManager::SetsByOwner> FirstPartySetsManager::Sets(
const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(FirstPartySetsManager::SetsByOwner)> callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!sets_.has_value()) {
EnqueuePendingQuery(base::BindOnce(
&FirstPartySetsManager::SetsAndInvoke, weak_factory_.GetWeakPtr(),
std::move(callback), base::TimeTicks::Now()));
fps_context_config, std::move(callback), base::TimeTicks::Now()));
return absl::nullopt;
}
return SetsInternal();
return SetsInternal(fps_context_config);
}
void FirstPartySetsManager::SetsAndInvoke(
const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(FirstPartySetsManager::SetsByOwner)> callback,
base::TimeTicks enqueued_at) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@ -303,15 +331,18 @@ void FirstPartySetsManager::SetsAndInvoke(
UMA_HISTOGRAM_TIMES("Cookie.FirstPartySets.EnqueueingDelay.Sets",
base::TimeTicks::Now() - enqueued_at);
std::move(callback).Run(SetsInternal());
std::move(callback).Run(SetsInternal(fps_context_config));
}
FirstPartySetsManager::SetsByOwner FirstPartySetsManager::SetsInternal() const {
FirstPartySetsManager::SetsByOwner FirstPartySetsManager::SetsInternal(
const FirstPartySetsContextConfig& fps_context_config) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(sets_.has_value());
FirstPartySetsManager::SetsByOwner sets;
if (!fps_context_config.is_enabled())
return {};
FirstPartySetsManager::SetsByOwner sets;
for (const auto& pair : *sets_) {
const net::SchemefulSite& member = pair.first;
const net::SchemefulSite& owner = pair.second;

@ -21,6 +21,7 @@
#include "net/cookies/cookie_constants.h"
#include "net/cookies/first_party_set_metadata.h"
#include "net/cookies/same_party_context.h"
#include "services/network/first_party_sets/first_party_sets_context_config.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace network {
@ -46,7 +47,7 @@ class FirstPartySetsManager {
return enabled_;
}
// Computes the First-Party Set metadata related to the given context.
// Computes the First-Party Set metadata related to the given request context.
//
// This may return a result synchronously, or asynchronously invoke `callback`
// with the result. The callback will be invoked iff the return value is
@ -56,6 +57,7 @@ class FirstPartySetsManager {
const net::SchemefulSite& site,
const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context,
const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(net::FirstPartySetMetadata)> callback);
// Computes a mapping from owner to set members. For convenience of iteration,
@ -66,6 +68,7 @@ class FirstPartySetsManager {
// nullopt; i.e. a result will be provided via return value or callback, but
// not both, and not neither.
[[nodiscard]] absl::optional<SetsByOwner> Sets(
const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(SetsByOwner)> callback);
// Stores the First-Party Sets data.
@ -88,6 +91,7 @@ class FirstPartySetsManager {
// not both, and not neither.
[[nodiscard]] absl::optional<OwnerResult> FindOwner(
const net::SchemefulSite& site,
const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(OwnerResult)> callback);
// Batched version of `FindOwner`. Returns the mapping of sites to owners for
@ -104,6 +108,7 @@ class FirstPartySetsManager {
// not both, and not neither.
[[nodiscard]] absl::optional<OwnersResult> FindOwners(
const base::flat_set<net::SchemefulSite>& sites,
const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(OwnersResult)> callback);
private:
@ -113,6 +118,7 @@ class FirstPartySetsManager {
const net::SchemefulSite& site,
const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context,
const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(net::FirstPartySetMetadata)> callback,
base::TimeTicks enqueued_at) const;
@ -121,7 +127,8 @@ class FirstPartySetsManager {
net::FirstPartySetMetadata ComputeMetadataInternal(
const net::SchemefulSite& site,
const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context) const;
const std::set<net::SchemefulSite>& party_context,
const FirstPartySetsContextConfig& fps_context_config) const;
// Returns whether the `site` is same-party with the `party_context`, and
// `top_frame_site` (if it is not nullptr). That is, is the `site`'s owner the
@ -133,6 +140,7 @@ class FirstPartySetsManager {
const net::SchemefulSite& site,
const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context,
const FirstPartySetsContextConfig& fps_context_config,
bool infer_singleton_sets) const;
// Computes the "type" of the context. I.e., categorizes contexts based on
@ -147,43 +155,52 @@ class FirstPartySetsManager {
net::FirstPartySetsContextType ComputeContextType(
const net::SchemefulSite& site,
const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context) const;
const std::set<net::SchemefulSite>& party_context,
const FirstPartySetsContextConfig& fps_context_config) const;
// Same as `FindOwner`, but plumbs the result into the callback. Must only be
// called once the instance is fully initialized.
void FindOwnerAndInvoke(const net::SchemefulSite& site,
const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(OwnerResult)> callback,
base::TimeTicks enqueued_at) const;
// Returns `site`'s owner (optionally inferring a singleton set if necessary),
// or `nullopt` if `site` has no owner. Must not return `nullopt` if
// `infer_singleton_sets` is true.
// `infer_singleton_sets` is true. `fps_context_config` is the configuration
// to be used in this context.
//
// This is synchronous, and must not be called
// until the instance is fully initialized.
const absl::optional<net::SchemefulSite> FindOwnerInternal(
const net::SchemefulSite& site,
const FirstPartySetsContextConfig& fps_context_config,
bool infer_singleton_sets) const;
// Same as `FindOwners`, but plumbs the result into the callback. Must only be
// called once the instance is fully initialized.
void FindOwnersAndInvoke(const base::flat_set<net::SchemefulSite>& sites,
base::OnceCallback<void(OwnersResult)> callback,
base::TimeTicks enqueued_at) const;
void FindOwnersAndInvoke(
const base::flat_set<net::SchemefulSite>& sites,
const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(OwnersResult)> callback,
base::TimeTicks enqueued_at) const;
// Synchronous version of `FindOwners`, to be run only once the instance is
// initialized.
OwnersResult FindOwnersInternal(
const base::flat_set<net::SchemefulSite>& sites) const;
const base::flat_set<net::SchemefulSite>& sites,
const FirstPartySetsContextConfig& fps_context_config) const;
// Same as `Sets`, but plumbs the result into the callback. Must only be
// called once the instance is fully initialized.
void SetsAndInvoke(base::OnceCallback<void(SetsByOwner)> callback,
void SetsAndInvoke(const FirstPartySetsContextConfig& fps_context_config,
base::OnceCallback<void(SetsByOwner)> callback,
base::TimeTicks enqueued_at) const;
// Synchronous version of `Sets`, to be run only once the instance is
// initialized.
SetsByOwner SetsInternal() const;
SetsByOwner SetsInternal(
const FirstPartySetsContextConfig& fps_context_config) const;
// Enqueues a query to be answered once the instance is fully initialized.
void EnqueuePendingQuery(base::OnceClosure run_query);

@ -47,7 +47,7 @@ class FirstPartySetsManagerTest : public ::testing::Test {
FirstPartySetsManager::SetsByOwner SetsAndWait() {
base::test::TestFuture<FirstPartySetsManager::SetsByOwner> future;
absl::optional<FirstPartySetsManager::SetsByOwner> result =
manager_.Sets(future.GetCallback());
manager_.Sets(fps_context_config_, future.GetCallback());
return result.has_value() ? result.value() : future.Get();
}
@ -58,7 +58,7 @@ class FirstPartySetsManagerTest : public ::testing::Test {
base::test::TestFuture<net::FirstPartySetMetadata> future;
absl::optional<net::FirstPartySetMetadata> result =
manager_.ComputeMetadata(site, top_frame_site, party_context,
future.GetCallback());
fps_context_config_, future.GetCallback());
return result.has_value() ? std::move(result).value() : future.Take();
}
@ -66,7 +66,7 @@ class FirstPartySetsManagerTest : public ::testing::Test {
const net::SchemefulSite& site) {
base::test::TestFuture<FirstPartySetsManager::OwnerResult> future;
absl::optional<FirstPartySetsManager::OwnerResult> result =
manager_.FindOwner(site, future.GetCallback());
manager_.FindOwner(site, fps_context_config_, future.GetCallback());
return result.has_value() ? result.value() : future.Get();
}
@ -74,22 +74,35 @@ class FirstPartySetsManagerTest : public ::testing::Test {
const base::flat_set<net::SchemefulSite>& site) {
base::test::TestFuture<FirstPartySetsManager::OwnersResult> future;
absl::optional<FirstPartySetsManager::OwnersResult> result =
manager_.FindOwners(site, future.GetCallback());
manager_.FindOwners(site, fps_context_config_, future.GetCallback());
return result.has_value() ? result.value() : future.Get();
}
FirstPartySetsManager& manager() { return manager_; }
FirstPartySetsContextConfig& fps_context_config() {
return fps_context_config_;
}
base::test::TaskEnvironment& env() { return env_; }
protected:
void SetFirstPartySetsContextConfig(bool enabled) {
fps_context_config_ = FirstPartySetsContextConfig(enabled);
}
private:
base::test::TaskEnvironment env_;
FirstPartySetsManager manager_;
FirstPartySetsContextConfig fps_context_config_;
};
class FirstPartySetsManagerDisabledTest : public FirstPartySetsManagerTest {
public:
FirstPartySetsManagerDisabledTest() : FirstPartySetsManagerTest(false) {}
FirstPartySetsManagerDisabledTest() : FirstPartySetsManagerTest(false) {
// FPS setting by the browser overrules FPS setting by a profile.
SetFirstPartySetsContextConfig(true);
}
};
TEST_F(FirstPartySetsManagerDisabledTest, SetCompleteSets) {
@ -163,7 +176,9 @@ TEST_F(FirstPartySetsManagerDisabledTest, Sets_IsEmpty) {
class FirstPartySetsEnabledTest : public FirstPartySetsManagerTest {
public:
FirstPartySetsEnabledTest() : FirstPartySetsManagerTest(true) {}
FirstPartySetsEnabledTest() : FirstPartySetsManagerTest(true) {
SetFirstPartySetsContextConfig(true);
}
};
TEST_F(FirstPartySetsEnabledTest, Sets_IsEmpty) {
@ -243,8 +258,8 @@ TEST_F(AsyncPopulatedFirstPartySetsManagerTest,
net::SchemefulSite owner(GURL("https://example.test"));
base::test::TestFuture<net::FirstPartySetMetadata> future;
EXPECT_FALSE(manager().ComputeMetadata(member, &member, {member},
future.GetCallback()));
EXPECT_FALSE(manager().ComputeMetadata(
member, &member, {member}, fps_context_config(), future.GetCallback()));
Populate();
@ -256,8 +271,9 @@ TEST_F(AsyncPopulatedFirstPartySetsManagerTest,
TEST_F(AsyncPopulatedFirstPartySetsManagerTest, QueryBeforeReady_FindOwner) {
base::test::TestFuture<FirstPartySetsManager::OwnerResult> future;
EXPECT_FALSE(manager().FindOwner(
net::SchemefulSite(GURL("https://member1.test")), future.GetCallback()));
EXPECT_FALSE(
manager().FindOwner(net::SchemefulSite(GURL("https://member1.test")),
fps_context_config(), future.GetCallback()));
Populate();
@ -273,7 +289,7 @@ TEST_F(AsyncPopulatedFirstPartySetsManagerTest, QueryBeforeReady_FindOwners) {
net::SchemefulSite(GURL("https://member1.test")),
net::SchemefulSite(GURL("https://member2.test")),
},
future.GetCallback()));
fps_context_config(), future.GetCallback()));
Populate();
@ -286,7 +302,7 @@ TEST_F(AsyncPopulatedFirstPartySetsManagerTest, QueryBeforeReady_FindOwners) {
TEST_F(AsyncPopulatedFirstPartySetsManagerTest, QueryBeforeReady_Sets) {
base::test::TestFuture<FirstPartySetsManager::SetsByOwner> future;
EXPECT_FALSE(manager().Sets(future.GetCallback()));
EXPECT_FALSE(manager().Sets(fps_context_config(), future.GetCallback()));
Populate();
@ -940,40 +956,117 @@ TEST_F(PopulatedFirstPartySetsManagerTest, ComputeContextType) {
});
net::SchemefulSite singleton(GURL("https://implicit-singleton.test"));
EXPECT_EQ(net::FirstPartySetsContextType::kTopFrameIgnoredHomogeneous,
manager().ComputeContextType(example, nullptr, {}));
EXPECT_EQ(
net::FirstPartySetsContextType::kTopFrameIgnoredHomogeneous,
manager().ComputeContextType(example, nullptr, homogeneous_context));
manager().ComputeContextType(example, nullptr, {}, fps_context_config()));
EXPECT_EQ(net::FirstPartySetsContextType::kTopFrameIgnoredHomogeneous,
manager().ComputeContextType(example, nullptr, homogeneous_context,
fps_context_config()));
EXPECT_EQ(net::FirstPartySetsContextType::kTopFrameIgnoredMixed,
manager().ComputeContextType(example, nullptr, mixed_context));
manager().ComputeContextType(example, nullptr, mixed_context,
fps_context_config()));
EXPECT_EQ(net::FirstPartySetsContextType::kHomogeneous,
manager().ComputeContextType(example, &member1, {}));
manager().ComputeContextType(example, &member1, {},
fps_context_config()));
EXPECT_EQ(net::FirstPartySetsContextType::kHomogeneous,
manager().ComputeContextType(example, &member1, homogeneous_context,
fps_context_config()));
EXPECT_EQ(net::FirstPartySetsContextType::kHomogeneous,
manager().ComputeContextType(singleton, &singleton, {singleton},
fps_context_config()));
EXPECT_EQ(net::FirstPartySetsContextType::kTopResourceMatchMixed,
manager().ComputeContextType(example, &member1, {foo},
fps_context_config()));
EXPECT_EQ(net::FirstPartySetsContextType::kTopResourceMatchMixed,
manager().ComputeContextType(example, &member1, mixed_context,
fps_context_config()));
EXPECT_EQ(net::FirstPartySetsContextType::kTopResourceMatchMixed,
manager().ComputeContextType(example, &member1, {singleton},
fps_context_config()));
EXPECT_EQ(net::FirstPartySetsContextType::kTopResourceMatchMixed,
manager().ComputeContextType(singleton, &singleton, mixed_context,
fps_context_config()));
EXPECT_EQ(
net::FirstPartySetsContextType::kHomogeneous,
manager().ComputeContextType(example, &member1, homogeneous_context));
EXPECT_EQ(net::FirstPartySetsContextType::kHomogeneous,
manager().ComputeContextType(singleton, &singleton, {singleton}));
net::FirstPartySetsContextType::kTopResourceMismatch,
manager().ComputeContextType(example, &foo, {}, fps_context_config()));
EXPECT_EQ(net::FirstPartySetsContextType::kTopResourceMismatch,
manager().ComputeContextType(example, &foo, homogeneous_context,
fps_context_config()));
EXPECT_EQ(net::FirstPartySetsContextType::kTopResourceMismatch,
manager().ComputeContextType(example, &foo, mixed_context,
fps_context_config()));
EXPECT_EQ(net::FirstPartySetsContextType::kTopResourceMismatch,
manager().ComputeContextType(example, &singleton, mixed_context,
fps_context_config()));
}
EXPECT_EQ(net::FirstPartySetsContextType::kTopResourceMatchMixed,
manager().ComputeContextType(example, &member1, {foo}));
EXPECT_EQ(net::FirstPartySetsContextType::kTopResourceMatchMixed,
manager().ComputeContextType(example, &member1, mixed_context));
EXPECT_EQ(net::FirstPartySetsContextType::kTopResourceMatchMixed,
manager().ComputeContextType(example, &member1, {singleton}));
EXPECT_EQ(net::FirstPartySetsContextType::kTopResourceMatchMixed,
manager().ComputeContextType(singleton, &singleton, mixed_context));
class DisabledContextFirstPartySetsManagerTest
: public PopulatedFirstPartySetsManagerTest {
public:
DisabledContextFirstPartySetsManagerTest() {
SetFirstPartySetsContextConfig(false);
}
};
EXPECT_EQ(net::FirstPartySetsContextType::kTopResourceMismatch,
manager().ComputeContextType(example, &foo, {}));
EXPECT_EQ(net::FirstPartySetsContextType::kTopResourceMismatch,
manager().ComputeContextType(example, &foo, homogeneous_context));
EXPECT_EQ(net::FirstPartySetsContextType::kTopResourceMismatch,
manager().ComputeContextType(example, &foo, mixed_context));
EXPECT_EQ(net::FirstPartySetsContextType::kTopResourceMismatch,
manager().ComputeContextType(example, &singleton, mixed_context));
TEST_F(DisabledContextFirstPartySetsManagerTest, FindOwners) {
EXPECT_THAT(
FindOwnersAndWait({net::SchemefulSite(GURL("https://example.test"))}),
IsEmpty());
}
TEST_F(DisabledContextFirstPartySetsManagerTest, FindOwner) {
EXPECT_FALSE(
FindOwnerAndWait(net::SchemefulSite(GURL("https://example.test"))));
EXPECT_FALSE(
FindOwnerAndWait(net::SchemefulSite(GURL("https://member.test"))));
}
TEST_F(DisabledContextFirstPartySetsManagerTest, Sets_IsEmpty) {
EXPECT_THAT(SetsAndWait(), IsEmpty());
}
TEST_F(DisabledContextFirstPartySetsManagerTest, ComputeMetadata) {
net::SchemefulSite member(GURL("https://member1.test"));
net::SchemefulSite example(GURL("https://example.test"));
net::SchemefulSite wss_member(GURL("wss://member1.test"));
// Works if the site is provided with WSS scheme instead of HTTPS.
EXPECT_THAT(
ComputeMetadataAndWait(wss_member, &member, {member, example}).context(),
net::SamePartyContext(Type::kCrossParty, Type::kCrossParty,
Type::kSameParty));
EXPECT_THAT(ComputeMetadataAndWait(example, &member, {member}).context(),
net::SamePartyContext(Type::kCrossParty));
EXPECT_THAT(ComputeMetadataAndWait(member, &example, {member}).context(),
net::SamePartyContext(Type::kCrossParty));
// Top&resource differs from Ancestors.
EXPECT_THAT(ComputeMetadataAndWait(member, &member, {example}).context(),
net::SamePartyContext(Type::kCrossParty, Type::kCrossParty,
Type::kSameParty));
// Metrics values infer singleton sets when appropriate.
EXPECT_THAT(ComputeMetadataAndWait(member, &member, {member}).context(),
net::SamePartyContext(Type::kCrossParty, Type::kSameParty,
Type::kSameParty));
EXPECT_THAT(ComputeMetadataAndWait(member, &example, {member}).context(),
net::SamePartyContext(Type::kCrossParty));
EXPECT_THAT(ComputeMetadataAndWait(example, &member, {member}).context(),
net::SamePartyContext(Type::kCrossParty));
EXPECT_THAT(ComputeMetadataAndWait(member, &member, {example}).context(),
net::SamePartyContext(Type::kCrossParty, Type::kCrossParty,
Type::kSameParty));
EXPECT_THAT(
ComputeMetadataAndWait(member, &member, {member, example}).context(),
net::SamePartyContext(Type::kCrossParty, Type::kCrossParty,
Type::kSameParty));
}
} // namespace network