0

FLEDGE: extend information reported about auctions to devtools

A new, frame-specific interestGroupAuctionEvent is added, which reports auction configuration, structure of component auctions, and names each auction (including component ones) with a unique ID.

The existing interestGroupAccessed events that take place as part of auctions now specify which auction they are part of, and provide information on bid values. Bids taking place in top-level auctions are now also reported.

Bug: 1516642
Fuchsia-Binary-Size: Size increase is unavoidable.
Change-Id: I6109f2e3d60d52421b5be445f19e5faa74ab9e3c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5153907
Commit-Queue: Maks Orlovich <morlovich@chromium.org>
Reviewed-by: Andrey Kosyakov <caseq@chromium.org>
Reviewed-by: Ayu Ishii <ayui@chromium.org>
Reviewed-by: Russ Hamilton <behamilton@google.com>
Cr-Commit-Position: refs/heads/main@{#1249552}
This commit is contained in:
Maks Orlovich
2024-01-19 21:49:46 +00:00
committed by Chromium LUCI CQ
parent 533d6ba7c5
commit a7d97ed824
23 changed files with 811 additions and 285 deletions

@@ -1198,6 +1198,7 @@ source_set("browser") {
"interest_group/debuggable_auction_worklet.h", "interest_group/debuggable_auction_worklet.h",
"interest_group/debuggable_auction_worklet_tracker.cc", "interest_group/debuggable_auction_worklet_tracker.cc",
"interest_group/debuggable_auction_worklet_tracker.h", "interest_group/debuggable_auction_worklet_tracker.h",
"interest_group/devtools_enums.h",
"interest_group/header_direct_from_seller_signals.cc", "interest_group/header_direct_from_seller_signals.cc",
"interest_group/header_direct_from_seller_signals.h", "interest_group/header_direct_from_seller_signals.h",
"interest_group/interest_group_auction.cc", "interest_group/interest_group_auction.cc",

@@ -29,6 +29,7 @@
#include "content/browser/devtools/protocol/page_handler.h" #include "content/browser/devtools/protocol/page_handler.h"
#include "content/browser/devtools/protocol/preload_handler.h" #include "content/browser/devtools/protocol/preload_handler.h"
#include "content/browser/devtools/protocol/security_handler.h" #include "content/browser/devtools/protocol/security_handler.h"
#include "content/browser/devtools/protocol/storage_handler.h"
#include "content/browser/devtools/protocol/target_handler.h" #include "content/browser/devtools/protocol/target_handler.h"
#include "content/browser/devtools/protocol/tracing_handler.h" #include "content/browser/devtools/protocol/tracing_handler.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h" #include "content/browser/devtools/render_frame_devtools_agent_host.h"
@@ -1526,6 +1527,36 @@ void OnAuctionWorkletNetworkRequestComplete(
status); status);
} }
bool NeedInterestGroupAuctionEvents(int frame_tree_node_id) {
FrameTreeNode* ftn = FrameTreeNode::GloballyFindByID(frame_tree_node_id);
if (!ftn) {
return false;
}
DevToolsAgentHostImpl* agent_host = RenderFrameDevToolsAgentHost::GetFor(ftn);
if (!agent_host) {
return false;
}
for (auto* storage : protocol::StorageHandler::ForAgentHost(agent_host)) {
if (storage->interest_group_auction_tracking_enabled()) {
return true;
}
}
return false;
}
void OnInterestGroupAuctionEventOccurred(
int frame_tree_node_id,
base::Time event_time,
InterestGroupAuctionEventType type,
const std::string& unique_auction_id,
base::optional_ref<const std::string> parent_auction_id,
const base::Value::Dict& auction_config) {
DispatchToAgents(
frame_tree_node_id,
&protocol::StorageHandler::NotifyInterestGroupAuctionEventOccurred,
event_time, type, unique_auction_id, parent_auction_id, auction_config);
}
void OnNavigationRequestWillBeSent( void OnNavigationRequestWillBeSent(
const NavigationRequest& navigation_request) { const NavigationRequest& navigation_request) {
// Note this intentionally deviates from the usual instrumentation signal // Note this intentionally deviates from the usual instrumentation signal

@@ -12,8 +12,10 @@
#include <optional> #include <optional>
#include <vector> #include <vector>
#include "base/values.h"
#include "content/browser/devtools/devtools_device_request_prompt_info.h" #include "content/browser/devtools/devtools_device_request_prompt_info.h"
#include "content/browser/devtools/devtools_throttle_handle.h" #include "content/browser/devtools/devtools_throttle_handle.h"
#include "content/browser/interest_group/devtools_enums.h"
#include "content/browser/preloading/prefetch/prefetch_status.h" #include "content/browser/preloading/prefetch/prefetch_status.h"
#include "content/browser/preloading/prerender/prerender_final_status.h" #include "content/browser/preloading/prerender/prerender_final_status.h"
#include "content/browser/renderer_host/back_forward_cache_impl.h" #include "content/browser/renderer_host/back_forward_cache_impl.h"
@@ -229,6 +231,16 @@ void OnAuctionWorkletNetworkRequestComplete(
const std::string& request_id, const std::string& request_id,
const network::URLLoaderCompletionStatus& status); const network::URLLoaderCompletionStatus& status);
bool NeedInterestGroupAuctionEvents(int frame_tree_node_id);
void OnInterestGroupAuctionEventOccurred(
int frame_tree_node_id,
base::Time event_time,
content::InterestGroupAuctionEventType type,
const std::string& unique_auction_id,
base::optional_ref<const std::string> parent_auction_id,
const base::Value::Dict& auction_config);
bool ShouldBypassCSP(const NavigationRequest& nav_request); bool ShouldBypassCSP(const NavigationRequest& nav_request);
void ApplyNetworkOverridesForDownload( void ApplyNetworkOverridesForDownload(

@@ -450,6 +450,12 @@ StorageHandler::~StorageHandler() {
DCHECK(!indexed_db_observer_); DCHECK(!indexed_db_observer_);
} }
// static
std::vector<StorageHandler*> StorageHandler::ForAgentHost(
DevToolsAgentHostImpl* host) {
return host->HandlersByName<StorageHandler>(Storage::Metainfo::domainName);
}
void StorageHandler::Wire(UberDispatcher* dispatcher) { void StorageHandler::Wire(UberDispatcher* dispatcher) {
frontend_ = std::make_unique<Storage::Frontend>(dispatcher->channel()); frontend_ = std::make_unique<Storage::Frontend>(dispatcher->channel());
Storage::Dispatcher::wire(dispatcher, this); Storage::Dispatcher::wire(dispatcher, this);
@@ -1016,10 +1022,14 @@ void StorageHandler::ClearTrustTokens(
} }
void StorageHandler::OnInterestGroupAccessed( void StorageHandler::OnInterestGroupAccessed(
const base::Time& access_time, base::optional_ref<const std::string> auction_id,
base::Time access_time,
InterestGroupManagerImpl::InterestGroupObserver::AccessType type, InterestGroupManagerImpl::InterestGroupObserver::AccessType type,
const url::Origin& owner_origin, const url::Origin& owner_origin,
const std::string& name) { const std::string& name,
base::optional_ref<const url::Origin> component_seller_origin,
std::optional<double> bid,
base::optional_ref<const std::string> bid_currency) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
using AccessType = using AccessType =
InterestGroupManagerImpl::InterestGroupObserver::AccessType; InterestGroupManagerImpl::InterestGroupObserver::AccessType;
@@ -1052,9 +1062,22 @@ void StorageHandler::OnInterestGroupAccessed(
case AccessType::kClear: case AccessType::kClear:
type_enum = Storage::InterestGroupAccessTypeEnum::Clear; type_enum = Storage::InterestGroupAccessTypeEnum::Clear;
break; break;
case AccessType::kTopLevelBid:
type_enum = Storage::InterestGroupAccessTypeEnum::TopLevelBid;
break;
case AccessType::kTopLevelAdditionalBid:
type_enum = Storage::InterestGroupAccessTypeEnum::TopLevelAdditionalBid;
break;
}; };
frontend_->InterestGroupAccessed(access_time.InSecondsFSinceUnixEpoch(), frontend_->InterestGroupAccessed(
type_enum, owner_origin.Serialize(), name); access_time.InSecondsFSinceUnixEpoch(), type_enum,
owner_origin.Serialize(), name,
component_seller_origin.has_value()
? Maybe<String>(component_seller_origin->Serialize())
: Maybe<String>(),
bid.has_value() ? Maybe<double>(*bid) : Maybe<double>(),
bid_currency.has_value() ? Maybe<String>(*bid_currency) : Maybe<String>(),
auction_id.has_value() ? Maybe<String>(*auction_id) : Maybe<String>());
} }
namespace { namespace {
@@ -1188,6 +1211,11 @@ Response StorageHandler::SetInterestGroupTracking(bool enable) {
return Response::Success(); return Response::Success();
} }
Response StorageHandler::SetInterestGroupAuctionTracking(bool enable) {
interest_group_auction_tracking_enabled_ = enable;
return Response::Success();
}
namespace { namespace {
void SendSharedStorageMetadata( void SendSharedStorageMetadata(
@@ -2135,5 +2163,30 @@ Response StorageHandler::SetAttributionReportingTracking(bool enable) {
return Response::Success(); return Response::Success();
} }
void StorageHandler::NotifyInterestGroupAuctionEventOccurred(
base::Time event_time,
content::InterestGroupAuctionEventType type,
const std::string& unique_auction_id,
base::optional_ref<const std::string> parent_auction_id,
const base::Value::Dict& auction_config) {
if (!interest_group_auction_tracking_enabled_) {
return;
}
std::string type_enum;
switch (type) {
case content::InterestGroupAuctionEventType::kStarted:
type_enum = Storage::InterestGroupAuctionEventTypeEnum::Started;
break;
case content::InterestGroupAuctionEventType::kConfigResolved:
type_enum = Storage::InterestGroupAuctionEventTypeEnum::ConfigResolved;
break;
};
frontend_->InterestGroupAuctionEventOccurred(
event_time.InSecondsFSinceUnixEpoch(), type_enum, unique_auction_id,
parent_auction_id.has_value() ? Maybe<String>(*parent_auction_id)
: Maybe<String>(),
std::make_unique<base::Value::Dict>(auction_config.Clone()));
}
} // namespace protocol } // namespace protocol
} // namespace content } // namespace content

@@ -10,10 +10,12 @@
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h" #include "base/scoped_observation.h"
#include "base/types/optional_ref.h"
#include "components/services/storage/shared_storage/shared_storage_manager.h" #include "components/services/storage/shared_storage/shared_storage_manager.h"
#include "content/browser/attribution_reporting/attribution_observer.h" #include "content/browser/attribution_reporting/attribution_observer.h"
#include "content/browser/devtools/protocol/devtools_domain_handler.h" #include "content/browser/devtools/protocol/devtools_domain_handler.h"
#include "content/browser/devtools/protocol/storage.h" #include "content/browser/devtools/protocol/storage.h"
#include "content/browser/interest_group/devtools_enums.h"
#include "content/browser/interest_group/interest_group_manager_impl.h" #include "content/browser/interest_group/interest_group_manager_impl.h"
#include "content/browser/renderer_host/frame_tree_node.h" #include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_frame_host_impl.h"
@@ -43,12 +45,18 @@ class StorageHandler
~StorageHandler() override; ~StorageHandler() override;
static std::vector<StorageHandler*> ForAgentHost(DevToolsAgentHostImpl* host);
// content::protocol::DevToolsDomainHandler // content::protocol::DevToolsDomainHandler
void Wire(UberDispatcher* dispatcher) override; void Wire(UberDispatcher* dispatcher) override;
void SetRenderer(int process_host_id, void SetRenderer(int process_host_id,
RenderFrameHostImpl* frame_host) override; RenderFrameHostImpl* frame_host) override;
Response Disable() override; Response Disable() override;
bool interest_group_auction_tracking_enabled() const {
return interest_group_auction_tracking_enabled_;
}
// content::protocol::storage::Backend // content::protocol::storage::Backend
Response GetStorageKeyForFrame(const std::string& frame_id, Response GetStorageKeyForFrame(const std::string& frame_id,
std::string* serialized_storage_key) override; std::string* serialized_storage_key) override;
@@ -109,6 +117,7 @@ class StorageHandler
const std::string& name, const std::string& name,
std::unique_ptr<GetInterestGroupDetailsCallback> callback) override; std::unique_ptr<GetInterestGroupDetailsCallback> callback) override;
Response SetInterestGroupTracking(bool enable) override; Response SetInterestGroupTracking(bool enable) override;
Response SetInterestGroupAuctionTracking(bool enable) override;
void GetSharedStorageMetadata( void GetSharedStorageMetadata(
const std::string& owner_origin_string, const std::string& owner_origin_string,
@@ -147,6 +156,13 @@ class StorageHandler
override; override;
Response SetAttributionReportingTracking(bool enable) override; Response SetAttributionReportingTracking(bool enable) override;
void NotifyInterestGroupAuctionEventOccurred(
base::Time event_time,
content::InterestGroupAuctionEventType type,
const std::string& unique_auction_id,
base::optional_ref<const std::string> parent_auction_id,
const base::Value::Dict& auction_config);
private: private:
// See definition for lifetime information. // See definition for lifetime information.
class CacheStorageObserver; class CacheStorageObserver;
@@ -167,10 +183,14 @@ class StorageHandler
// content::InterestGroupManagerImpl::InterestGroupObserver // content::InterestGroupManagerImpl::InterestGroupObserver
void OnInterestGroupAccessed( void OnInterestGroupAccessed(
const base::Time& accessTime, base::optional_ref<const std::string> auction_id,
base::Time access_time,
InterestGroupManagerImpl::InterestGroupObserver::AccessType type, InterestGroupManagerImpl::InterestGroupObserver::AccessType type,
const url::Origin& owner_origin, const url::Origin& owner_origin,
const std::string& name) override; const std::string& name,
base::optional_ref<const url::Origin> component_seller_origin,
std::optional<double> bid,
base::optional_ref<const std::string> bid_currency) override;
// AttributionObserver // AttributionObserver
void OnSourceHandled( void OnSourceHandled(
@@ -219,6 +239,8 @@ class StorageHandler
std::unique_ptr<storage::QuotaOverrideHandle> quota_override_handle_; std::unique_ptr<storage::QuotaOverrideHandle> quota_override_handle_;
bool client_is_trusted_; bool client_is_trusted_;
bool interest_group_auction_tracking_enabled_ = false;
base::ScopedObservation<AttributionManager, AttributionObserver> base::ScopedObservation<AttributionManager, AttributionObserver>
attribution_observation_{this}; attribution_observation_{this};

@@ -830,12 +830,13 @@ class AdAuctionServiceImplTest : public RenderViewHostTestHarness {
scoped_refptr<StorageInterestGroups> interest_groups; scoped_refptr<StorageInterestGroups> interest_groups;
base::RunLoop run_loop; base::RunLoop run_loop;
manager_->GetInterestGroupsForOwner( manager_->GetInterestGroupsForOwner(
owner, base::BindLambdaForTesting( /*devtools_auction_id=*/std::nullopt, owner,
[&run_loop, &interest_groups]( base::BindLambdaForTesting(
scoped_refptr<StorageInterestGroups> groups) { [&run_loop,
interest_groups = std::move(groups); &interest_groups](scoped_refptr<StorageInterestGroups> groups) {
run_loop.Quit(); interest_groups = std::move(groups);
})); run_loop.Quit();
}));
run_loop.Run(); run_loop.Run();
return interest_groups; return interest_groups;
} }

@@ -0,0 +1,14 @@
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_INTEREST_GROUP_DEVTOOLS_ENUMS_H_
#define CONTENT_BROWSER_INTEREST_GROUP_DEVTOOLS_ENUMS_H_
namespace content {
enum class InterestGroupAuctionEventType { kStarted, kConfigResolved };
} // namespace content
#endif // CONTENT_BROWSER_INTEREST_GROUP_DEVTOOLS_ENUMS_H_

@@ -39,10 +39,12 @@
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/task/sequenced_task_runner.h" #include "base/task/sequenced_task_runner.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/token.h"
#include "base/trace_event/trace_event.h" #include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_id_helper.h" #include "base/trace_event/trace_id_helper.h"
#include "base/types/optional_ref.h" #include "base/types/optional_ref.h"
#include "base/uuid.h" #include "base/uuid.h"
#include "content/browser/devtools/devtools_instrumentation.h"
#include "content/browser/interest_group/ad_auction_page_data.h" #include "content/browser/interest_group/ad_auction_page_data.h"
#include "content/browser/interest_group/additional_bid_result.h" #include "content/browser/interest_group/additional_bid_result.h"
#include "content/browser/interest_group/additional_bids_util.h" #include "content/browser/interest_group/additional_bids_util.h"
@@ -2128,7 +2130,8 @@ InterestGroupAuction::InterestGroupAuction(
base::RepeatingCallback< base::RepeatingCallback<
void(const PrivateAggregationRequests& private_aggregation_requests)> void(const PrivateAggregationRequests& private_aggregation_requests)>
maybe_log_private_aggregation_web_features_callback) maybe_log_private_aggregation_web_features_callback)
: trace_id_(base::trace_event::GetNextGlobalTraceId()), : devtools_auction_id_(base::Token::CreateRandom().ToString()),
trace_id_(base::trace_event::GetNextGlobalTraceId()),
kanon_mode_(kanon_mode), kanon_mode_(kanon_mode),
auction_worklet_manager_(auction_worklet_manager), auction_worklet_manager_(auction_worklet_manager),
auction_nonce_manager_(auction_nonce_manager), auction_nonce_manager_(auction_nonce_manager),
@@ -2150,6 +2153,17 @@ InterestGroupAuction::InterestGroupAuction(
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("fledge", "auction", *trace_id_, TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("fledge", "auction", *trace_id_,
"decision_logic_url", "decision_logic_url",
config_->decision_logic_url); config_->decision_logic_url);
int frame_tree_node_id = auction_worklet_manager_->GetFrameTreeNodeID();
if (devtools_instrumentation::NeedInterestGroupAuctionEvents(
frame_tree_node_id)) {
devtools_instrumentation::OnInterestGroupAuctionEventOccurred(
frame_tree_node_id, auction_start_time_,
InterestGroupAuctionEventType::kStarted, devtools_auction_id_,
parent_ ? base::optional_ref<const std::string>(
parent->devtools_auction_id_)
: base::optional_ref<const std::string>(),
config_->SerializeForDevtools());
}
uint32_t child_pos = 0; uint32_t child_pos = 0;
for (const auto& component_auction_config : for (const auto& component_auction_config :
@@ -2296,8 +2310,9 @@ void InterestGroupAuction::StartLoadInterestGroupsPhase(
continue; continue;
} }
interest_group_manager_->GetInterestGroupsForOwner( interest_group_manager_->GetInterestGroupsForOwner(
buyer, base::BindOnce(&InterestGroupAuction::OnInterestGroupRead, devtools_auction_id_, buyer,
weak_ptr_factory_.GetWeakPtr())); base::BindOnce(&InterestGroupAuction::OnInterestGroupRead,
weak_ptr_factory_.GetWeakPtr()));
++num_pending_loads_; ++num_pending_loads_;
} }
} }
@@ -2717,10 +2732,10 @@ InterestGroupAuction::CreateReporter(
interest_group_manager_, auction_worklet_manager_, browser_context, interest_group_manager_, auction_worklet_manager_, browser_context,
private_aggregation_manager, private_aggregation_manager,
maybe_log_private_aggregation_web_features_callback_, maybe_log_private_aggregation_web_features_callback_,
std::move(auction_config), main_frame_origin, frame_origin, std::move(auction_config), devtools_auction_id_, main_frame_origin,
std::move(client_security_state), std::move(url_loader_factory), frame_origin, std::move(client_security_state),
kanon_mode_, bid_is_kanon, std::move(winning_bid_info), std::move(url_loader_factory), kanon_mode_, bid_is_kanon,
std::move(top_level_seller_winning_bid_info), std::move(winning_bid_info), std::move(top_level_seller_winning_bid_info),
std::move(component_seller_winning_bid_info), std::move(component_seller_winning_bid_info),
std::move(interest_groups_that_bid), std::move(debug_win_report_urls), std::move(interest_groups_that_bid), std::move(debug_win_report_urls),
std::move(debug_loss_report_urls), GetKAnonKeysToJoin(), std::move(debug_loss_report_urls), GetKAnonKeysToJoin(),
@@ -2745,6 +2760,18 @@ void InterestGroupAuction::NotifyConfigPromisesResolved() {
auction_metrics_recorder_->OnConfigPromisesResolved(); auction_metrics_recorder_->OnConfigPromisesResolved();
int frame_tree_node_id = auction_worklet_manager_->GetFrameTreeNodeID();
if (devtools_instrumentation::NeedInterestGroupAuctionEvents(
frame_tree_node_id)) {
devtools_instrumentation::OnInterestGroupAuctionEventOccurred(
frame_tree_node_id, base::Time::Now(),
InterestGroupAuctionEventType::kConfigResolved, devtools_auction_id_,
parent_ ? base::optional_ref<const std::string>(
parent_->devtools_auction_id_)
: base::optional_ref<const std::string>(),
config_->SerializeForDevtools());
}
// If we haven't started the bidding and scoring phase, we will just handle // If we haven't started the bidding and scoring phase, we will just handle
// this information at its start; setting `config_promises_resolved_` is // this information at its start; setting `config_promises_resolved_` is
// enough both for us and the BuyerHelper. If we are after the phase, that // enough both for us and the BuyerHelper. If we are after the phase, that
@@ -2925,9 +2952,14 @@ void InterestGroupAuction::GetInterestGroupsThatBidAndReportBidCounts(
saved_response_->bidding_groups.end()); saved_response_->bidding_groups.end());
for (const auto& ig_bid : interest_groups) { for (const auto& ig_bid : interest_groups) {
interest_group_manager_->NotifyInterestGroupAccessed( interest_group_manager_->NotifyInterestGroupAccessed(
devtools_auction_id_,
InterestGroupManagerImpl::InterestGroupObserver:: InterestGroupManagerImpl::InterestGroupObserver::
InterestGroupObserver::kBid, InterestGroupObserver::kBid,
ig_bid.owner, ig_bid.name); ig_bid.owner, ig_bid.name,
/*component_seller_origin=*/std::nullopt,
// Don't know individual bid values of a server-side auction, just
// that the IGs participated.
/*bid=*/std::nullopt, /*bid_currency=*/std::nullopt);
} }
return; return;
} }
@@ -4148,18 +4180,32 @@ void InterestGroupAuction::ScoreBidIfReady(std::unique_ptr<Bid> bid) {
any_bid_made_ = true; any_bid_made_ = true;
// TODO(https://crbug.com/1516642): Report component auctions participating // TODO(https://crbug.com/1516642): Report k-anon re-runs.
// in top-level auction, as well as k-anon re-runs. if (IsBidRoleUsedForWinner(kanon_mode_, bid->bid_role)) {
if (component_auctions_.empty() && InterestGroupManagerImpl::InterestGroupObserver::AccessType event_type =
IsBidRoleUsedForWinner(kanon_mode_, bid->bid_role)) { InterestGroupManagerImpl::InterestGroupObserver::kBid;
if (!component_auctions_.empty()) {
event_type =
bid->bid_state->additional_bid_buyer
? InterestGroupManagerImpl::InterestGroupObserver::
kTopLevelAdditionalBid
: InterestGroupManagerImpl::InterestGroupObserver::kTopLevelBid;
} else if (bid->bid_state->additional_bid_buyer) {
event_type =
InterestGroupManagerImpl::InterestGroupObserver::kAdditionalBid;
}
interest_group_manager_->NotifyInterestGroupAccessed( interest_group_manager_->NotifyInterestGroupAccessed(
bid->bid_state->additional_bid_buyer devtools_auction_id_, event_type,
? InterestGroupManagerImpl::InterestGroupObserver::
InterestGroupObserver::kAdditionalBid
: InterestGroupManagerImpl::InterestGroupObserver::
InterestGroupObserver::kBid,
bid->bid_state->bidder->interest_group.owner, bid->bid_state->bidder->interest_group.owner,
bid->bid_state->bidder->interest_group.name); bid->bid_state->bidder->interest_group.name,
component_auctions_.empty() ? base::optional_ref<const url::Origin>()
: base::optional_ref<const url::Origin>(
bid->auction->config_->seller),
bid->bid,
bid->bid_currency
? base::optional_ref(bid->bid_currency->currency_code())
: base::optional_ref<const std::string>());
} }
// If seller worklet hasn't been received yet, or configuration is still // If seller worklet hasn't been received yet, or configuration is still

@@ -1192,6 +1192,10 @@ class CONTENT_EXPORT InterestGroupAuction
static data_decoder::DataDecoder* GetDataDecoder( static data_decoder::DataDecoder* GetDataDecoder(
base::WeakPtr<InterestGroupAuction> instance); base::WeakPtr<InterestGroupAuction> instance);
// For associating various events with a particular auction. Note that
// component auctions have their own.
const std::string devtools_auction_id_;
// Tracing ID associated with the Auction. A nestable // Tracing ID associated with the Auction. A nestable
// async "Auction" trace event lasts for the combined lifetime of `this` // async "Auction" trace event lasts for the combined lifetime of `this`
// and a possible InterestGroupAuctionReporter. Sequential events that // and a possible InterestGroupAuctionReporter. Sequential events that

@@ -163,6 +163,7 @@ InterestGroupAuctionReporter::InterestGroupAuctionReporter(
LogPrivateAggregationRequestsCallback LogPrivateAggregationRequestsCallback
log_private_aggregation_requests_callback, log_private_aggregation_requests_callback,
std::unique_ptr<blink::AuctionConfig> auction_config, std::unique_ptr<blink::AuctionConfig> auction_config,
const std::string& devtools_auction_id,
const url::Origin& main_frame_origin, const url::Origin& main_frame_origin,
const url::Origin& frame_origin, const url::Origin& frame_origin,
network::mojom::ClientSecurityStatePtr client_security_state, network::mojom::ClientSecurityStatePtr client_security_state,
@@ -186,6 +187,7 @@ InterestGroupAuctionReporter::InterestGroupAuctionReporter(
log_private_aggregation_requests_callback_( log_private_aggregation_requests_callback_(
std::move(log_private_aggregation_requests_callback)), std::move(log_private_aggregation_requests_callback)),
auction_config_(std::move(auction_config)), auction_config_(std::move(auction_config)),
devtools_auction_id_(devtools_auction_id),
main_frame_origin_(main_frame_origin), main_frame_origin_(main_frame_origin),
frame_origin_(frame_origin), frame_origin_(frame_origin),
client_security_state_(std::move(client_security_state)), client_security_state_(std::move(client_security_state)),
@@ -1004,18 +1006,23 @@ void InterestGroupAuctionReporter::OnNavigateToWinningAd(
const blink::InterestGroup& winning_group = const blink::InterestGroup& winning_group =
winning_bid_info_.storage_interest_group->interest_group; winning_bid_info_.storage_interest_group->interest_group;
if (!winning_bid_info_.provided_as_additional_bid) { InterestGroupManagerImpl::InterestGroupObserver::AccessType win_type =
InterestGroupManagerImpl::InterestGroupObserver::kWin;
if (winning_bid_info_.provided_as_additional_bid) {
win_type =
InterestGroupManagerImpl::InterestGroupObserver::kAdditionalBidWin;
} else {
interest_group_manager_->RecordInterestGroupWin( interest_group_manager_->RecordInterestGroupWin(
blink::InterestGroupKey(winning_group.owner, winning_group.name), blink::InterestGroupKey(winning_group.owner, winning_group.name),
winning_bid_info_.ad_metadata); winning_bid_info_.ad_metadata);
interest_group_manager_->NotifyInterestGroupAccessed(
InterestGroupManagerImpl::InterestGroupObserver::kWin,
winning_group.owner, winning_group.name);
} else {
interest_group_manager_->NotifyInterestGroupAccessed(
InterestGroupManagerImpl::InterestGroupObserver::kAdditionalBidWin,
winning_group.owner, winning_group.name);
} }
interest_group_manager_->NotifyInterestGroupAccessed(
devtools_auction_id_, win_type, winning_group.owner, winning_group.name,
component_seller_winning_bid_info_.has_value()
? base::optional_ref<const url::Origin>(
component_seller_winning_bid_info_->auction_config->seller)
: base::optional_ref<const url::Origin>(),
/*bid=*/std::nullopt, /*bid_currency=*/std::nullopt);
interest_group_manager_->RegisterAdKeysAsJoined( interest_group_manager_->RegisterAdKeysAsJoined(
std::move(k_anon_keys_to_join_)); std::move(k_anon_keys_to_join_));

@@ -246,6 +246,7 @@ class CONTENT_EXPORT InterestGroupAuctionReporter {
LogPrivateAggregationRequestsCallback LogPrivateAggregationRequestsCallback
log_private_aggregation_requests_callback, log_private_aggregation_requests_callback,
std::unique_ptr<blink::AuctionConfig> auction_config, std::unique_ptr<blink::AuctionConfig> auction_config,
const std::string& devtools_auction_id,
const url::Origin& main_frame_origin, const url::Origin& main_frame_origin,
const url::Origin& frame_origin, const url::Origin& frame_origin,
network::mojom::ClientSecurityStatePtr client_security_state, network::mojom::ClientSecurityStatePtr client_security_state,
@@ -480,6 +481,7 @@ class CONTENT_EXPORT InterestGroupAuctionReporter {
// SellerWinningBidInfo, it points to an AuctionConfig contained within it. // SellerWinningBidInfo, it points to an AuctionConfig contained within it.
const std::unique_ptr<blink::AuctionConfig> auction_config_; const std::unique_ptr<blink::AuctionConfig> auction_config_;
const std::optional<std::string> devtools_auction_id_;
const url::Origin main_frame_origin_; const url::Origin main_frame_origin_;
const url::Origin frame_origin_; const url::Origin frame_origin_;
const network::mojom::ClientSecurityStatePtr client_security_state_; const network::mojom::ClientSecurityStatePtr client_security_state_;

@@ -249,8 +249,8 @@ class InterestGroupAuctionReporterTest
&private_aggregation_manager_, &private_aggregation_manager_,
private_aggregation_manager_ private_aggregation_manager_
.GetLogPrivateAggregationRequestsCallback(), .GetLogPrivateAggregationRequestsCallback(),
std::move(auction_config_), kTopFrameOrigin, kFrameOrigin, std::move(auction_config_), kDevtoolsAuctionId, kTopFrameOrigin,
frame_client_security_state_.Clone(), kFrameOrigin, frame_client_security_state_.Clone(),
dummy_report_shared_url_loader_factory_, dummy_report_shared_url_loader_factory_,
auction_worklet::mojom::KAnonymityBidMode::kNone, false, auction_worklet::mojom::KAnonymityBidMode::kNone, false,
std::move(winning_bid_info_), std::move(seller_winning_bid_info_), std::move(winning_bid_info_), std::move(seller_winning_bid_info_),
@@ -467,6 +467,7 @@ class InterestGroupAuctionReporterTest
EventReportingAttestationBrowserClient browser_client_; EventReportingAttestationBrowserClient browser_client_;
ScopedContentBrowserClientSetting browser_client_setting_{&browser_client_}; ScopedContentBrowserClientSetting browser_client_setting_{&browser_client_};
const std::string kDevtoolsAuctionId = "123-456";
const url::Origin kTopFrameOrigin = const url::Origin kTopFrameOrigin =
url::Origin::Create(GURL("https://top_frame_origin.test/")); url::Origin::Create(GURL("https://top_frame_origin.test/"));
const url::Origin kFrameOrigin = const url::Origin kFrameOrigin =

@@ -1129,7 +1129,7 @@ class InterestGroupBrowserTest : public ContentBrowserTest {
scoped_refptr<StorageInterestGroups> result; scoped_refptr<StorageInterestGroups> result;
base::RunLoop run_loop; base::RunLoop run_loop;
manager_->GetInterestGroupsForOwner( manager_->GetInterestGroupsForOwner(
owner, /*devtools_auction_id=*/std::nullopt, owner,
base::BindLambdaForTesting( base::BindLambdaForTesting(
[&result, &run_loop](scoped_refptr<StorageInterestGroups> groups) { [&result, &run_loop](scoped_refptr<StorageInterestGroups> groups) {
result = std::move(groups); result = std::move(groups);
@@ -2393,10 +2393,10 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
/*joining_url=*/embedded_https_test_server().GetURL("b.test", "/echo")); /*joining_url=*/embedded_https_test_server().GetURL("b.test", "/echo"));
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kJoin, test_origin_a, kName1}, {{"global", TestInterestGroupObserver::kJoin, test_origin_a, kName1},
{TestInterestGroupObserver::kJoin, test_origin_a, kName2}, {"global", TestInterestGroupObserver::kJoin, test_origin_a, kName2},
{TestInterestGroupObserver::kJoin, test_origin_a, kName3}, {"global", TestInterestGroupObserver::kJoin, test_origin_a, kName3},
{TestInterestGroupObserver::kJoin, test_origin_a, kName4}}); {"global", TestInterestGroupObserver::kJoin, test_origin_a, kName4}});
EXPECT_EQ(kSuccess, ClearOriginJoinedInterestGroups( EXPECT_EQ(kSuccess, ClearOriginJoinedInterestGroups(
test_origin_a, /*groups_to_keep=*/{{kName2}})); test_origin_a, /*groups_to_keep=*/{{kName2}}));
@@ -2404,8 +2404,8 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
// kName2 and kName4 should not be cleared. Don't check exact order, as // kName2 and kName4 should not be cleared. Don't check exact order, as
// there's no guarantee about the order groups will be listed in. // there's no guarantee about the order groups will be listed in.
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kClear, test_origin_a, kName1}, {{"global", TestInterestGroupObserver::kClear, test_origin_a, kName1},
{TestInterestGroupObserver::kClear, test_origin_a, kName3}}); {"global", TestInterestGroupObserver::kClear, test_origin_a, kName3}});
} }
// Can't join or leave interest groups from http://localhost, even though it's // Can't join or leave interest groups from http://localhost, even though it's
@@ -3199,7 +3199,7 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
})())", })())",
test_origin, url))); test_origin, url)));
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
}); });
auto storage_groups = GetInterestGroupsForOwner(test_origin); auto storage_groups = GetInterestGroupsForOwner(test_origin);
ASSERT_EQ(storage_groups->size(), 1u); ASSERT_EQ(storage_groups->size(), 1u);
@@ -3253,7 +3253,7 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, JoinInterestGroupLifetimeMs) {
})())", })())",
test_origin))); test_origin)));
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
}); });
auto storage_groups = GetInterestGroupsForOwner(test_origin); auto storage_groups = GetInterestGroupsForOwner(test_origin);
ASSERT_EQ(storage_groups->size(), 1u); ASSERT_EQ(storage_groups->size(), 1u);
@@ -3286,7 +3286,7 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
})())", })())",
test_origin))); test_origin)));
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
}); });
auto storage_groups = GetInterestGroupsForOwner(test_origin); auto storage_groups = GetInterestGroupsForOwner(test_origin);
ASSERT_EQ(storage_groups->size(), 1u); ASSERT_EQ(storage_groups->size(), 1u);
@@ -3745,7 +3745,7 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
})())", })())",
origin))); origin)));
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kJoin, origin, "cars"}, {"global", TestInterestGroupObserver::kJoin, origin, "cars"},
}); });
scoped_refptr<StorageInterestGroups> groups = scoped_refptr<StorageInterestGroups> groups =
GetInterestGroupsForOwner(origin); GetInterestGroupsForOwner(origin);
@@ -4690,7 +4690,7 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
? kAdditionalBidKeySloppyBase64 ? kAdditionalBidKeySloppyBase64
: kAdditionalBidKeyBase64))); : kAdditionalBidKeyBase64)));
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kJoin, origin, "cars"}, {"global", TestInterestGroupObserver::kJoin, origin, "cars"},
}); });
scoped_refptr<StorageInterestGroups> groups = scoped_refptr<StorageInterestGroups> groups =
GetInterestGroupsForOwner(origin); GetInterestGroupsForOwner(origin);
@@ -7871,7 +7871,7 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
embedded_https_test_server().GetURL( embedded_https_test_server().GetURL(
"/interest_group/decision_logic.js"))); "/interest_group/decision_logic.js")));
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kJoin, test_origin_a, "cars"}, {"global", TestInterestGroupObserver::kJoin, test_origin_a, "cars"},
}); });
} }
@@ -7940,11 +7940,11 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
embedded_https_test_server().GetURL( embedded_https_test_server().GetURL(
"/interest_group/bidding_logic_stop_bidding_after_win.js"))); "/interest_group/bidding_logic_stop_bidding_after_win.js")));
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kJoin, disabled_origin, "candy"}, {"global", TestInterestGroupObserver::kJoin, disabled_origin, "candy"},
{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "cars"}, {"1", TestInterestGroupObserver::kWin, test_origin, "cars"},
}); });
} }
@@ -8494,10 +8494,10 @@ IN_PROC_BROWSER_TEST_F(
"a.test", "/interest_group/decision_logic.js")), "a.test", "/interest_group/decision_logic.js")),
ad_url); ad_url);
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {{"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "cars"}}); {"1", TestInterestGroupObserver::kWin, test_origin, "cars"}});
} }
IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, RunAdAuctionCancel) { IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, RunAdAuctionCancel) {
@@ -9406,10 +9406,10 @@ IN_PROC_BROWSER_TEST_F(InterestGroupFencedFrameBrowserTest,
// InterestGroupAccessObserver should see the join and auction. // InterestGroupAccessObserver should see the join and auction.
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {{"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "cars"}}); {"1", TestInterestGroupObserver::kWin, test_origin, "cars"}});
// Leaving the winning interest group should succeed. Do it by calling // Leaving the winning interest group should succeed. Do it by calling
// Javascript directly instead of loading a page that does this // Javascript directly instead of loading a page that does this
@@ -9420,7 +9420,7 @@ IN_PROC_BROWSER_TEST_F(InterestGroupFencedFrameBrowserTest,
// The leave should be observed. // The leave should be observed.
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kLeave, test_origin, "cars"}}); {{"global", TestInterestGroupObserver::kLeave, test_origin, "cars"}});
EXPECT_TRUE(GetAllInterestGroups().empty()); EXPECT_TRUE(GetAllInterestGroups().empty());
} }
@@ -9463,10 +9463,10 @@ IN_PROC_BROWSER_TEST_F(InterestGroupFencedFrameBrowserTest,
// InterestGroupAccessObserver should see the join and auction. // InterestGroupAccessObserver should see the join and auction.
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {{"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "cars"}}); {"1", TestInterestGroupObserver::kWin, test_origin, "cars"}});
// Leaving the winning interest group should fail. Do it by calling Javascript // Leaving the winning interest group should fail. Do it by calling Javascript
// directly instead of loading a page that does this to avoid races with // directly instead of loading a page that does this to avoid races with
@@ -9529,10 +9529,10 @@ IN_PROC_BROWSER_TEST_F(InterestGroupFencedFrameBrowserTest,
// InterestGroupAccessObserver should see the join and auction. // InterestGroupAccessObserver should see the join and auction.
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {{"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "cars"}}); {"1", TestInterestGroupObserver::kWin, test_origin, "cars"}});
// Leaving the winning interest group from the nested iframe should succeed. // Leaving the winning interest group from the nested iframe should succeed.
// Do it by calling Javascript directly instead of loading a page that does // Do it by calling Javascript directly instead of loading a page that does
@@ -9544,7 +9544,7 @@ IN_PROC_BROWSER_TEST_F(InterestGroupFencedFrameBrowserTest,
// The leave should be observed. // The leave should be observed.
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kLeave, test_origin, "cars"}}); {{"global", TestInterestGroupObserver::kLeave, test_origin, "cars"}});
EXPECT_TRUE(GetAllInterestGroups().empty()); EXPECT_TRUE(GetAllInterestGroups().empty());
} }
@@ -9597,10 +9597,10 @@ IN_PROC_BROWSER_TEST_F(InterestGroupFencedFrameBrowserTest,
// InterestGroupAccessObserver should see the join and auction. // InterestGroupAccessObserver should see the join and auction.
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {{"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "cars"}}); {"1", TestInterestGroupObserver::kWin, test_origin, "cars"}});
// Leaving the winning interest group from the nested iframe should fail. // Leaving the winning interest group from the nested iframe should fail.
// Do it by calling Javascript directly instead of loading a page that does // Do it by calling Javascript directly instead of loading a page that does
@@ -9705,13 +9705,13 @@ perBuyerSignals: {$1: {even: 'more', x: 4.5}}
// InterestGroupAccessObserver should see the join and auction. // InterestGroupAccessObserver should see the join and auction.
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kJoin, test_origin, "trucks"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "trucks"},
{TestInterestGroupObserver::kLoaded, test_origin, "trucks"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "trucks"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 2.0},
{TestInterestGroupObserver::kBid, test_origin, "trucks"}, {"1", TestInterestGroupObserver::kBid, test_origin, "trucks", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "cars"}, {"1", TestInterestGroupObserver::kWin, test_origin, "cars"},
}); });
// Try to leave the winning interest group, which should fail, since the ad is // Try to leave the winning interest group, which should fail, since the ad is
@@ -9742,10 +9742,10 @@ perBuyerSignals: {$1: {even: 'more', x: 4.5}}
// attempt, as updating the data is potentially racy with the navigation // attempt, as updating the data is potentially racy with the navigation
// committing, so the leave event could appear out of order. // committing, so the leave event could appear out of order.
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kLoaded, test_origin, "trucks"}, {{"2", TestInterestGroupObserver::kLoaded, test_origin, "trucks"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"2", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "trucks"}, {"2", TestInterestGroupObserver::kBid, test_origin, "trucks", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "trucks"}}); {"2", TestInterestGroupObserver::kWin, test_origin, "trucks"}});
// Try to leave the winning interest group, which should succeed this time. Do // Try to leave the winning interest group, which should succeed this time. Do
// it by calling Javascript directly instead of loading a page that does this // it by calling Javascript directly instead of loading a page that does this
@@ -9753,7 +9753,7 @@ perBuyerSignals: {$1: {even: 'more', x: 4.5}}
EXPECT_EQ(nullptr, EvalJs(GetFencedFrameRenderFrameHost(rfh2), EXPECT_EQ(nullptr, EvalJs(GetFencedFrameRenderFrameHost(rfh2),
"navigator.leaveAdInterestGroup()")); "navigator.leaveAdInterestGroup()"));
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kLeave, test_origin, "trucks"}}); {{"global", TestInterestGroupObserver::kLeave, test_origin, "trucks"}});
// Only the "truck" interest group should have been left. // Only the "truck" interest group should have been left.
auto groups = GetAllInterestGroups(); auto groups = GetAllInterestGroups();
@@ -9764,8 +9764,6 @@ perBuyerSignals: {$1: {even: 'more', x: 4.5}}
// Runs ad auction with fenced frames enabled. The auction should succeed and // Runs ad auction with fenced frames enabled. The auction should succeed and
// be loaded in a fenced frame. The displayed ad leaves the interest group // be loaded in a fenced frame. The displayed ad leaves the interest group
// from a nested iframe. // from a nested iframe.
//
// TODO(crbug.com/1320438): Re-enable the test.
IN_PROC_BROWSER_TEST_F(InterestGroupFencedFrameBrowserTest, IN_PROC_BROWSER_TEST_F(InterestGroupFencedFrameBrowserTest,
RunAdAuctionWithWinnerNestedLeaveGroup) { RunAdAuctionWithWinnerNestedLeaveGroup) {
URLLoaderMonitor url_loader_monitor; URLLoaderMonitor url_loader_monitor;
@@ -9816,10 +9814,10 @@ perBuyerSignals: {$1: {even: 'more', x: 4.5}}
// InterestGroupAccessObserver should see the join and auction. // InterestGroupAccessObserver should see the join and auction.
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {{"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "cars"}}); {"1", TestInterestGroupObserver::kWin, test_origin, "cars"}});
// Leave the interest group and wait to observe the event. Do this after the // Leave the interest group and wait to observe the event. Do this after the
// above WaitForAccessObserved() call, as leaving is racy with recording the // above WaitForAccessObserved() call, as leaving is racy with recording the
@@ -9829,7 +9827,7 @@ perBuyerSignals: {$1: {even: 'more', x: 4.5}}
->current_frame_host(), ->current_frame_host(),
"navigator.leaveAdInterestGroup()")); "navigator.leaveAdInterestGroup()"));
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kLeave, test_origin, "cars"}}); {{"global", TestInterestGroupObserver::kLeave, test_origin, "cars"}});
// The ad should have left the interest group when the page was shown. // The ad should have left the interest group when the page was shown.
EXPECT_EQ(0u, GetAllInterestGroups().size()); EXPECT_EQ(0u, GetAllInterestGroups().size());
@@ -9940,7 +9938,7 @@ IN_PROC_BROWSER_TEST_F(InterestGroupFencedFrameBrowserTest,
// InterestGroupAccessObserver should see the join. // InterestGroupAccessObserver should see the join.
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kJoin, test_origin, "cars"}}); {{"global", TestInterestGroupObserver::kJoin, test_origin, "cars"}});
// The ad should not have left the interest group when the page was shown. // The ad should not have left the interest group when the page was shown.
EXPECT_EQ(1u, GetAllInterestGroups().size()); EXPECT_EQ(1u, GetAllInterestGroups().size());
@@ -10030,10 +10028,10 @@ function reportResult(
seller_signals_url, bidder_origin)); seller_signals_url, bidder_origin));
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kJoin, bidder_origin, "cars"}, {"global", TestInterestGroupObserver::kJoin, bidder_origin, "cars"},
{TestInterestGroupObserver::kLoaded, bidder_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, bidder_origin, "cars"},
{TestInterestGroupObserver::kBid, bidder_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, bidder_origin, "cars", 1.0},
{TestInterestGroupObserver::kWin, bidder_origin, "cars"}, {"1", TestInterestGroupObserver::kWin, bidder_origin, "cars"},
}); });
// Reporting urls should be fetched after an auction succeeded. // Reporting urls should be fetched after an auction succeeded.
@@ -10091,10 +10089,10 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad_url); RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad_url);
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "cars"}, {"1", TestInterestGroupObserver::kWin, test_origin, "cars"},
}); });
// Wait for the component to load. // Wait for the component to load.
@@ -10382,14 +10380,14 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, RunAdAuctionAllGroupsLimited) {
RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad1_url); RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad1_url);
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kJoin, test_origin, "bikes"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "bikes"},
{TestInterestGroupObserver::kJoin, test_origin, "shoes"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "shoes"},
{TestInterestGroupObserver::kLoaded, test_origin, "shoes"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "shoes"},
{TestInterestGroupObserver::kLoaded, test_origin, "bikes"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "bikes"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "cars"}, {"1", TestInterestGroupObserver::kWin, test_origin, "cars"},
}); });
} }
@@ -10495,22 +10493,22 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, RunAdAuctionOneGroupLimited) {
RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad1_url); RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad1_url);
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kJoin, test_origin, "bikes"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "bikes"},
{TestInterestGroupObserver::kJoin, test_origin, "shoes"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "shoes"},
{TestInterestGroupObserver::kJoin, test_origin2, "cars"}, {"global", TestInterestGroupObserver::kJoin, test_origin2, "cars"},
{TestInterestGroupObserver::kJoin, test_origin2, "bikes"}, {"global", TestInterestGroupObserver::kJoin, test_origin2, "bikes"},
{TestInterestGroupObserver::kJoin, test_origin2, "shoes"}, {"global", TestInterestGroupObserver::kJoin, test_origin2, "shoes"},
{TestInterestGroupObserver::kLoaded, test_origin, "shoes"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "shoes"},
{TestInterestGroupObserver::kLoaded, test_origin, "bikes"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "bikes"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kLoaded, test_origin2, "shoes"}, {"1", TestInterestGroupObserver::kLoaded, test_origin2, "shoes"},
{TestInterestGroupObserver::kLoaded, test_origin2, "bikes"}, {"1", TestInterestGroupObserver::kLoaded, test_origin2, "bikes"},
{TestInterestGroupObserver::kLoaded, test_origin2, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin2, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 2.0},
{TestInterestGroupObserver::kBid, test_origin2, "bikes"}, {"1", TestInterestGroupObserver::kBid, test_origin2, "bikes", 1.0},
{TestInterestGroupObserver::kBid, test_origin2, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin2, "cars", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "cars"}, {"1", TestInterestGroupObserver::kWin, test_origin, "cars"},
}); });
} }
@@ -10617,23 +10615,23 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad1_url); RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad1_url);
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kJoin, test_origin, "bikes"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "bikes"},
{TestInterestGroupObserver::kJoin, test_origin, "shoes"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "shoes"},
{TestInterestGroupObserver::kJoin, test_origin2, "cars"}, {"global", TestInterestGroupObserver::kJoin, test_origin2, "cars"},
{TestInterestGroupObserver::kJoin, test_origin2, "bikes"}, {"global", TestInterestGroupObserver::kJoin, test_origin2, "bikes"},
{TestInterestGroupObserver::kJoin, test_origin2, "shoes"}, {"global", TestInterestGroupObserver::kJoin, test_origin2, "shoes"},
{TestInterestGroupObserver::kLoaded, test_origin, "shoes"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "shoes"},
{TestInterestGroupObserver::kLoaded, test_origin, "bikes"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "bikes"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kLoaded, test_origin2, "shoes"}, {"1", TestInterestGroupObserver::kLoaded, test_origin2, "shoes"},
{TestInterestGroupObserver::kLoaded, test_origin2, "bikes"}, {"1", TestInterestGroupObserver::kLoaded, test_origin2, "bikes"},
{TestInterestGroupObserver::kLoaded, test_origin2, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin2, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 2.0},
{TestInterestGroupObserver::kBid, test_origin2, "bikes"}, {"1", TestInterestGroupObserver::kBid, test_origin2, "bikes", 1.0},
{TestInterestGroupObserver::kBid, test_origin2, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin2, "cars", 1.0},
{TestInterestGroupObserver::kBid, test_origin2, "shoes"}, {"1", TestInterestGroupObserver::kBid, test_origin2, "shoes", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "cars"}, {"1", TestInterestGroupObserver::kWin, test_origin, "cars"},
}); });
} }
@@ -10782,19 +10780,20 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, RunAdAuctionMultipleAuctions) {
RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad1_url); RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad1_url);
// Wait for interest groups to be updated. Interest groups are updated // Wait for interest groups to be updated. Interest groups are updated
// during/after commit, so this test is potentially racy without this. // during/after commit, so this test is potentially racy without this.
WaitForAccessObserved({{TestInterestGroupObserver::kLoaded, origin2, "shoes"}, WaitForAccessObserved(
{TestInterestGroupObserver::kLoaded, origin, "cars"}, {{"1", TestInterestGroupObserver::kLoaded, origin2, "shoes"},
{TestInterestGroupObserver::kBid, origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, origin, "cars"},
{TestInterestGroupObserver::kBid, origin2, "shoes"}, {"1", TestInterestGroupObserver::kBid, origin, "cars", 2.0},
{TestInterestGroupObserver::kWin, origin, "cars"}}); {"1", TestInterestGroupObserver::kBid, origin2, "shoes", 1.0},
{"1", TestInterestGroupObserver::kWin, origin, "cars"}});
// `prev_wins` of `test_url`'s interest group cars is updated in storage. // `prev_wins` of `test_url`'s interest group cars is updated in storage.
storage_interest_groups = GetInterestGroupsForOwner(origin); storage_interest_groups = GetInterestGroupsForOwner(origin);
storage_interest_groups2 = GetInterestGroupsForOwner(origin2); storage_interest_groups2 = GetInterestGroupsForOwner(origin2);
// Remove the above two loads from the observer. // Remove the above two loads from the observer.
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kLoaded, origin, "cars"}, {{"global", TestInterestGroupObserver::kLoaded, origin, "cars"},
{TestInterestGroupObserver::kLoaded, origin2, "shoes"}}); {"global", TestInterestGroupObserver::kLoaded, origin2, "shoes"}});
EXPECT_EQ(storage_interest_groups->GetInterestGroups()[0] EXPECT_EQ(storage_interest_groups->GetInterestGroups()[0]
->bidding_browser_signals->prev_wins.size(), ->bidding_browser_signals->prev_wins.size(),
1u); 1u);
@@ -10817,18 +10816,19 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, RunAdAuctionMultipleAuctions) {
// Run auction again. Interest group shoes of owner `test_url2` wins. // Run auction again. Interest group shoes of owner `test_url2` wins.
RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad2_url); RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad2_url);
// Need to wait again. // Need to wait again.
WaitForAccessObserved({{TestInterestGroupObserver::kLoaded, origin2, "shoes"}, WaitForAccessObserved(
{TestInterestGroupObserver::kLoaded, origin, "cars"}, {{"2", TestInterestGroupObserver::kLoaded, origin2, "shoes"},
{TestInterestGroupObserver::kBid, origin2, "shoes"}, {"2", TestInterestGroupObserver::kLoaded, origin, "cars"},
{TestInterestGroupObserver::kWin, origin2, "shoes"}}); {"2", TestInterestGroupObserver::kBid, origin2, "shoes", 1.0},
{"2", TestInterestGroupObserver::kWin, origin2, "shoes"}});
// `test_url2`'s interest group shoes has one `prev_wins` in storage. // `test_url2`'s interest group shoes has one `prev_wins` in storage.
storage_interest_groups = GetInterestGroupsForOwner(origin); storage_interest_groups = GetInterestGroupsForOwner(origin);
storage_interest_groups2 = GetInterestGroupsForOwner(origin2); storage_interest_groups2 = GetInterestGroupsForOwner(origin2);
// Remove the above two loads from the observer. // Remove the above two loads from the observer.
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kLoaded, origin, "cars"}, {{"global", TestInterestGroupObserver::kLoaded, origin, "cars"},
{TestInterestGroupObserver::kLoaded, origin2, "shoes"}}); {"global", TestInterestGroupObserver::kLoaded, origin2, "shoes"}});
EXPECT_EQ(storage_interest_groups->GetInterestGroups()[0] EXPECT_EQ(storage_interest_groups->GetInterestGroups()[0]
->bidding_browser_signals->prev_wins.size(), ->bidding_browser_signals->prev_wins.size(),
1u); 1u);
@@ -10860,9 +10860,9 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, RunAdAuctionMultipleAuctions) {
RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad2_url); RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad2_url);
// Need to wait again. // Need to wait again.
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kLoaded, origin2, "shoes"}, {"3", TestInterestGroupObserver::kLoaded, origin2, "shoes"},
{TestInterestGroupObserver::kBid, origin2, "shoes"}, {"3", TestInterestGroupObserver::kBid, origin2, "shoes", 1.0},
{TestInterestGroupObserver::kWin, origin2, "shoes"}, {"3", TestInterestGroupObserver::kWin, origin2, "shoes"},
}); });
// `test_url2`'s interest group shoes has two `prev_wins` in storage. // `test_url2`'s interest group shoes has two `prev_wins` in storage.
@@ -11557,6 +11557,7 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
} }
IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, ComponentAuction) { IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, ComponentAuction) {
AttachInterestGroupObserver();
GURL test_url = GURL test_url =
embedded_https_test_server().GetURL("a.test", "/page_with_iframe.html"); embedded_https_test_server().GetURL("a.test", "/page_with_iframe.html");
ASSERT_TRUE(NavigateToURL(shell(), test_url)); ASSERT_TRUE(NavigateToURL(shell(), test_url));
@@ -11597,6 +11598,16 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, ComponentAuction) {
embedded_https_test_server().GetURL("a.test", embedded_https_test_server().GetURL("a.test",
"/interest_group/decision_logic.js")); "/interest_group/decision_logic.js"));
RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad_url); RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad_url);
WaitForAccessObserved({
{"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{"1", TestInterestGroupObserver::kBid, test_origin, "cars", 1.0},
{"2", TestInterestGroupObserver::kTopLevelBid, test_origin, "cars", 1.0,
/*bid_currency=*/absl::nullopt, test_origin},
{"2", TestInterestGroupObserver::kWin, test_origin, "cars",
/*bid=*/absl::nullopt, /*bid_currency=*/absl::nullopt, test_origin},
});
} }
// Test the case of a component argument in the case a bidder refuses to // Test the case of a component argument in the case a bidder refuses to
@@ -11742,6 +11753,8 @@ class InterestGroupWorkletValidationBrowserTest
// the expected values. // the expected values.
IN_PROC_BROWSER_TEST_P(InterestGroupWorkletValidationBrowserTest, IN_PROC_BROWSER_TEST_P(InterestGroupWorkletValidationBrowserTest,
ValidateWorkletParameters) { ValidateWorkletParameters) {
AttachInterestGroupObserver();
// Use different hostnames for each participant, since // Use different hostnames for each participant, since
// `trusted_bidding_signals` only checks the hostname of certain parameters. // `trusted_bidding_signals` only checks the hostname of certain parameters.
constexpr char kBidderHost[] = "a.test"; constexpr char kBidderHost[] = "a.test";
@@ -11928,6 +11941,18 @@ IN_PROC_BROWSER_TEST_P(InterestGroupWorkletValidationBrowserTest,
embedded_https_test_server().GetURL(kSellerHost, "/echo?report_seller")); embedded_https_test_server().GetURL(kSellerHost, "/echo?report_seller"));
WaitForUrl( WaitForUrl(
embedded_https_test_server().GetURL(kSellerHost, "/echo?report_bidder")); embedded_https_test_server().GetURL(kSellerHost, "/echo?report_bidder"));
WaitForAccessObserved({
{"global", TestInterestGroupObserver::kJoin, second_bidder_origin,
"boats"},
{"global", TestInterestGroupObserver::kJoin, bidder_origin, "cars"},
{"1", TestInterestGroupObserver::kLoaded, second_bidder_origin, "boats"},
{"1", TestInterestGroupObserver::kLoaded, bidder_origin, "cars"},
{"1", TestInterestGroupObserver::kBid, second_bidder_origin, "boats",
1.0},
{"1", TestInterestGroupObserver::kBid, bidder_origin, "cars", 2.0, "USD"},
{"1", TestInterestGroupObserver::kWin, bidder_origin, "cars"},
});
} }
INSTANTIATE_TEST_SUITE_P( INSTANTIATE_TEST_SUITE_P(
@@ -12114,6 +12139,8 @@ IN_PROC_BROWSER_TEST_P(InterestGroupComponentWorkletValidationBrowserTest,
/*name=*/"cars")); /*name=*/"cars"));
} }
AttachInterestGroupObserver();
ASSERT_EQ(kSuccess, ASSERT_EQ(kSuccess,
JoinInterestGroupAndVerify( JoinInterestGroupAndVerify(
blink::TestInterestGroupBuilder(/*owner=*/bidder_origin, blink::TestInterestGroupBuilder(/*owner=*/bidder_origin,
@@ -12360,6 +12387,18 @@ IN_PROC_BROWSER_TEST_P(InterestGroupComponentWorkletValidationBrowserTest,
kComponentSellerHost, "/echo?report_component_seller")); kComponentSellerHost, "/echo?report_component_seller"));
WaitForUrl(embedded_https_test_server().GetURL(kBidderHost, WaitForUrl(embedded_https_test_server().GetURL(kBidderHost,
"/echo?report_bidder")); "/echo?report_bidder"));
WaitForAccessObserved({
{"global", TestInterestGroupObserver::kJoin, bidder_origin, "cars"},
{"1", TestInterestGroupObserver::kLoaded, bidder_origin, "cars"},
{"1", TestInterestGroupObserver::kBid, bidder_origin, "cars", 2.0,
"USD"},
{"2", TestInterestGroupObserver::kTopLevelBid, bidder_origin, "cars",
42.0, "CAD", component_seller_origin},
{"2", TestInterestGroupObserver::kWin, bidder_origin, "cars",
/*bid=*/absl::nullopt, /*bid_currency=*/absl::nullopt,
component_seller_origin},
});
} }
} }
@@ -16469,19 +16508,19 @@ IN_PROC_BROWSER_TEST_P(LeaveAdInterestGroupFromAdComponentBrowserTest,
if (IsLeaveAdInterestGroupFromAdComponentEnabled()) { if (IsLeaveAdInterestGroupFromAdComponentEnabled()) {
// InterestGroupAccessObserver should see the join, auction and the leave. // InterestGroupAccessObserver should see the join, auction and the leave.
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {{"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "cars"}, {"1", TestInterestGroupObserver::kWin, test_origin, "cars"},
{TestInterestGroupObserver::kLeave, test_origin, "cars"}}); {"global", TestInterestGroupObserver::kLeave, test_origin, "cars"}});
} else { } else {
// InterestGroupAccessObserver should see the join and auction, but not the // InterestGroupAccessObserver should see the join and auction, but not the
// leave. // leave.
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {{"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "cars"}}); {"1", TestInterestGroupObserver::kWin, test_origin, "cars"}});
} }
// The state of the interest groups depends on the feature toggle. // The state of the interest groups depends on the feature toggle.
@@ -16506,10 +16545,10 @@ IN_PROC_BROWSER_TEST_P(LeaveAdInterestGroupFromAdComponentBrowserTest,
// implicit leave since it was blocked due to cross origin to the interest // implicit leave since it was blocked due to cross origin to the interest
// group owner. // group owner.
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {{"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 1.0},
{TestInterestGroupObserver::kWin, test_origin, "cars"}}); {"1", TestInterestGroupObserver::kWin, test_origin, "cars"}});
// The ad should not leave the interest group. // The ad should not leave the interest group.
EXPECT_EQ(1u, GetAllInterestGroups().size()); EXPECT_EQ(1u, GetAllInterestGroups().size());
@@ -18335,18 +18374,19 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
auction_config, should_win ? additional_bid_ad_url : ad_url); auction_config, should_win ? additional_bid_ad_url : ad_url);
WaitForUrl(embedded_https_test_server().GetURL("a.test", WaitForUrl(embedded_https_test_server().GetURL("a.test",
"/echoall?report_seller")); "/echoall?report_seller"));
if (should_win) { if (should_win) {
WaitForUrl(embedded_https_test_server().GetURL( WaitForUrl(embedded_https_test_server().GetURL(
"a.test", "/echoall?report_bidder_additional")); "a.test", "/echoall?report_bidder_additional"));
EXPECT_FALSE(HasServerSeenUrl(embedded_https_test_server().GetURL( EXPECT_FALSE(HasServerSeenUrl(embedded_https_test_server().GetURL(
"a.test", "/echoall?report_bidder"))); "a.test", "/echoall?report_bidder")));
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 1.0},
{TestInterestGroupObserver::kAdditionalBid, additional_bid_origin, {"1", TestInterestGroupObserver::kAdditionalBid,
"campaign123"}, additional_bid_origin, "campaign123", 1.99},
{TestInterestGroupObserver::kAdditionalBidWin, additional_bid_origin, {"1", TestInterestGroupObserver::kAdditionalBidWin,
"campaign123"}, additional_bid_origin, "campaign123"},
}); });
} else { } else {
WaitForUrl(embedded_https_test_server().GetURL("a.test", WaitForUrl(embedded_https_test_server().GetURL("a.test",
@@ -18354,11 +18394,11 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
EXPECT_FALSE(HasServerSeenUrl(embedded_https_test_server().GetURL( EXPECT_FALSE(HasServerSeenUrl(embedded_https_test_server().GetURL(
"a.test", "/echoall?report_bidder_additional"))); "a.test", "/echoall?report_bidder_additional")));
WaitForAccessObserved( WaitForAccessObserved(
{{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {{"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kBid, test_origin, "cars"}, {"1", TestInterestGroupObserver::kBid, test_origin, "cars", 1.0},
{TestInterestGroupObserver::kAdditionalBid, additional_bid_origin, {"1", TestInterestGroupObserver::kAdditionalBid,
"campaign123"}, additional_bid_origin, "campaign123", 0.1},
{TestInterestGroupObserver::kWin, test_origin, "cars"}}); {"1", TestInterestGroupObserver::kWin, test_origin, "cars"}});
} }
} }
} }
@@ -18417,9 +18457,9 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
WaitForUrl(embedded_https_test_server().GetURL( WaitForUrl(embedded_https_test_server().GetURL(
"a.test", "/echoall?report_bidder_additional")); "a.test", "/echoall?report_bidder_additional"));
WaitForAccessObserved({ WaitForAccessObserved({
{TestInterestGroupObserver::kAdditionalBid, additional_bid_origin, {"1", TestInterestGroupObserver::kAdditionalBid, additional_bid_origin,
"campaign123"}, "campaign123", 2.0},
{TestInterestGroupObserver::kAdditionalBidWin, additional_bid_origin, {"1", TestInterestGroupObserver::kAdditionalBidWin, additional_bid_origin,
"campaign123"}, "campaign123"},
}); });
} }
@@ -20162,6 +20202,7 @@ IN_PROC_BROWSER_TEST_F(
// so it does bid and win. // so it does bid and win.
IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
AdditionalBidOnComponentAuctionWithNoNegativeIGDoesBid) { AdditionalBidOnComponentAuctionWithNoNegativeIGDoesBid) {
AttachInterestGroupObserver();
URLLoaderMonitor url_loader_monitor; URLLoaderMonitor url_loader_monitor;
constexpr char kTestOrigin[] = "a.test"; constexpr char kTestOrigin[] = "a.test";
@@ -20235,6 +20276,19 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest,
kTestOrigin, "/echoall?report_bidder_additional")); kTestOrigin, "/echoall?report_bidder_additional"));
EXPECT_FALSE(HasServerSeenUrl(embedded_https_test_server().GetURL( EXPECT_FALSE(HasServerSeenUrl(embedded_https_test_server().GetURL(
kTestOrigin, "/echoall?report_bidder"))); kTestOrigin, "/echoall?report_bidder")));
url::Origin bid_origin = url::Origin::Create(test_url);
WaitForAccessObserved(
{{"global", TestInterestGroupObserver::kJoin, bid_origin, "cars"},
{"1", TestInterestGroupObserver::kLoaded, bid_origin, "cars"},
{"1", TestInterestGroupObserver::kAdditionalBid, bid_origin,
"campaign123", 1.99},
{"1", TestInterestGroupObserver::kBid, bid_origin, "cars", 1.0},
{"2", TestInterestGroupObserver::kTopLevelAdditionalBid, bid_origin,
"campaign123", 1.99, /*bid_currency=*/std::nullopt,
/*component_seller_origin=*/bid_origin},
{"2", TestInterestGroupObserver::kAdditionalBidWin, bid_origin,
"campaign123", /*bid=*/std::nullopt, /*bid_currency=*/std::nullopt,
/*component_seller_origin=*/bid_origin}});
} }
// Test to make sure that Promises configuration fields that are checked early // Test to make sure that Promises configuration fields that are checked early
@@ -20314,11 +20368,11 @@ IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, NotificationOrder) {
// Expect events to be in order. // Expect events to be in order.
WaitForAccessObservedInOrder( WaitForAccessObservedInOrder(
{{TestInterestGroupObserver::kJoin, test_origin, "cars"}, {{"global", TestInterestGroupObserver::kJoin, test_origin, "cars"},
{TestInterestGroupObserver::kJoin, test_origin, "golf carts"}, {"global", TestInterestGroupObserver::kJoin, test_origin, "golf carts"},
{TestInterestGroupObserver::kClear, test_origin, "golf carts"}, {"global", TestInterestGroupObserver::kClear, test_origin, "golf carts"},
{TestInterestGroupObserver::kLoaded, test_origin, "cars"}, {"1", TestInterestGroupObserver::kLoaded, test_origin, "cars"},
{TestInterestGroupObserver::kLeave, test_origin, "cars"}}); {"global", TestInterestGroupObserver::kLeave, test_origin, "cars"}});
} }
// Make sure we don't crash when cross-frame promise resolution tries to notify // Make sure we don't crash when cross-frame promise resolution tries to notify

@@ -306,7 +306,10 @@ void InterestGroupManagerImpl::OnClearOriginJoinedInterestGroupsComplete(
const url::Origin& owner, const url::Origin& owner,
std::vector<std::string> left_interest_group_names) { std::vector<std::string> left_interest_group_names) {
for (const auto& name : left_interest_group_names) { for (const auto& name : left_interest_group_names) {
NotifyInterestGroupAccessed(InterestGroupObserver::kClear, owner, name); NotifyInterestGroupAccessed(
/*devtools_auction_id=*/std::nullopt, InterestGroupObserver::kClear,
owner, name, /*component_seller_origin=*/std::nullopt,
/*bid=*/std::nullopt, /*bid_currency=*/std::nullopt);
} }
} }
@@ -391,12 +394,14 @@ void InterestGroupManagerImpl::GetAllInterestGroupOwners(
} }
void InterestGroupManagerImpl::GetInterestGroupsForOwner( void InterestGroupManagerImpl::GetInterestGroupsForOwner(
const std::optional<std::string>& devtools_auction_id,
const url::Origin& owner, const url::Origin& owner,
base::OnceCallback<void(scoped_refptr<StorageInterestGroups>)> callback) { base::OnceCallback<void(scoped_refptr<StorageInterestGroups>)> callback) {
caching_storage_.GetInterestGroupsForOwner( caching_storage_.GetInterestGroupsForOwner(
owner, owner,
base::BindOnce(&InterestGroupManagerImpl::OnGetInterestGroupsComplete, base::BindOnce(&InterestGroupManagerImpl::OnGetInterestGroupsComplete,
weak_factory_.GetWeakPtr(), std::move(callback))); weak_factory_.GetWeakPtr(), std::move(callback),
devtools_auction_id));
} }
void InterestGroupManagerImpl::DeleteInterestGroupData( void InterestGroupManagerImpl::DeleteInterestGroupData(
@@ -527,8 +532,10 @@ void InterestGroupManagerImpl::LoadNextInterestGroupAdAuctionData(
if (!owners.empty()) { if (!owners.empty()) {
url::Origin next_owner = std::move(owners.back()); url::Origin next_owner = std::move(owners.back());
owners.pop_back(); owners.pop_back();
// Since a single B&A blob can be associated with multiple auctions, we
// can't link these loads to a specific one.
GetInterestGroupsForOwner( GetInterestGroupsForOwner(
next_owner, /*devtools_auction_id=*/absl::nullopt, next_owner,
base::BindOnce( base::BindOnce(
&InterestGroupManagerImpl::OnLoadedNextInterestGroupAdAuctionData, &InterestGroupManagerImpl::OnLoadedNextInterestGroupAdAuctionData,
weak_factory_.GetWeakPtr(), std::move(state), std::move(owners), weak_factory_.GetWeakPtr(), std::move(state), std::move(owners),
@@ -674,8 +681,6 @@ void InterestGroupManagerImpl::UpdateInterestGroup(
const blink::InterestGroupKey& group_key, const blink::InterestGroupKey& group_key,
InterestGroupUpdate update, InterestGroupUpdate update,
base::OnceCallback<void(bool)> callback) { base::OnceCallback<void(bool)> callback) {
NotifyInterestGroupAccessed(InterestGroupObserver::kUpdate, group_key.owner,
group_key.name);
caching_storage_.UpdateInterestGroup( caching_storage_.UpdateInterestGroup(
group_key, std::move(update), group_key, std::move(update),
base::BindOnce(&InterestGroupManagerImpl::OnUpdateComplete, base::BindOnce(&InterestGroupManagerImpl::OnUpdateComplete,
@@ -688,8 +693,11 @@ void InterestGroupManagerImpl::OnUpdateComplete(
const std::string& name, const std::string& name,
base::OnceCallback<void(bool)> callback, base::OnceCallback<void(bool)> callback,
bool success) { bool success) {
NotifyInterestGroupAccessed(InterestGroupObserver::kUpdate, owner_origin, NotifyInterestGroupAccessed(/*devtools_auction_id=*/std::nullopt,
name); InterestGroupObserver::kUpdate, owner_origin,
name, /*component_seller_origin=*/std::nullopt,
/*bid=*/std::nullopt,
/*bid_currency=*/std::nullopt);
std::move(callback).Run(success); std::move(callback).Run(success);
} }
@@ -701,26 +709,35 @@ void InterestGroupManagerImpl::ReportUpdateFailed(
void InterestGroupManagerImpl::OnGetInterestGroupsComplete( void InterestGroupManagerImpl::OnGetInterestGroupsComplete(
base::OnceCallback<void(scoped_refptr<StorageInterestGroups>)> callback, base::OnceCallback<void(scoped_refptr<StorageInterestGroups>)> callback,
const std::optional<std::string>& devtools_auction_id,
scoped_refptr<StorageInterestGroups> groups) { scoped_refptr<StorageInterestGroups> groups) {
for (const SingleStorageInterestGroup& group : groups->GetInterestGroups()) { for (const SingleStorageInterestGroup& group : groups->GetInterestGroups()) {
NotifyInterestGroupAccessed(InterestGroupObserver::kLoaded, NotifyInterestGroupAccessed(
group->interest_group.owner, devtools_auction_id, InterestGroupObserver::kLoaded,
group->interest_group.name); group->interest_group.owner, group->interest_group.name,
/*component_seller_origin=*/std::nullopt,
/*bid=*/std::nullopt, /*bid_currency=*/std::nullopt);
} }
std::move(callback).Run(std::move(groups)); std::move(callback).Run(std::move(groups));
} }
void InterestGroupManagerImpl::NotifyInterestGroupAccessed( void InterestGroupManagerImpl::NotifyInterestGroupAccessed(
base::optional_ref<const std::string> devtools_auction_id,
InterestGroupObserver::AccessType type, InterestGroupObserver::AccessType type,
const url::Origin& owner_origin, const url::Origin& owner_origin,
const std::string& name) { const std::string& name,
base::optional_ref<const url::Origin> component_seller_origin,
std::optional<double> bid,
base::optional_ref<const std::string> bid_currency) {
// Don't bother getting the time if there are no observers. // Don't bother getting the time if there are no observers.
if (observers_.empty()) { if (observers_.empty()) {
return; return;
} }
base::Time now = base::Time::Now(); base::Time now = base::Time::Now();
for (InterestGroupObserver& observer : observers_) { for (InterestGroupObserver& observer : observers_) {
observer.OnInterestGroupAccessed(now, type, owner_origin, name); observer.OnInterestGroupAccessed(
devtools_auction_id, now, type, owner_origin, name,
component_seller_origin, bid, bid_currency);
} }
} }
@@ -823,8 +840,15 @@ InterestGroupManagerImpl::CreateNotifyInterestGroupAccessedCallback(
InterestGroupObserver::AccessType type, InterestGroupObserver::AccessType type,
const url::Origin& owner_origin, const url::Origin& owner_origin,
const std::string& name) { const std::string& name) {
// This is only used for join/leave, so no auction ID associated.
DCHECK(type == InterestGroupObserver::kJoin ||
type == InterestGroupObserver::kLeave);
return base::BindOnce(&InterestGroupManagerImpl::NotifyInterestGroupAccessed, return base::BindOnce(&InterestGroupManagerImpl::NotifyInterestGroupAccessed,
weak_factory_.GetWeakPtr(), type, owner_origin, name); weak_factory_.GetWeakPtr(),
/*devtools_auction_id=*/std::nullopt, type,
owner_origin, name,
/*component_seller_origin=*/std::nullopt,
/*bid=*/std::nullopt, /*bid_currency=*/std::nullopt);
} }
} // namespace content } // namespace content

@@ -21,6 +21,7 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "base/types/expected.h" #include "base/types/expected.h"
#include "base/types/optional_ref.h"
#include "content/browser/interest_group/auction_process_manager.h" #include "content/browser/interest_group/auction_process_manager.h"
#include "content/browser/interest_group/bidding_and_auction_serializer.h" #include "content/browser/interest_group/bidding_and_auction_serializer.h"
#include "content/browser/interest_group/bidding_and_auction_server_key_fetcher.h" #include "content/browser/interest_group/bidding_and_auction_server_key_fetcher.h"
@@ -106,11 +107,19 @@ class CONTENT_EXPORT InterestGroupManagerImpl : public InterestGroupManager {
kWin, kWin,
kAdditionalBidWin, kAdditionalBidWin,
kClear, kClear,
kTopLevelBid,
kTopLevelAdditionalBid
}; };
virtual void OnInterestGroupAccessed(const base::Time& access_time,
AccessType type, virtual void OnInterestGroupAccessed(
const url::Origin& owner_origin, base::optional_ref<const std::string> devtools_auction_id,
const std::string& name) = 0; base::Time access_time,
AccessType type,
const url::Origin& owner_origin,
const std::string& name,
base::optional_ref<const url::Origin> component_seller_origin,
std::optional<double> bid,
base::optional_ref<const std::string> bid_currency) = 0;
}; };
// InterestGroupManager overrides: // InterestGroupManager overrides:
@@ -271,6 +280,7 @@ class CONTENT_EXPORT InterestGroupManagerImpl : public InterestGroupManager {
// Gets a list of all interest groups with their bidding information // Gets a list of all interest groups with their bidding information
// associated with the provided owner. // associated with the provided owner.
void GetInterestGroupsForOwner( void GetInterestGroupsForOwner(
const std::optional<std::string>& devtools_auction_id,
const url::Origin& owner, const url::Origin& owner,
base::OnceCallback<void(scoped_refptr<StorageInterestGroups>)> callback); base::OnceCallback<void(scoped_refptr<StorageInterestGroups>)> callback);
@@ -421,9 +431,14 @@ class CONTENT_EXPORT InterestGroupManagerImpl : public InterestGroupManager {
// database (can't log them all before the database update, since for, e.g., // database (can't log them all before the database update, since for, e.g.,
// calls to retrieve all interest groups for an owner, the name may not be // calls to retrieve all interest groups for an owner, the name may not be
// known until after the database has been accessed). // known until after the database has been accessed).
void NotifyInterestGroupAccessed(InterestGroupObserver::AccessType type, void NotifyInterestGroupAccessed(
const url::Origin& owner_origin, base::optional_ref<const std::string> devtools_auction_id,
const std::string& name); InterestGroupObserver::AccessType type,
const url::Origin& owner_origin,
const std::string& name,
base::optional_ref<const url::Origin> component_seller_origin,
std::optional<double> bid,
base::optional_ref<const std::string> bid_currency);
private: private:
// InterestGroupUpdateManager calls private members to write updates to the // InterestGroupUpdateManager calls private members to write updates to the
@@ -525,6 +540,7 @@ class CONTENT_EXPORT InterestGroupManagerImpl : public InterestGroupManager {
void OnGetInterestGroupsComplete( void OnGetInterestGroupsComplete(
base::OnceCallback<void(scoped_refptr<StorageInterestGroups>)> callback, base::OnceCallback<void(scoped_refptr<StorageInterestGroups>)> callback,
const std::optional<std::string>& devtools_auction_id,
scoped_refptr<StorageInterestGroups> groups); scoped_refptr<StorageInterestGroups> groups);
// Dequeues and sends the first report request in `report_requests_` queue, // Dequeues and sends the first report request in `report_requests_` queue,

@@ -89,10 +89,14 @@ void TestInterestGroupManagerImpl::EnqueueReports(
} }
void TestInterestGroupManagerImpl::OnInterestGroupAccessed( void TestInterestGroupManagerImpl::OnInterestGroupAccessed(
const base::Time& access_time, base::optional_ref<const std::string> devtools_auction_id,
base::Time access_time,
AccessType type, AccessType type,
const url::Origin& owner_origin, const url::Origin& owner_origin,
const std::string& name) { const std::string& name,
base::optional_ref<const url::Origin> component_seller_origin,
std::optional<double> bid,
base::optional_ref<const std::string> bid_currency) {
if (type == AccessType::kBid) { if (type == AccessType::kBid) {
interest_groups_that_bid_.emplace_back(owner_origin, name); interest_groups_that_bid_.emplace_back(owner_origin, name);
} }

@@ -69,10 +69,15 @@ class TestInterestGroupManagerImpl
// //
// This is used instead of a virtual method for tracking bids, since it has // This is used instead of a virtual method for tracking bids, since it has
// all the information that's needed. // all the information that's needed.
void OnInterestGroupAccessed(const base::Time& access_time, void OnInterestGroupAccessed(
AccessType type, base::optional_ref<const std::string> devtools_auction_id,
const url::Origin& owner_origin, base::Time access_time,
const std::string& name) override; AccessType type,
const url::Origin& owner_origin,
const std::string& name,
base::optional_ref<const url::Origin> component_seller_origin,
std::optional<double> bid,
base::optional_ref<const std::string> bid_currency) override;
// KAnonymityServiceDelegate implementation: // KAnonymityServiceDelegate implementation:
void JoinSet(std::string id, void JoinSet(std::string id,

@@ -10,6 +10,7 @@
#include <vector> #include <vector>
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "content/browser/interest_group/interest_group_manager_impl.h" #include "content/browser/interest_group/interest_group_manager_impl.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
@@ -19,16 +20,59 @@
namespace content { namespace content {
TestInterestGroupObserver::Entry::Entry(
std::string devtools_auction_id,
InterestGroupManagerImpl::InterestGroupObserver::AccessType access_type,
url::Origin owner_origin,
std::string ig_name,
std::optional<double> bid,
std::optional<std::string> bid_currency,
std::optional<url::Origin> component_seller_origin)
: devtools_auction_id(std::move(devtools_auction_id)),
access_type(access_type),
owner_origin(std::move(owner_origin)),
ig_name(std::move(ig_name)),
bid(std::move(bid)),
bid_currency(std::move(bid_currency)),
component_seller_origin(std::move(component_seller_origin)) {}
TestInterestGroupObserver::Entry::Entry(const Entry&) = default;
TestInterestGroupObserver::Entry::~Entry() = default;
TestInterestGroupObserver::Entry& TestInterestGroupObserver::Entry::operator=(
const Entry&) = default;
bool TestInterestGroupObserver::Entry::operator==(const Entry&) const = default;
TestInterestGroupObserver::TestInterestGroupObserver() = default; TestInterestGroupObserver::TestInterestGroupObserver() = default;
TestInterestGroupObserver::~TestInterestGroupObserver() = default; TestInterestGroupObserver::~TestInterestGroupObserver() = default;
void TestInterestGroupObserver::OnInterestGroupAccessed( void TestInterestGroupObserver::OnInterestGroupAccessed(
const base::Time& access_time, base::optional_ref<const std::string> devtools_auction_id,
base::Time access_time,
InterestGroupManagerImpl::InterestGroupObserver::AccessType type, InterestGroupManagerImpl::InterestGroupObserver::AccessType type,
const url::Origin& owner_origin, const url::Origin& owner_origin,
const std::string& name) { const std::string& name,
accesses_.emplace_back(type, owner_origin, name); base::optional_ref<const url::Origin> component_seller_origin,
std::optional<double> bid,
base::optional_ref<const std::string> bid_currency) {
// Hide the randomness of auction IDs for easier testing by renaming them to
// sequential integers (and "global" if not set)
std::string normalized_auction_id = "global";
if (devtools_auction_id.has_value()) {
auto it = seen_auction_ids_.find(*devtools_auction_id);
if (it != seen_auction_ids_.end()) {
normalized_auction_id = it->second;
} else {
normalized_auction_id =
base::NumberToString(seen_auction_ids_.size() + 1);
seen_auction_ids_[*devtools_auction_id] = normalized_auction_id;
}
}
accesses_.emplace_back(normalized_auction_id, type, owner_origin, name, bid,
bid_currency.CopyAsOptional(),
component_seller_origin.CopyAsOptional());
if (run_loop_ && accesses_.size() >= expected_.size()) { if (run_loop_ && accesses_.size() >= expected_.size()) {
run_loop_->Quit(); run_loop_->Quit();
@@ -65,4 +109,28 @@ void TestInterestGroupObserver::WaitForAccessesInOrder(
accesses_.clear(); accesses_.clear();
} }
void PrintTo(const TestInterestGroupObserver::Entry& e, std::ostream* os) {
*os << "(";
*os << e.devtools_auction_id << ", ";
*os << e.access_type << ", ";
*os << e.owner_origin.Serialize() << ", ";
*os << e.ig_name << ", ";
if (e.bid.has_value()) {
*os << e.bid.value() << ", ";
} else {
*os << "(no bid), ";
}
if (e.bid_currency.has_value()) {
*os << e.bid_currency.value() << ", ";
} else {
*os << "(no bid_currency), ";
}
if (e.component_seller_origin.has_value()) {
*os << e.component_seller_origin->Serialize();
} else {
*os << "(no component_seller_origin)";
}
*os << ")";
}
} // namespace content } // namespace content

@@ -5,7 +5,10 @@
#ifndef CONTENT_BROWSER_INTEREST_GROUP_TEST_INTEREST_GROUP_OBSERVER_H_ #ifndef CONTENT_BROWSER_INTEREST_GROUP_TEST_INTEREST_GROUP_OBSERVER_H_
#define CONTENT_BROWSER_INTEREST_GROUP_TEST_INTEREST_GROUP_OBSERVER_H_ #define CONTENT_BROWSER_INTEREST_GROUP_TEST_INTEREST_GROUP_OBSERVER_H_
#include <map>
#include <memory> #include <memory>
#include <optional>
#include <ostream>
#include <string> #include <string>
#include <tuple> #include <tuple>
#include <vector> #include <vector>
@@ -22,10 +25,31 @@ namespace content {
class TestInterestGroupObserver class TestInterestGroupObserver
: public InterestGroupManagerImpl::InterestGroupObserver { : public InterestGroupManagerImpl::InterestGroupObserver {
public: public:
using Entry = struct Entry {
std::tuple<InterestGroupManagerImpl::InterestGroupObserver::AccessType, Entry(
url::Origin, std::string devtools_auction_id,
std::string>; InterestGroupManagerImpl::InterestGroupObserver::AccessType access_type,
url::Origin owner_origin,
std::string ig_name,
std::optional<double> bid = std::nullopt,
std::optional<std::string> bid_currency = std::nullopt,
std::optional<url::Origin> component_seller_origin = std::nullopt);
Entry(const Entry&);
~Entry();
Entry& operator=(const Entry&);
bool operator==(const Entry&) const;
// The auction ID is replaced by either "global" or a number starting from
// 1, strinfigied.
std::string devtools_auction_id;
InterestGroupManagerImpl::InterestGroupObserver::AccessType access_type;
url::Origin owner_origin;
std::string ig_name;
std::optional<double> bid;
std::optional<std::string> bid_currency;
std::optional<url::Origin> component_seller_origin;
};
TestInterestGroupObserver(); TestInterestGroupObserver();
~TestInterestGroupObserver() override; ~TestInterestGroupObserver() override;
@@ -36,10 +60,14 @@ class TestInterestGroupObserver
// InterestGroupManagerImpl::InterestGroupObserver implementation: // InterestGroupManagerImpl::InterestGroupObserver implementation:
void OnInterestGroupAccessed( void OnInterestGroupAccessed(
const base::Time& access_time, base::optional_ref<const std::string> devtools_auction_id,
base::Time access_time,
InterestGroupManagerImpl::InterestGroupObserver::AccessType type, InterestGroupManagerImpl::InterestGroupObserver::AccessType type,
const url::Origin& owner_origin, const url::Origin& owner_origin,
const std::string& name) override; const std::string& name,
base::optional_ref<const url::Origin> component_seller_origin,
std::optional<double> bid,
base::optional_ref<const std::string> bid_currency) override;
// Waits until exactly the expected events have seen, in the passed in order. // Waits until exactly the expected events have seen, in the passed in order.
// Once they have been observed, clears the log of the previous events. Note // Once they have been observed, clears the log of the previous events. Note
@@ -54,11 +82,15 @@ class TestInterestGroupObserver
void WaitForAccessesInOrder(const std::vector<Entry>& expected); void WaitForAccessesInOrder(const std::vector<Entry>& expected);
private: private:
std::map<std::string, std::string> seen_auction_ids_;
std::vector<Entry> accesses_; std::vector<Entry> accesses_;
std::vector<Entry> expected_; std::vector<Entry> expected_;
std::unique_ptr<base::RunLoop> run_loop_; std::unique_ptr<base::RunLoop> run_loop_;
}; };
// Printer for gtest.
void PrintTo(const TestInterestGroupObserver::Entry& e, std::ostream* os);
} // namespace content } // namespace content
#endif // CONTENT_BROWSER_INTEREST_GROUP_TEST_INTEREST_GROUP_OBSERVER_H_ #endif // CONTENT_BROWSER_INTEREST_GROUP_TEST_INTEREST_GROUP_OBSERVER_H_

@@ -206,9 +206,10 @@ class RemoveInterestGroupTester {
static_cast<InterestGroupManagerImpl*>( static_cast<InterestGroupManagerImpl*>(
storage_partition_->GetInterestGroupManager()) storage_partition_->GetInterestGroupManager())
->GetInterestGroupsForOwner( ->GetInterestGroupsForOwner(
origin, base::BindOnce( /*devtools_auction_id=*/std::nullopt, origin,
&RemoveInterestGroupTester::GetInterestGroupsCallback, base::BindOnce(
base::Unretained(this), loop.QuitClosure())); &RemoveInterestGroupTester::GetInterestGroupsCallback,
base::Unretained(this), loop.QuitClosure()));
loop.Run(); loop.Run();
return get_interest_group_success_; return get_interest_group_success_;
} }

@@ -9521,6 +9521,9 @@ experimental domain Storage
string issuerOrigin string issuerOrigin
number count number count
# Protected audience interest group auction identifier.
type InterestGroupAuctionId extends string
# Enum of interest group access types. # Enum of interest group access types.
type InterestGroupAccessType extends string type InterestGroupAccessType extends string
enum enum
@@ -9532,8 +9535,16 @@ experimental domain Storage
win win
additionalBid additionalBid
additionalBidWin additionalBidWin
topLevelBid
topLevelAdditionalBid
clear clear
# Enum of auction events.
type InterestGroupAuctionEventType extends string
enum
started
configResolved
# Ad advertising element inside an interest group. # Ad advertising element inside an interest group.
type InterestGroupAd extends object type InterestGroupAd extends object
properties properties
@@ -9813,6 +9824,11 @@ experimental domain Storage
parameters parameters
boolean enable boolean enable
# Enables/Disables issuing of interestGroupAuctionEvent events.
experimental command setInterestGroupAuctionTracking
parameters
boolean enable
# Gets metadata for an origin's shared storage. # Gets metadata for an origin's shared storage.
experimental command getSharedStorageMetadata experimental command getSharedStorageMetadata
parameters parameters
@@ -9920,13 +9936,34 @@ experimental domain Storage
# Storage bucket to update. # Storage bucket to update.
string bucketId string bucketId
# One of the interest groups was accessed by the associated page. # One of the interest groups was accessed. Note that these events are global
# to all targets sharing an interest group store.
event interestGroupAccessed event interestGroupAccessed
parameters parameters
Network.TimeSinceEpoch accessTime Network.TimeSinceEpoch accessTime
InterestGroupAccessType type InterestGroupAccessType type
string ownerOrigin string ownerOrigin
string name string name
# For topLevelBid/topLevelAdditionalBid, and when appropriate,
# win and additionalBidWin
optional string componentSellerOrigin
# For bid or somethingBid event, if done locally and not on a server.
optional number bid
optional string bidCurrency
# For non-global events --- links to interestGroupAuctionEvent
optional InterestGroupAuctionId uniqueAuctionId
# An auction involving interest groups is taking place. These events are
# target-specific.
event interestGroupAuctionEventOccurred
parameters
Network.TimeSinceEpoch eventTime
InterestGroupAuctionEventType type
InterestGroupAuctionId uniqueAuctionId
# Set for child auctions.
optional InterestGroupAuctionId parentAuctionId
# Set for started and configResolved
optional object auctionConfig
# Shared storage was accessed by the associated page. # Shared storage was accessed by the associated page.
# The following parameters are included in all events. # The following parameters are included in all events.

@@ -1,12 +1,26 @@
Tests that interest groups are read and cleared. Tests that interest groups are read and cleared.
Start Tracking Start Tracking
Events logged: 7 Logged IG events:
{ interestGroupAuctionEventOccurred {
"ownerOrigin": "https://a.test:8443", auctionConfig : {
"name": "0", decisionLogicUrl : https://a.test:8443/inspector-protocol/resources/fledge_decision_logic.js.php
"type": "join" interestGroupBuyers : [
[0] : https://a.test:8443
]
seller : https://a.test:8443
}
eventTime : <number>
type : started
uniqueAuctionId : 1
} }
{ interestGroupAccessed {
accessTime : <number>
name : 0
ownerOrigin : https://a.test:8443
type : join
uniqueAuctionId : global
}
interestGroupDetails {
adComponents : [ adComponents : [
] ]
ads : [ ads : [
@@ -23,12 +37,14 @@ Events logged: 7
trustedBiddingSignalsKeys : [ trustedBiddingSignalsKeys : [
] ]
} }
{ interestGroupAccessed {
"ownerOrigin": "https://a.test:8443", accessTime : <number>
"name": "1", name : 1
"type": "join" ownerOrigin : https://a.test:8443
type : join
uniqueAuctionId : global
} }
{ interestGroupDetails {
adComponents : [ adComponents : [
] ]
ads : [ ads : [
@@ -45,12 +61,14 @@ Events logged: 7
trustedBiddingSignalsKeys : [ trustedBiddingSignalsKeys : [
] ]
} }
{ interestGroupAccessed {
"ownerOrigin": "https://a.test:8443", accessTime : <number>
"name": "0", name : 0
"type": "loaded" ownerOrigin : https://a.test:8443
type : loaded
uniqueAuctionId : 1
} }
{ interestGroupDetails {
adComponents : [ adComponents : [
] ]
ads : [ ads : [
@@ -67,12 +85,14 @@ Events logged: 7
trustedBiddingSignalsKeys : [ trustedBiddingSignalsKeys : [
] ]
} }
{ interestGroupAccessed {
"ownerOrigin": "https://a.test:8443", accessTime : <number>
"name": "1", name : 1
"type": "loaded" ownerOrigin : https://a.test:8443
type : loaded
uniqueAuctionId : 1
} }
{ interestGroupDetails {
adComponents : [ adComponents : [
] ]
ads : [ ads : [
@@ -89,12 +109,15 @@ Events logged: 7
trustedBiddingSignalsKeys : [ trustedBiddingSignalsKeys : [
] ]
} }
{ interestGroupAccessed {
"ownerOrigin": "https://a.test:8443", accessTime : <number>
"name": "0", bid : 1
"type": "bid" name : 0
ownerOrigin : https://a.test:8443
type : bid
uniqueAuctionId : 1
} }
{ interestGroupDetails {
adComponents : [ adComponents : [
] ]
ads : [ ads : [
@@ -111,12 +134,15 @@ Events logged: 7
trustedBiddingSignalsKeys : [ trustedBiddingSignalsKeys : [
] ]
} }
{ interestGroupAccessed {
"ownerOrigin": "https://a.test:8443", accessTime : <number>
"name": "1", bid : 2
"type": "bid" name : 1
ownerOrigin : https://a.test:8443
type : bid
uniqueAuctionId : 1
} }
{ interestGroupDetails {
adComponents : [ adComponents : [
] ]
ads : [ ads : [
@@ -133,12 +159,14 @@ Events logged: 7
trustedBiddingSignalsKeys : [ trustedBiddingSignalsKeys : [
] ]
} }
{ interestGroupAccessed {
"ownerOrigin": "https://a.test:8443", accessTime : <number>
"name": "1", name : 1
"type": "win" ownerOrigin : https://a.test:8443
type : win
uniqueAuctionId : 1
} }
{ interestGroupDetails {
adComponents : [ adComponents : [
] ]
ads : [ ads : [
@@ -155,6 +183,21 @@ Events logged: 7
trustedBiddingSignalsKeys : [ trustedBiddingSignalsKeys : [
] ]
} }
Stop Tracking Stop Tracking IG Events
Events logged: 0 Logged IG events:
interestGroupAuctionEventOccurred {
auctionConfig : {
decisionLogicUrl : https://a.test:8443/inspector-protocol/resources/fledge_decision_logic.js.php
interestGroupBuyers : [
[0] : https://a.test:8443
]
seller : https://a.test:8443
}
eventTime : <number>
type : started
uniqueAuctionId : 2
}
Stop Tracking Auction Events
Logged IG events:
Test Done

@@ -20,6 +20,20 @@
} }
} }
let nextAuctionId = 1;
let auctionIdMap = new Map();
function normalizeAuctionId(event) {
if ('uniqueAuctionId' in event) {
if (!auctionIdMap.has(event.uniqueAuctionId)) {
auctionIdMap.set(event.uniqueAuctionId, nextAuctionId);
++nextAuctionId;
}
return auctionIdMap.get(event.uniqueAuctionId);
} else {
return 'global';
}
}
// Helper for sorting IG devtools events. // Helper for sorting IG devtools events.
function compareEvents(a, b) { function compareEvents(a, b) {
let aTypeOrder = typeSortKey(a.type); let aTypeOrder = typeSortKey(a.type);
@@ -60,29 +74,52 @@
} }
events = []; events = [];
auctionEvents = [];
async function logAndClearEvents() { async function logAndClearEvents() {
testRunner.log(`Events logged: ${events.length}`); testRunner.log('Logged IG events:');
// We need to sort events before dumping since ordering of bids is not // We expect only one auction event, so no ordering issue to worry about.
for (let event of auctionEvents) {
event.uniqueAuctionId = normalizeAuctionId(event);
// Only some of auctionConfig fields are kept so this doesn't have to be
// changed every time something new is added that shows up by default.
const keepConfigFields =
new Set(['decisionLogicUrl', 'seller', 'interestGroupBuyers']);
for (let fieldName of Object.getOwnPropertyNames(event.auctionConfig)) {
if (!keepConfigFields.has(fieldName)) {
delete event.auctionConfig[fieldName];
}
}
testRunner.log(
event, 'interestGroupAuctionEventOccurred ', ['eventTime']);
}
// We need to sort IG events before dumping since ordering of bids is not
// deterministic. // deterministic.
events.sort(compareEvents); events.sort(compareEvents);
for (event of events) { for (let event of events) {
testRunner.log( event.uniqueAuctionId = normalizeAuctionId(event);
JSON.stringify(event, ['ownerOrigin', 'name', 'type'], 2)); testRunner.log(event, 'interestGroupAccessed ', ['accessTime']);
data = await dp.Storage.getInterestGroupDetails( data = await dp.Storage.getInterestGroupDetails(
{ownerOrigin: event.ownerOrigin, name: event.name}); {ownerOrigin: event.ownerOrigin, name: event.name});
const details = data.result.details; const details = data.result.details;
details.expirationTime = 0; details.expirationTime = 0;
testRunner.log(details); testRunner.log(details, 'interestGroupDetails ');
} }
auctionEvents = [];
events = []; events = [];
} }
let resolveWaitForWinPromise; let resolveWaitForWinPromise;
const waitForWinPromise = new Promise((resolve, reject)=>{ const waitForWinPromise = new Promise((resolve, reject) => {
resolveWaitForWinPromise = resolve; resolveWaitForWinPromise = resolve;
}); });
dp.Storage.onInterestGroupAccessed((messageObject)=>{ dp.Storage.onInterestGroupAuctionEventOccurred(messageObject => {
auctionEvents.push(messageObject.params);
});
dp.Storage.onInterestGroupAccessed(messageObject => {
events.push(messageObject.params); events.push(messageObject.params);
if (messageObject.params.type == 'win') { if (messageObject.params.type == 'win') {
resolveWaitForWinPromise(); resolveWaitForWinPromise();
@@ -92,6 +129,7 @@
// Start tracking, join interest groups, and run an auction. // Start tracking, join interest groups, and run an auction.
await dp.Storage.setInterestGroupTracking({enable: true}); await dp.Storage.setInterestGroupTracking({enable: true});
await dp.Storage.setInterestGroupAuctionTracking({enable: true});
testRunner.log("Start Tracking"); testRunner.log("Start Tracking");
await joinInterestGroups(0); await joinInterestGroups(0);
await joinInterestGroups(1); await joinInterestGroups(1);
@@ -112,12 +150,22 @@
// the logging of the bid events is potentially racy with enabling/disabling // the logging of the bid events is potentially racy with enabling/disabling
// logging. // logging.
await dp.Storage.setInterestGroupTracking({enable: false}); await dp.Storage.setInterestGroupTracking({enable: false});
testRunner.log("Stop Tracking"); testRunner.log('Stop Tracking IG Events');
// These calls should not trigger any events, since tracking is disabled. // These calls should only trigger auction events, since IG tracking is
// disabled.
await joinInterestGroups(0); await joinInterestGroups(0);
await joinInterestGroups(1); await joinInterestGroups(1);
await runAdAuctionAndNavigateFencedFrame(); await runAdAuctionAndNavigateFencedFrame();
logAndClearEvents(); logAndClearEvents();
testRunner.log('Stop Tracking Auction Events');
await dp.Storage.setInterestGroupAuctionTracking({enable: false});
// Now nothing should show up.
await joinInterestGroups(0);
await joinInterestGroups(1);
await runAdAuctionAndNavigateFencedFrame();
logAndClearEvents();
testRunner.log('Test Done')
testRunner.completeTest(); testRunner.completeTest();
}) })