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:

committed by
Chromium LUCI CQ

parent
16d5837572
commit
fe8c01d468
@ -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
|
||||
|
Reference in New Issue
Block a user