0

[Protected Audience] Wire up devtools auction IDs to KVv2 signals cache.

This cl adds devtools instrumentation calls that associate KVv2 trusted
signals cache fetches with their corresponding devtools auction IDs.

Currently, if a new auction is associated with a fetch after it has
been sent over the network, nothing is logged though that may be worth
changing in a followup.

Other corner cases:
* If an auction is cancelled before a fetch starts, but the fetch is
still started due to other ongoing auctions, the fetch will still log
an event associated with the failed auction. Changing this behavior
would require substantial complexity and/or more copies of devtools
IDs, so may not be worth it. Devtools consumers are supposed to be
robust against such things, anyways.

* If an entry from the cache is used directly, without triggering
a fetch, nothing is logged to devtools. The fetch events require
a network request ID, but the network request may have finished long
ago (and in the future, may also have been in another tab). We may
want to log some other event in this case, but that's an issue for
another day.

Bug: 379843989
Change-Id: I322218ee8fd8018b6011b55854f61349802407ec
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6367483
Reviewed-by: Maks Orlovich <morlovich@chromium.org>
Commit-Queue: mmenke <mmenke@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1435010}
This commit is contained in:
Matt Menke
2025-03-19 12:22:28 -07:00
committed by Chromium LUCI CQ
parent 9c6115e5c3
commit 55534ca1c8
12 changed files with 233 additions and 46 deletions

@ -543,6 +543,7 @@ class AuctionProcessManagerTest
trusted_signals_handle =
trusted_signals_cache_.RequestTrustedBiddingSignals(
/*url_loader_factory=*/nullptr, FrameTreeNodeId(1),
{"devtools_auction_id"},
url::Origin::Create(GURL("https://main-frame-origin.test")),
network::mojom::IPAddressSpace::kPublic, origin,
"Interest Group Name",
@ -557,6 +558,7 @@ class AuctionProcessManagerTest
trusted_signals_handle =
trusted_signals_cache_.RequestTrustedScoringSignals(
/*url_loader_factory=*/nullptr, FrameTreeNodeId(1),
{"devtools_auction_id"},
url::Origin::Create(GURL("https://main-frame-origin.test")),
network::mojom::IPAddressSpace::kPublic, origin,
GURL("https://trusted-signals-url/"),

@ -12,6 +12,7 @@
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <string_view>
#include <utility>
@ -20,6 +21,7 @@
#include "base/base64.h"
#include "base/check.h"
#include "base/containers/contains.h"
#include "base/containers/flat_set.h"
#include "base/feature_list.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_writer.h"
@ -1867,6 +1869,7 @@ class MockTrustedSignalsCacheImpl : public TrustedSignalsCacheImpl {
void FetchBiddingSignals(
network::mojom::URLLoaderFactory* url_loader_factory,
FrameTreeNodeId /*frame_tree_node_id*/,
base::flat_set<std::string> /*devtools_auction_ids*/,
const url::Origin& main_frame_origin,
network::mojom::IPAddressSpace /*ip_address_space*/,
base::UnguessableToken /*network_partition_nonce*/,
@ -1903,6 +1906,7 @@ class MockTrustedSignalsCacheImpl : public TrustedSignalsCacheImpl {
void FetchScoringSignals(
network::mojom::URLLoaderFactory* url_loader_factory,
FrameTreeNodeId /*frame_tree_node_id*/,
base::flat_set<std::string> /*devtools_auction_ids*/,
const url::Origin& main_frame_origin,
network::mojom::IPAddressSpace /*ip_address_space*/,
base::UnguessableToken /*network_partition_nonce*/,

@ -2337,9 +2337,10 @@ class InterestGroupAuction::BuyerHelper
->RequestTrustedBiddingSignals(
auction_->url_loader_factory_,
auction_->auction_worklet_manager_->GetFrameTreeNodeID(),
auction_->main_frame_origin_, auction_->ip_address_space_,
interest_group.owner, interest_group.name,
interest_group.execution_mode, bid_state.bidder->joining_origin,
auction_->devtools_auction_id_, auction_->main_frame_origin_,
auction_->ip_address_space_, interest_group.owner,
interest_group.name, interest_group.execution_mode,
bid_state.bidder->joining_origin,
*interest_group.trusted_bidding_signals_url,
*interest_group.trusted_bidding_signals_coordinator,
interest_group.trusted_bidding_signals_keys,
@ -5603,8 +5604,8 @@ void InterestGroupAuction::ScoreBid(std::unique_ptr<Bid> bid) {
->RequestTrustedScoringSignals(
url_loader_factory_,
auction_worklet_manager_->GetFrameTreeNodeID(),
main_frame_origin_, ip_address_space_, config_->seller,
*config_->trusted_scoring_signals_url,
devtools_auction_id_, main_frame_origin_, ip_address_space_,
config_->seller, *config_->trusted_scoring_signals_url,
*config_->non_shared_params.trusted_scoring_signals_coordinator,
bid->interest_group->owner,
bid->bid_state->bidder->joining_origin, bid->ad_descriptor.url,

@ -17,6 +17,7 @@
#include <vector>
#include "base/check.h"
#include "base/containers/flat_set.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/location.h"
@ -207,6 +208,18 @@ struct TrustedSignalsCacheImpl::Fetch {
explicit Fetch(TrustedSignalsCacheImpl* trusted_signals_cache)
: weak_ptr_factory(trusted_signals_cache) {}
// Adds devtools auction ID to the Fetch, if the Fetch hasn't yet started.
// Note that devtools IDs cannot currently be removed from fetches, to make
// bookkeeping simpler, and are only logged on fetch start.
void AddDevtoolsAuctionId(const std::string& devtools_auction_id) {
// If fetch has started, do nothing.
if (fetcher) {
return;
}
devtools_auction_ids.insert(devtools_auction_id);
}
CompressionGroupMap compression_groups;
std::unique_ptr<TrustedSignalsFetcher> fetcher;
@ -218,6 +231,13 @@ struct TrustedSignalsCacheImpl::Fetch {
bool can_start = false;
std::optional<BiddingAndAuctionServerKey> coordinator_key;
// Devtools IDs of all associated auctions. They're all logged on fetch start,
// and the set is permanently cleared. Use `flat_set` because expected use
// case is a few Fetches shared by a lot of IGs in a small number of auctions,
// so most insertion attempts should not modify the set, and the better lookup
// performance seems more likely to matter.
base::flat_set<std::string> devtools_auction_ids;
// Weak reference to the TrustedSignalsCacheImpl. Used for calls to
// GetCoordinatorKeyCallback, and delayed calls to set `can_start` to true, so
// that destroying the fetch aborts the callback.
@ -821,6 +841,7 @@ std::unique_ptr<TrustedSignalsCacheImpl::Handle>
TrustedSignalsCacheImpl::RequestTrustedBiddingSignals(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
FrameTreeNodeId frame_tree_node_id,
const std::string& devtools_auction_id,
const url::Origin& main_frame_origin,
network::mojom::IPAddressSpace ip_address_space,
const url::Origin& interest_group_owner,
@ -854,11 +875,13 @@ TrustedSignalsCacheImpl::RequestTrustedBiddingSignals(
// If `cache_entry`'s Fetch hasn't yet started, update the BiddingCacheEntry
// to include any new keys, and return the entry's CompressionGroupData. The
// Fetch will get the updated keys when it's started, so it does not need to
// be modified.
// be modified, other than adding `devtools_auction_id`.
if (!compression_group_data->has_data() &&
!compression_group_data->fetch()->second.fetcher) {
cache_entry->AddInterestGroup(interest_group_name,
trusted_bidding_signals_keys);
compression_group_data->fetch()->second.AddDevtoolsAuctionId(
devtools_auction_id);
partition_id = cache_entry->partition_id;
return std::make_unique<Handle>(this,
scoped_refptr(compression_group_data));
@ -906,6 +929,7 @@ TrustedSignalsCacheImpl::RequestTrustedBiddingSignals(
scoped_refptr<CompressionGroupData> compression_group_data =
FindOrCreateCompressionGroupDataAndQueueFetch(
cache_entry_it->first.fetch_key, cache_entry_it->first.joining_origin,
devtools_auction_id,
/*interest_group_owner_if_scoring_signals=*/std::nullopt);
// The only thing left to do is set up pointers so objects can look up each
@ -930,6 +954,7 @@ std::unique_ptr<TrustedSignalsCacheImpl::Handle>
TrustedSignalsCacheImpl::RequestTrustedScoringSignals(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
FrameTreeNodeId frame_tree_node_id,
const std::string& devtools_auction_id,
const url::Origin& main_frame_origin,
network::mojom::IPAddressSpace ip_address_space,
const url::Origin& seller,
@ -960,6 +985,11 @@ TrustedSignalsCacheImpl::RequestTrustedScoringSignals(
// all parameters are in the key, which must match exactly.
if (!compression_group_data->has_data() ||
!compression_group_data->IsExpired()) {
// If there's a pending fetch, need to call AddDevtoolsAuctionId().
if (!compression_group_data->has_data()) {
compression_group_data->fetch()->second.AddDevtoolsAuctionId(
devtools_auction_id);
}
partition_id = cache_entry->partition_id;
return std::make_unique<Handle>(this,
scoped_refptr(compression_group_data));
@ -990,7 +1020,7 @@ TrustedSignalsCacheImpl::RequestTrustedScoringSignals(
scoped_refptr<CompressionGroupData> compression_group_data =
FindOrCreateCompressionGroupDataAndQueueFetch(
cache_entry_it->first.fetch_key, cache_entry_it->first.joining_origin,
interest_group_owner);
devtools_auction_id, interest_group_owner);
// The only thing left to do is set up pointers so objects can look up each
// other and return the result. When it's time to send a request, the Fetch
@ -1014,6 +1044,7 @@ scoped_refptr<TrustedSignalsCacheImpl::CompressionGroupData>
TrustedSignalsCacheImpl::FindOrCreateCompressionGroupDataAndQueueFetch(
const FetchKey& fetch_key,
const url::Origin& joining_origin,
const std::string& devtools_auction_id,
base::optional_ref<const url::Origin>
interest_group_owner_if_scoring_signals) {
// If there are any Fetches with the correct FetchKey, check if the last one
@ -1054,6 +1085,7 @@ TrustedSignalsCacheImpl::FindOrCreateCompressionGroupDataAndQueueFetch(
}
Fetch* fetch = &fetch_it->second;
fetch->AddDevtoolsAuctionId(devtools_auction_id);
// Now that we have a matching Fetch, check if there's an existing compression
// group that can be reused.
@ -1229,7 +1261,8 @@ void TrustedSignalsCacheImpl::StartBiddingSignalsFetch(
}
fetch->fetcher->FetchBiddingSignals(
fetch_key->url_loader_factory.get(), fetch_key->frame_tree_node_id,
fetch_key->main_frame_origin, fetch_key->ip_address_space,
std::move(fetch->devtools_auction_ids), fetch_key->main_frame_origin,
fetch_key->ip_address_space,
GetNetworkPartitionNonce(fetch_key->network_partition_nonce_key),
fetch_key->script_origin(), fetch_key->trusted_signals_url(),
*fetch->coordinator_key, bidding_partition_map,
@ -1275,12 +1308,14 @@ void TrustedSignalsCacheImpl::StartScoringSignalsFetch(
}
fetch->fetcher->FetchScoringSignals(
fetch_key->url_loader_factory.get(), fetch_key->frame_tree_node_id,
fetch_key->main_frame_origin, fetch_key->ip_address_space,
std::move(fetch->devtools_auction_ids), fetch_key->main_frame_origin,
fetch_key->ip_address_space,
GetNetworkPartitionNonce(fetch_key->network_partition_nonce_key),
fetch_key->script_origin(), fetch_key->trusted_signals_url(),
*fetch->coordinator_key, scoring_partition_map,
base::BindOnce(&TrustedSignalsCacheImpl::OnFetchComplete,
base::Unretained(this), fetch_it));
fetch->devtools_auction_ids.clear();
}
void TrustedSignalsCacheImpl::OnFetchComplete(

@ -250,6 +250,7 @@ class CONTENT_EXPORT TrustedSignalsCacheImpl
std::unique_ptr<Handle> RequestTrustedBiddingSignals(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
FrameTreeNodeId frame_tree_node_id,
const std::string& devtools_auction_id,
const url::Origin& main_frame_origin,
network::mojom::IPAddressSpace ip_address_space,
const url::Origin& interest_group_owner,
@ -285,6 +286,7 @@ class CONTENT_EXPORT TrustedSignalsCacheImpl
std::unique_ptr<TrustedSignalsCacheImpl::Handle> RequestTrustedScoringSignals(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
FrameTreeNodeId frame_tree_node_id,
const std::string& devtools_auction_id,
const url::Origin& main_frame_origin,
network::mojom::IPAddressSpace ip_address_space,
const url::Origin& seller,
@ -590,6 +592,7 @@ class CONTENT_EXPORT TrustedSignalsCacheImpl
FindOrCreateCompressionGroupDataAndQueueFetch(
const FetchKey& fetch_key,
const url::Origin& joining_origin,
const std::string& devtools_auction_id,
base::optional_ref<const url::Origin>
interest_group_owner_if_scoring_signals);

@ -16,6 +16,7 @@
#include "base/check.h"
#include "base/containers/contains.h"
#include "base/containers/flat_set.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/strcat.h"
@ -89,6 +90,9 @@ std::string CreateString(std::uint32_t i, size_t length = 3) {
struct BiddingParams {
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory;
FrameTreeNodeId frame_tree_node_id;
// Actual requests may only have a single devtools ID, but this struct is also
// be used to represent the result of multiple merged requests.
std::set<std::string> devtools_auction_ids{"devtools_auction_id1"};
url::Origin main_frame_origin;
network::mojom::IPAddressSpace ip_address_space =
network::mojom::IPAddressSpace::kPublic;
@ -114,6 +118,9 @@ struct BiddingParams {
struct ScoringParams {
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory;
FrameTreeNodeId frame_tree_node_id;
// While ScoringParams are never merged, so this will always only have one ID,
// use a set here to mirror BiddingParams.
std::set<std::string> devtools_auction_ids{"devtools_auction_id1"};
url::Origin main_frame_origin;
network::mojom::IPAddressSpace ip_address_space =
network::mojom::IPAddressSpace::kPublic;
@ -180,6 +187,7 @@ class TestTrustedSignalsCache : public TrustedSignalsCacheImpl {
BiddingAndAuctionServerKey bidding_and_auction_key;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory;
FrameTreeNodeId frame_tree_node_id;
base::flat_set<std::string> devtools_auction_ids;
url::Origin main_frame_origin;
network::mojom::IPAddressSpace ip_address_space;
base::UnguessableToken network_partition_nonce;
@ -198,6 +206,7 @@ class TestTrustedSignalsCache : public TrustedSignalsCacheImpl {
BiddingAndAuctionServerKey bidding_and_auction_key;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory;
FrameTreeNodeId frame_tree_node_id;
base::flat_set<std::string> devtools_auction_ids;
url::Origin main_frame_origin;
network::mojom::IPAddressSpace ip_address_space;
base::UnguessableToken network_partition_nonce;
@ -220,6 +229,7 @@ class TestTrustedSignalsCache : public TrustedSignalsCacheImpl {
void FetchBiddingSignals(
network::mojom::URLLoaderFactory* url_loader_factory,
FrameTreeNodeId frame_tree_node_id,
base::flat_set<std::string> devtools_auction_ids,
const url::Origin& main_frame_origin,
network::mojom::IPAddressSpace ip_address_space,
base::UnguessableToken network_partition_nonce,
@ -250,15 +260,16 @@ class TestTrustedSignalsCache : public TrustedSignalsCacheImpl {
cache_->OnPendingBiddingSignalsFetch(PendingBiddingSignalsFetch(
trusted_signals_url, bidding_and_auction_key,
static_cast<network::SharedURLLoaderFactory*>(url_loader_factory),
frame_tree_node_id, main_frame_origin, ip_address_space,
network_partition_nonce, script_origin,
std::move(compression_groups_copy), std::move(callback),
weak_ptr_factory_.GetWeakPtr()));
frame_tree_node_id, std::move(devtools_auction_ids),
main_frame_origin, ip_address_space, network_partition_nonce,
script_origin, std::move(compression_groups_copy),
std::move(callback), weak_ptr_factory_.GetWeakPtr()));
}
void FetchScoringSignals(
network::mojom::URLLoaderFactory* url_loader_factory,
FrameTreeNodeId frame_tree_node_id,
base::flat_set<std::string> devtools_auction_ids,
const url::Origin& main_frame_origin,
network::mojom::IPAddressSpace ip_address_space,
base::UnguessableToken network_partition_nonce,
@ -290,10 +301,10 @@ class TestTrustedSignalsCache : public TrustedSignalsCacheImpl {
trusted_signals_url, bidding_and_auction_key,
reinterpret_cast<network::SharedURLLoaderFactory*>(
url_loader_factory),
frame_tree_node_id, main_frame_origin, ip_address_space,
network_partition_nonce, script_origin,
std::move(compression_groups_copy), std::move(callback),
weak_ptr_factory_.GetWeakPtr()));
frame_tree_node_id, std::move(devtools_auction_ids),
main_frame_origin, ip_address_space, network_partition_nonce,
script_origin, std::move(compression_groups_copy),
std::move(callback), weak_ptr_factory_.GetWeakPtr()));
}
const raw_ptr<TestTrustedSignalsCache> cache_;
@ -534,6 +545,8 @@ void ValidateFetchParams(const FetcherFetchType& fetch,
int expected_partition_id) {
EXPECT_EQ(fetch.url_loader_factory, params.url_loader_factory);
EXPECT_EQ(fetch.frame_tree_node_id, params.frame_tree_node_id);
EXPECT_THAT(fetch.devtools_auction_ids,
testing::ElementsAreArray(params.devtools_auction_ids));
EXPECT_EQ(fetch.main_frame_origin, params.main_frame_origin);
EXPECT_EQ(fetch.ip_address_space, params.ip_address_space);
EXPECT_EQ(fetch.trusted_signals_url, params.trusted_signals_url);
@ -894,6 +907,8 @@ class TrustedSignalsCacheTest : public testing::Test {
TestCase out;
out.params1 = CreateDefaultParams();
out.params2 = CreateDefaultParams();
out.params2.devtools_auction_ids = {"devtools_auction_id2"};
return out;
}
@ -1214,6 +1229,7 @@ class TrustedSignalsCacheTest : public testing::Test {
BiddingParams merged_bidding_params{
bidding_params1.url_loader_factory,
bidding_params1.frame_tree_node_id,
bidding_params1.devtools_auction_ids,
bidding_params1.main_frame_origin,
bidding_params1.ip_address_space,
bidding_params1.script_origin,
@ -1225,6 +1241,9 @@ class TrustedSignalsCacheTest : public testing::Test {
bidding_params1.trusted_bidding_signals_keys,
bidding_params1.additional_params.Clone()};
merged_bidding_params.devtools_auction_ids.insert(
bidding_params2.devtools_auction_ids.begin(),
bidding_params2.devtools_auction_ids.end());
merged_bidding_params.interest_group_names.insert(
bidding_params2.interest_group_names.begin(),
bidding_params2.interest_group_names.end());
@ -1265,6 +1284,7 @@ class TrustedSignalsCacheTest : public testing::Test {
CHECK_EQ(1u, bidding_params.interest_group_names.size());
auto handle = trusted_signals_cache_->RequestTrustedBiddingSignals(
bidding_params.url_loader_factory, bidding_params.frame_tree_node_id,
*bidding_params.devtools_auction_ids.begin(),
bidding_params.main_frame_origin, bidding_params.ip_address_space,
bidding_params.script_origin,
*bidding_params.interest_group_names.begin(),
@ -1291,6 +1311,7 @@ class TrustedSignalsCacheTest : public testing::Test {
int partition_id = -1;
auto handle = trusted_signals_cache_->RequestTrustedScoringSignals(
scoring_params.url_loader_factory, scoring_params.frame_tree_node_id,
*scoring_params.devtools_auction_ids.begin(),
scoring_params.main_frame_origin, scoring_params.ip_address_space,
scoring_params.script_origin, scoring_params.trusted_signals_url,
scoring_params.coordinator, scoring_params.interest_group_owner,
@ -2793,14 +2814,14 @@ TYPED_TEST(TrustedSignalsCacheTest, DifferentParamsAfterFetchComplete) {
// Only one fetch is made.
TYPED_TEST(TrustedSignalsCacheTest,
DifferentParamsCancelSecondBeforeFetchStart) {
for (const auto& test_case : this->CreateTestCases()) {
for (auto& test_case : this->CreateTestCases()) {
SCOPED_TRACE(test_case.description);
// Start with a clean slate for each test. Not strictly necessary, but
// limits what's under test a bit.
this->CreateCache();
const auto& params1 = test_case.params1;
const auto& params2 = test_case.params2;
auto params1 = std::move(test_case.params1);
auto params2 = std::move(test_case.params2);
// Don't bother to compare handles here - that's covered by another test.
auto [handle1, partition_id1] = this->RequestTrustedSignals(params1);
@ -2817,7 +2838,15 @@ TYPED_TEST(TrustedSignalsCacheTest,
// both to the caller and to the created fetches.
case RequestRelation::kDifferentFetches:
case RequestRelation::kDifferentCompressionGroups: {
// Fetch should not be affected by the second (now cancelled) fetch.
// Fetch should not be affected by the first (cancelled) fetch, other
// than including its devtools auction ID in the different compression
// group case.
if (test_case.request_relation ==
RequestRelation::kDifferentCompressionGroups) {
params1.devtools_auction_ids.insert(
params2.devtools_auction_ids.begin(),
params2.devtools_auction_ids.end());
}
ValidateFetchParams(fetch1, params1,
/*expected_compression_group_id=*/0, partition_id1);
RespondToFetchWithSuccess(fetch1);
@ -2852,6 +2881,10 @@ TYPED_TEST(TrustedSignalsCacheTest,
EXPECT_EQ(fetch1.trusted_signals_url, params1.trusted_signals_url);
ASSERT_EQ(fetch1.compression_groups.size(), 1u);
EXPECT_EQ(fetch1.compression_groups.begin()->first, 0);
EXPECT_THAT(fetch1.devtools_auction_ids,
testing::UnorderedElementsAre(
*params1.devtools_auction_ids.begin(),
*params2.devtools_auction_ids.begin()));
const auto& partitions = fetch1.compression_groups.begin()->second;
ASSERT_EQ(partitions.size(), 2u);
@ -2912,14 +2945,14 @@ TYPED_TEST(TrustedSignalsCacheTest,
// partition 1 request.
TYPED_TEST(TrustedSignalsCacheTest,
DifferentParamsCancelFirstBeforeFetchStart) {
for (const auto& test_case : this->CreateTestCases()) {
for (auto& test_case : this->CreateTestCases()) {
SCOPED_TRACE(test_case.description);
// Start with a clean slate for each test. Not strictly necessary, but
// limits what's under test a bit.
this->CreateCache();
const auto& params1 = test_case.params1;
const auto& params2 = test_case.params2;
auto params1 = std::move(test_case.params1);
auto params2 = std::move(test_case.params2);
// Don't bother to compare handles here - that's covered by another test.
auto [handle1, partition_id1] = this->RequestTrustedSignals(params1);
@ -2936,7 +2969,15 @@ TYPED_TEST(TrustedSignalsCacheTest,
// same both to the caller and to the created fetches.
case RequestRelation::kDifferentFetches:
case RequestRelation::kDifferentCompressionGroups: {
// Fetch should not be affected by the first (cancelled) fetch.
// Fetch should not be affected by the first (cancelled) fetch, other
// than including its devtools auction ID in the different compression
// group case.
if (test_case.request_relation ==
RequestRelation::kDifferentCompressionGroups) {
params2.devtools_auction_ids.insert(
params1.devtools_auction_ids.begin(),
params1.devtools_auction_ids.end());
}
ValidateFetchParams(fetch1, params2,
/*expected_compression_group_id=*/0, partition_id2);
RespondToFetchWithSuccess(fetch1);
@ -2969,6 +3010,10 @@ TYPED_TEST(TrustedSignalsCacheTest,
EXPECT_EQ(fetch1.trusted_signals_url, params2.trusted_signals_url);
ASSERT_EQ(fetch1.compression_groups.size(), 1u);
EXPECT_EQ(fetch1.compression_groups.begin()->first, 0);
EXPECT_THAT(fetch1.devtools_auction_ids,
testing::UnorderedElementsAre(
*params1.devtools_auction_ids.begin(),
*params2.devtools_auction_ids.begin()));
const auto& partitions = fetch1.compression_groups.begin()->second;
ASSERT_EQ(partitions.size(), 2u);

@ -15,6 +15,7 @@
#include <vector>
#include "base/check.h"
#include "base/containers/flat_set.h"
#include "base/containers/span.h"
#include "base/containers/span_reader.h"
#include "base/containers/span_writer.h"
@ -30,7 +31,9 @@
#include "bidding_and_auction_server_key_fetcher.h"
#include "components/cbor/values.h"
#include "components/cbor/writer.h"
#include "content/browser/devtools/devtools_instrumentation.h"
#include "content/browser/interest_group/auction_downloader_delegate.h"
#include "content/browser/interest_group/devtools_enums.h"
#include "content/browser/renderer_host/private_network_access_util.h"
#include "content/common/content_export.h"
#include "content/public/browser/frame_tree_node_id.h"
@ -307,6 +310,7 @@ TrustedSignalsFetcher::~TrustedSignalsFetcher() = default;
void TrustedSignalsFetcher::FetchBiddingSignals(
network::mojom::URLLoaderFactory* url_loader_factory,
FrameTreeNodeId frame_tree_node_id,
base::flat_set<std::string> devtools_auction_ids,
const url::Origin& main_frame_origin,
network::mojom::IPAddressSpace ip_address_space,
base::UnguessableToken network_partition_nonce,
@ -316,7 +320,8 @@ void TrustedSignalsFetcher::FetchBiddingSignals(
const std::map<int, std::vector<BiddingPartition>>& compression_groups,
Callback callback) {
EncryptRequestBodyAndStart(
url_loader_factory, frame_tree_node_id, main_frame_origin,
url_loader_factory, InterestGroupAuctionFetchType::kBidderTrustedSignals,
frame_tree_node_id, std::move(devtools_auction_ids), main_frame_origin,
ip_address_space, network_partition_nonce, script_origin,
trusted_bidding_signals_url, bidding_and_auction_key,
BuildSignalsRequestBody(main_frame_origin.host(), compression_groups),
@ -326,6 +331,7 @@ void TrustedSignalsFetcher::FetchBiddingSignals(
void TrustedSignalsFetcher::FetchScoringSignals(
network::mojom::URLLoaderFactory* url_loader_factory,
FrameTreeNodeId frame_tree_node_id,
base::flat_set<std::string> devtools_auction_ids,
const url::Origin& main_frame_origin,
network::mojom::IPAddressSpace ip_address_space,
base::UnguessableToken network_partition_nonce,
@ -335,7 +341,8 @@ void TrustedSignalsFetcher::FetchScoringSignals(
const std::map<int, std::vector<ScoringPartition>>& compression_groups,
Callback callback) {
EncryptRequestBodyAndStart(
url_loader_factory, frame_tree_node_id, main_frame_origin,
url_loader_factory, InterestGroupAuctionFetchType::kSellerTrustedSignals,
frame_tree_node_id, std::move(devtools_auction_ids), main_frame_origin,
ip_address_space, network_partition_nonce, script_origin,
trusted_scoring_signals_url, bidding_and_auction_key,
BuildSignalsRequestBody(main_frame_origin.host(), compression_groups),
@ -344,7 +351,9 @@ void TrustedSignalsFetcher::FetchScoringSignals(
void TrustedSignalsFetcher::EncryptRequestBodyAndStart(
network::mojom::URLLoaderFactory* url_loader_factory,
InterestGroupAuctionFetchType fetch_type,
FrameTreeNodeId frame_tree_node_id,
base::flat_set<std::string> devtools_auction_ids,
const url::Origin& main_frame_origin,
network::mojom::IPAddressSpace ip_address_space,
base::UnguessableToken network_partition_nonce,
@ -418,6 +427,13 @@ void TrustedSignalsFetcher::EncryptRequestBodyAndStart(
AuctionDownloaderDelegate::MaybeCreate(frame_tree_node_id));
ohttp_context_ = std::make_unique<quiche::ObliviousHttpRequest::Context>(
std::move(maybe_ciphertext_request_body).value().ReleaseContext());
if (frame_tree_node_id &&
devtools_instrumentation::NeedInterestGroupAuctionEvents(
frame_tree_node_id)) {
devtools_instrumentation::OnInterestGroupAuctionNetworkRequestCreated(
frame_tree_node_id, fetch_type, auction_downloader_->request_id(),
std::move(devtools_auction_ids).extract());
}
}
void TrustedSignalsFetcher::OnRequestComplete(

@ -14,6 +14,7 @@
#include <string_view>
#include <vector>
#include "base/containers/flat_set.h"
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
@ -21,6 +22,7 @@
#include "base/types/expected.h"
#include "base/unguessable_token.h"
#include "base/values.h"
#include "content/browser/interest_group/devtools_enums.h"
#include "content/common/content_export.h"
#include "content/public/browser/frame_tree_node_id.h"
#include "content/services/auction_worklet/public/mojom/trusted_signals_cache.mojom.h"
@ -156,7 +158,8 @@ class CONTENT_EXPORT TrustedSignalsFetcher {
TrustedSignalsFetcher(const TrustedSignalsFetcher&) = delete;
TrustedSignalsFetcher& operator=(const TrustedSignalsFetcher&) = delete;
// `frame_tree_node_id` is used to log events for devtools.
// `frame_tree_node_id` and `devtools_auction_ids` are used to log events for
// devtools, if needed.
//
// `main_frame_origin` and `network_partition_nonce` are used to create an
// IsolationInfo identifying the network partition to use.
@ -178,6 +181,7 @@ class CONTENT_EXPORT TrustedSignalsFetcher {
virtual void FetchBiddingSignals(
network::mojom::URLLoaderFactory* url_loader_factory,
FrameTreeNodeId frame_tree_node_id,
base::flat_set<std::string> devtools_auction_ids,
const url::Origin& main_frame_origin,
network::mojom::IPAddressSpace ip_address_space,
base::UnguessableToken network_partition_nonce,
@ -187,7 +191,8 @@ class CONTENT_EXPORT TrustedSignalsFetcher {
const std::map<int, std::vector<BiddingPartition>>& compression_groups,
Callback callback);
// `frame_tree_node_id` is used to log events for devtools.
// `frame_tree_node_id` and `devtools_auction_ids` are used to log events for
// devtools, if needed.
//
// `main_frame_origin` and `network_partition_nonce` are used to create an
// IsolationInfo identifying the network partition to use.
@ -206,6 +211,7 @@ class CONTENT_EXPORT TrustedSignalsFetcher {
virtual void FetchScoringSignals(
network::mojom::URLLoaderFactory* url_loader_factory,
FrameTreeNodeId frame_tree_node_id,
base::flat_set<std::string> devtools_auction_ids,
const url::Origin& main_frame_origin,
network::mojom::IPAddressSpace ip_address_space,
base::UnguessableToken network_partition_nonce,
@ -224,7 +230,9 @@ class CONTENT_EXPORT TrustedSignalsFetcher {
// this class.
void EncryptRequestBodyAndStart(
network::mojom::URLLoaderFactory* url_loader_factory,
InterestGroupAuctionFetchType fetch_type,
FrameTreeNodeId frame_tree_node_id,
base::flat_set<std::string> devtools_auction_ids,
const url::Origin& main_frame_origin,
network::mojom::IPAddressSpace ip_address_space,
base::UnguessableToken network_partition_nonce,

@ -15,6 +15,7 @@
#include <string>
#include <vector>
#include "base/containers/flat_set.h"
#include "base/containers/span.h"
#include "base/format_macros.h"
#include "base/functional/bind.h"
@ -276,9 +277,9 @@ class TrustedSignalsFetcherTest : public testing::Test {
TrustedSignalsFetcher::SignalsFetchResult out;
TrustedSignalsFetcher trusted_signals_fetcher;
trusted_signals_fetcher.FetchBiddingSignals(
url_loader_factory_.get(), FrameTreeNodeId(), kDefaultMainFrameOrigin,
network::mojom::IPAddressSpace::kPublic, network_partition_nonce_,
GetScriptOrigin(), url,
url_loader_factory_.get(), FrameTreeNodeId(), kAuctionDevtoolsIds,
kDefaultMainFrameOrigin, network::mojom::IPAddressSpace::kPublic,
network_partition_nonce_, GetScriptOrigin(), url,
BiddingAndAuctionServerKey{
std::string(reinterpret_cast<const char*>(kTestPublicKey),
sizeof(kTestPublicKey)),
@ -307,9 +308,9 @@ class TrustedSignalsFetcherTest : public testing::Test {
TrustedSignalsFetcher::SignalsFetchResult out;
TrustedSignalsFetcher trusted_signals_fetcher;
trusted_signals_fetcher.FetchScoringSignals(
url_loader_factory_.get(), FrameTreeNodeId(), kDefaultMainFrameOrigin,
network::mojom::IPAddressSpace::kPublic, network_partition_nonce_,
GetScriptOrigin(), url,
url_loader_factory_.get(), FrameTreeNodeId(), kAuctionDevtoolsIds,
kDefaultMainFrameOrigin, network::mojom::IPAddressSpace::kPublic,
network_partition_nonce_, GetScriptOrigin(), url,
BiddingAndAuctionServerKey{
std::string(reinterpret_cast<const char*>(kTestPublicKey),
sizeof(kTestPublicKey)),
@ -556,6 +557,9 @@ class TrustedSignalsFetcherTest : public testing::Test {
const std::string kTrustedScoringSignalsPath = "/scoring-signals";
const std::string kTrustedSignalsHost = "a.test";
// This value doesn't actually matter, as it's not tested by this file.
const base::flat_set<std::string> kAuctionDevtoolsIds{"auction_devtools_id"};
// Default values used by both both CreateBasicBiddingSignalsRequest() and
// CreateBasicScoringSignalsRequest(). They need to be fields of the test
// fixture to keep them alive, since the returned BiddingPartition holds onto
@ -2370,9 +2374,9 @@ TEST_F(TrustedSignalsFetcherTest, BiddingSignalsIsolationInfo) {
network::TestURLLoaderFactory url_loader_factory;
TrustedSignalsFetcher trusted_signals_fetcher;
trusted_signals_fetcher.FetchBiddingSignals(
&url_loader_factory, FrameTreeNodeId(), kDefaultMainFrameOrigin,
network::mojom::IPAddressSpace::kPublic, network_partition_nonce_,
GetScriptOrigin(), TrustedBiddingSignalsUrl(),
&url_loader_factory, FrameTreeNodeId(), kAuctionDevtoolsIds,
kDefaultMainFrameOrigin, network::mojom::IPAddressSpace::kPublic,
network_partition_nonce_, GetScriptOrigin(), TrustedBiddingSignalsUrl(),
BiddingAndAuctionServerKey{
std::string(reinterpret_cast<const char*>(kTestPublicKey),
sizeof(kTestPublicKey)),
@ -2407,9 +2411,9 @@ TEST_F(TrustedSignalsFetcherTest, ScoringSignalsIsolationInfo) {
network::TestURLLoaderFactory url_loader_factory;
TrustedSignalsFetcher trusted_signals_fetcher;
trusted_signals_fetcher.FetchScoringSignals(
&url_loader_factory, FrameTreeNodeId(), kDefaultMainFrameOrigin,
network::mojom::IPAddressSpace::kPublic, network_partition_nonce_,
GetScriptOrigin(), TrustedScoringSignalsUrl(),
&url_loader_factory, FrameTreeNodeId(), kAuctionDevtoolsIds,
kDefaultMainFrameOrigin, network::mojom::IPAddressSpace::kPublic,
network_partition_nonce_, GetScriptOrigin(), TrustedScoringSignalsUrl(),
BiddingAndAuctionServerKey{
std::string(reinterpret_cast<const char*>(kTestPublicKey),
sizeof(kTestPublicKey)),
@ -2465,9 +2469,9 @@ TEST_F(TrustedSignalsFetcherTest, ScoringSignalsClientSecurityState) {
network::TestURLLoaderFactory url_loader_factory;
TrustedSignalsFetcher trusted_signals_fetcher;
trusted_signals_fetcher.FetchScoringSignals(
&url_loader_factory, FrameTreeNodeId(), kDefaultMainFrameOrigin,
ip_address_space, network_partition_nonce_, GetScriptOrigin(),
TrustedScoringSignalsUrl(),
&url_loader_factory, FrameTreeNodeId(), kAuctionDevtoolsIds,
kDefaultMainFrameOrigin, ip_address_space, network_partition_nonce_,
GetScriptOrigin(), TrustedScoringSignalsUrl(),
BiddingAndAuctionServerKey{
std::string(reinterpret_cast<const char*>(kTestPublicKey),
sizeof(kTestPublicKey)),
@ -2555,7 +2559,7 @@ TEST(TrustedSignalsFetcherTimeoutTest, BiddingSignalsTimeout) {
TrustedSignalsFetcher::SignalsFetchResult out;
TrustedSignalsFetcher trusted_signals_fetcher;
trusted_signals_fetcher.FetchBiddingSignals(
&url_loader_factory, FrameTreeNodeId(),
&url_loader_factory, FrameTreeNodeId(), {"auction_devtools_id"},
/*main_frame_origin=*/kSignalsOrigin,
network::mojom::IPAddressSpace::kPublic,
/*network_partition_nonce=*/base::UnguessableToken::Create(),

@ -146,6 +146,8 @@ class CONTENT_EXPORT AuctionDownloader {
const GURL& source_url() const { return source_url_; }
const std::string& request_id() const { return request_id_; }
// Checks if the response is allowed for Protected Audience-related requests,
// based on the headers. Returns an error string and sets `status_out` on
// error.
@ -205,7 +207,7 @@ class CONTENT_EXPORT AuctionDownloader {
const MimeType mime_type_;
const std::optional<size_t> num_igs_for_trusted_bidding_signals_kvv1_;
// A UnguessableToken string to be used in devtools.
std::string request_id_;
const std::string request_id_;
// The time the response started, used for UMA.
std::optional<base::TimeTicks> response_started_time_;

@ -29,6 +29,14 @@ interestGroupAuctionNetworkRequestCreated {
type : bidderJs
url : https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php
}
interestGroupAuctionNetworkRequestCreated {
auctions : [
[0] : 1
]
requestId : <string>
type : bidderTrustedSignals
url : https://a.test:8443/inspector-protocol/resources/fledge_bidding_signals.js.php
}
interestGroupAuctionNetworkRequestCreated {
auctions : [
[0] : 1
@ -37,6 +45,14 @@ interestGroupAuctionNetworkRequestCreated {
type : sellerJs
url : https://a.test:8443/inspector-protocol/resources/fledge_decision_logic.js.php
}
interestGroupAuctionNetworkRequestCreated {
auctions : [
[0] : 1
]
requestId : <string>
type : sellerTrustedSignals
url : https://a.test:8443/inspector-protocol/resources/fledge_scoring_signals.js.php
}
interestGroupAccessed {
accessTime : <number>
name : 0
@ -57,6 +73,7 @@ interestGroupDetails {
name : 0
ownerOrigin : https://a.test:8443
priority : 0
trustedBiddingSignalsURL : https://a.test:8443/inspector-protocol/resources/fledge_bidding_signals.js.php
}
interestGroupAccessed {
accessTime : <number>
@ -78,6 +95,7 @@ interestGroupDetails {
name : 1
ownerOrigin : https://a.test:8443
priority : 0
trustedBiddingSignalsURL : https://a.test:8443/inspector-protocol/resources/fledge_bidding_signals.js.php
}
interestGroupAccessed {
accessTime : <number>
@ -99,6 +117,7 @@ interestGroupDetails {
name : 0
ownerOrigin : https://a.test:8443
priority : 0
trustedBiddingSignalsURL : https://a.test:8443/inspector-protocol/resources/fledge_bidding_signals.js.php
}
interestGroupAccessed {
accessTime : <number>
@ -120,6 +139,7 @@ interestGroupDetails {
name : 1
ownerOrigin : https://a.test:8443
priority : 0
trustedBiddingSignalsURL : https://a.test:8443/inspector-protocol/resources/fledge_bidding_signals.js.php
}
interestGroupAccessed {
accessTime : <number>
@ -142,6 +162,7 @@ interestGroupDetails {
name : 0
ownerOrigin : https://a.test:8443
priority : 0
trustedBiddingSignalsURL : https://a.test:8443/inspector-protocol/resources/fledge_bidding_signals.js.php
}
interestGroupAccessed {
accessTime : <number>
@ -164,6 +185,7 @@ interestGroupDetails {
name : 1
ownerOrigin : https://a.test:8443
priority : 0
trustedBiddingSignalsURL : https://a.test:8443/inspector-protocol/resources/fledge_bidding_signals.js.php
}
interestGroupAccessed {
accessTime : <number>
@ -185,6 +207,7 @@ interestGroupDetails {
name : 1
ownerOrigin : https://a.test:8443
priority : 0
trustedBiddingSignalsURL : https://a.test:8443/inspector-protocol/resources/fledge_bidding_signals.js.php
}
Stop Tracking IG Events
Logged IG events:
@ -216,6 +239,14 @@ interestGroupAuctionNetworkRequestCreated {
type : bidderJs
url : https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php
}
interestGroupAuctionNetworkRequestCreated {
auctions : [
[0] : 2
]
requestId : <string>
type : bidderTrustedSignals
url : https://a.test:8443/inspector-protocol/resources/fledge_bidding_signals.js.php
}
interestGroupAuctionNetworkRequestCreated {
auctions : [
[0] : 2
@ -224,6 +255,14 @@ interestGroupAuctionNetworkRequestCreated {
type : sellerJs
url : https://a.test:8443/inspector-protocol/resources/fledge_decision_logic.js.php
}
interestGroupAuctionNetworkRequestCreated {
auctions : [
[0] : 2
]
requestId : <string>
type : sellerTrustedSignals
url : https://a.test:8443/inspector-protocol/resources/fledge_scoring_signals.js.php
}
Stop Tracking Auction Events
Logged IG events:
Test Done

@ -1,9 +1,33 @@
const publicKeyConfig = `{
"originScopedKeys": {
"https://a.test:8443": {
"keys":[{
"id":"14345678-9abc-def0-1234-56789abcdef0",
"key":"oV9AZYb6xHuZWXDxhdnYkcdNzx65Gn1QpYsBaD5gBS0="}]
}
}
}`;
// 32 random'ish bits in hex.
function rand32() {
return Math.abs((Math.random() * 0x100000000) & 0xFFFFFFFF).toString(16)
}
(async function(/** @type {import('test_runner').TestRunner} */ testRunner) {
const {dp, session, page} = await testRunner.startBlank(
`Tests that interest groups are read and cleared.`);
const baseOrigin = 'https://a.test:8443/';
const base = baseOrigin + 'inspector-protocol/resources/';
// We generate a random coordinator hostname to isolate tests.
let coordinator = "https://cd" + rand32() + rand32() + rand32() + rand32() +
".test";
await dp.Browser.addPrivacySandboxCoordinatorKeyConfig({
api: 'TrustedKeyValue',
coordinatorOrigin: coordinator,
keyConfig: publicKeyConfig
});
// Order by phase.
function typeSortKey(type) {
switch (type) {
@ -64,6 +88,8 @@
name: ${id},
owner: "${baseOrigin}",
biddingLogicURL: "${base}fledge_bidding_logic.js.php",
trustedBiddingSignalsURL: "${base}fledge_bidding_signals.js.php",
trustedBiddingSignalsCoordinator: "${coordinator}",
ads: [{
renderURL: 'https://example.com/render' + ${id},
metadata: {ad: 'metadata', here: [1, 2, 3]}
@ -77,6 +103,8 @@
(async function() {
config = await navigator.runAdAuction({
decisionLogicURL: "${base}fledge_decision_logic.js.php",
trustedScoringSignalsURL: "${base}fledge_scoring_signals.js.php",
trustedScoringSignalsCoordinator: "${coordinator}",
seller: "${baseOrigin}",
interestGroupBuyers: ["${baseOrigin}"],
resolveToConfig: true});