blob: 93b1285000372c8f3ebeeeafedf4e641f8487abe [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/fenced_frame/fenced_frame_reporter.h"
#include <iterator>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "base/atomic_sequence_num.h"
#include "base/check.h"
#include "base/check_op.h"
#include "base/containers/flat_map.h"
#include "base/functional/bind.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
#include "base/strings/strcat.h"
#include "base/types/pass_key.h"
#include "content/browser/attribution_reporting/attribution_beacon_id.h"
#include "content/browser/attribution_reporting/attribution_data_host_manager.h"
#include "content/browser/attribution_reporting/attribution_host.h"
#include "content/browser/attribution_reporting/attribution_manager.h"
#include "content/browser/devtools/devtools_instrumentation.h"
#include "content/browser/devtools/network_service_devtools_observer.h"
#include "content/browser/devtools/protocol/network_handler.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/interest_group/interest_group_pa_report_util.h"
#include "content/browser/private_aggregation/private_aggregation_budget_key.h"
#include "content/browser/private_aggregation/private_aggregation_manager.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/services/auction_worklet/public/mojom/private_aggregation_request.mojom.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/http/http_response_headers.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/attribution_reporting_runtime_features.h"
#include "services/network/public/cpp/attribution_utils.h"
#include "services/network/public/cpp/devtools_observer_util.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/attribution.mojom.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/fenced_frame/redacted_fenced_frame_config.h"
#include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-shared.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace content {
namespace {
constexpr net::NetworkTrafficAnnotationTag kReportingBeaconNetworkTag =
net::DefineNetworkTrafficAnnotation("fenced_frame_reporting_beacon",
R"(
semantics {
sender: "Fenced frame reportEvent API"
description:
"This request sends out reporting beacon data in an HTTP POST "
"request. This is initiated by window.fence.reportEvent API."
trigger:
"When there are events such as impressions, user interactions and "
"clicks, fenced frames can invoke window.fence.reportEvent API. It "
"tells the browser to send a beacon with event data to a URL "
"registered by the worklet in registerAdBeacon. Please see "
"https://github.com/WICG/turtledove/blob/main/Fenced_Frames_Ads_Reporting.md#reportevent"
data:
"Event data given by fenced frame reportEvent API. Please see "
"https://github.com/WICG/turtledove/blob/main/Fenced_Frames_Ads_Reporting.md#parameters"
destination: OTHER
destination_other: "The reporting destination given by FLEDGE's "
"registerAdBeacon API or selectURL's inputs."
internal {
contacts {
email: "chrome-fenced-frames@google.com"
}
}
user_data {
type: NONE
}
last_reviewed: "2023-01-04"
}
policy {
cookies_allowed: NO
setting: "To use reportEvent API, users need to enable selectURL, "
"FLEDGE and FencedFrames features by enabling the Privacy Sandbox "
"Ads APIs experiment flag at "
"chrome://flags/#privacy-sandbox-ads-apis "
policy_exception_justification: "This beacon is sent by fenced frame "
"calling window.fence.reportEvent when there are events like user "
"interactions."
}
)");
base::StringPiece ReportingDestinationAsString(
const blink::FencedFrame::ReportingDestination& destination) {
switch (destination) {
case blink::FencedFrame::ReportingDestination::kBuyer:
return "Buyer";
case blink::FencedFrame::ReportingDestination::kSeller:
return "Seller";
case blink::FencedFrame::ReportingDestination::kComponentSeller:
return "ComponentSeller";
case blink::FencedFrame::ReportingDestination::kSharedStorageSelectUrl:
return "SharedStorageSelectUrl";
case blink::FencedFrame::ReportingDestination::kDirectSeller:
return "DirectSeller";
}
NOTREACHED();
}
base::StringPiece InvokingAPIAsString(
const PrivacySandboxInvokingAPI invoking_api) {
switch (invoking_api) {
case PrivacySandboxInvokingAPI::kProtectedAudience:
return "Protected Audience";
case PrivacySandboxInvokingAPI::kSharedStorage:
return "Shared Storage";
}
NOTREACHED();
}
} // namespace
FencedFrameReporter::PendingEvent::PendingEvent(
const std::string& type,
const std::string& data,
const url::Origin& request_initiator,
absl::optional<AttributionReportingData> attribution_reporting_data,
int initiator_frame_tree_node_id)
: type(type),
data(data),
request_initiator(request_initiator),
attribution_reporting_data(std::move(attribution_reporting_data)),
initiator_frame_tree_node_id(initiator_frame_tree_node_id) {}
FencedFrameReporter::PendingEvent::PendingEvent(const PendingEvent&) = default;
FencedFrameReporter::PendingEvent::PendingEvent(PendingEvent&&) = default;
FencedFrameReporter::PendingEvent& FencedFrameReporter::PendingEvent::operator=(
const PendingEvent&) = default;
FencedFrameReporter::PendingEvent& FencedFrameReporter::PendingEvent::operator=(
PendingEvent&&) = default;
FencedFrameReporter::PendingEvent::~PendingEvent() = default;
FencedFrameReporter::ReportingDestinationInfo::ReportingDestinationInfo(
absl::optional<ReportingUrlMap> reporting_url_map)
: reporting_url_map(std::move(reporting_url_map)) {}
FencedFrameReporter::ReportingDestinationInfo::ReportingDestinationInfo(
ReportingDestinationInfo&&) = default;
FencedFrameReporter::ReportingDestinationInfo::~ReportingDestinationInfo() =
default;
FencedFrameReporter::ReportingDestinationInfo&
FencedFrameReporter::ReportingDestinationInfo::operator=(
ReportingDestinationInfo&&) = default;
scoped_refptr<FencedFrameReporter> FencedFrameReporter::CreateForSharedStorage(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
BrowserContext* browser_context,
ReportingUrlMap reporting_url_map) {
// `private_aggregation_manager_`, `main_frame_origin_`, and `winner_origin_`
// are only needed by FLEDGE.
scoped_refptr<FencedFrameReporter> reporter =
base::MakeRefCounted<FencedFrameReporter>(
base::PassKey<FencedFrameReporter>(),
PrivacySandboxInvokingAPI::kSharedStorage,
std::move(url_loader_factory), browser_context);
reporter->reporting_metadata_.emplace(
blink::FencedFrame::ReportingDestination::kSharedStorageSelectUrl,
ReportingDestinationInfo(std::move(reporting_url_map)));
return reporter;
}
scoped_refptr<FencedFrameReporter> FencedFrameReporter::CreateForFledge(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
BrowserContext* browser_context,
bool direct_seller_is_seller,
PrivateAggregationManager* private_aggregation_manager,
const url::Origin& main_frame_origin,
const url::Origin& winner_origin) {
scoped_refptr<FencedFrameReporter> reporter =
base::MakeRefCounted<FencedFrameReporter>(
base::PassKey<FencedFrameReporter>(),
PrivacySandboxInvokingAPI::kProtectedAudience,
std::move(url_loader_factory), browser_context,
private_aggregation_manager, main_frame_origin, winner_origin);
reporter->direct_seller_is_seller_ = direct_seller_is_seller;
reporter->reporting_metadata_.emplace(
blink::FencedFrame::ReportingDestination::kBuyer,
ReportingDestinationInfo());
reporter->reporting_metadata_.emplace(
blink::FencedFrame::ReportingDestination::kSeller,
ReportingDestinationInfo());
reporter->reporting_metadata_.emplace(
blink::FencedFrame::ReportingDestination::kComponentSeller,
ReportingDestinationInfo());
return reporter;
}
FencedFrameReporter::FencedFrameReporter(
base::PassKey<FencedFrameReporter> pass_key,
PrivacySandboxInvokingAPI invoking_api,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
BrowserContext* browser_context,
PrivateAggregationManager* private_aggregation_manager,
const absl::optional<url::Origin>& main_frame_origin,
const absl::optional<url::Origin>& winner_origin)
: url_loader_factory_(std::move(url_loader_factory)),
attribution_manager_(
AttributionManager::FromBrowserContext(browser_context)),
browser_context_(browser_context),
private_aggregation_manager_(private_aggregation_manager),
main_frame_origin_(main_frame_origin),
winner_origin_(winner_origin),
invoking_api_(invoking_api) {
DCHECK(url_loader_factory_);
DCHECK(browser_context_);
// These should both be nullopt for non-FLEDGE fenced frames, and populated
// for FLEDGE fenced frames.
DCHECK_EQ(main_frame_origin_.has_value(), winner_origin_.has_value());
}
FencedFrameReporter::~FencedFrameReporter() {
for (const auto& [destination, destination_info] : reporting_metadata_) {
for (const auto& pending_event : destination_info.pending_events) {
NotifyFencedFrameReportingBeaconFailed(
pending_event.attribution_reporting_data);
}
}
}
void FencedFrameReporter::OnUrlMappingReady(
blink::FencedFrame::ReportingDestination reporting_destination,
ReportingUrlMap reporting_url_map) {
auto it = reporting_metadata_.find(reporting_destination);
DCHECK(it != reporting_metadata_.end());
DCHECK(!it->second.reporting_url_map);
it->second.reporting_url_map = std::move(reporting_url_map);
auto pending_events = std::exchange(it->second.pending_events, {});
for (const auto& pending_event : pending_events) {
std::string ignored_error_message;
blink::mojom::ConsoleMessageLevel ignored_console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
const std::string devtools_request_id =
base::UnguessableToken::Create().ToString();
SendReportInternal(it->second, pending_event.type, pending_event.data,
reporting_destination, pending_event.request_initiator,
pending_event.attribution_reporting_data,
pending_event.initiator_frame_tree_node_id,
ignored_error_message, ignored_console_message_level,
devtools_request_id);
}
}
bool FencedFrameReporter::SendReport(
const std::string& event_type,
const std::string& event_data,
blink::FencedFrame::ReportingDestination reporting_destination,
RenderFrameHostImpl* request_initiator_frame,
network::AttributionReportingRuntimeFeatures
attribution_reporting_runtime_features,
std::string& error_message,
blink::mojom::ConsoleMessageLevel& console_message_level,
int initiator_frame_tree_node_id,
absl::optional<int64_t> navigation_id) {
DCHECK(request_initiator_frame);
if (reporting_destination ==
blink::FencedFrame::ReportingDestination::kDirectSeller) {
if (direct_seller_is_seller_) {
reporting_destination = blink::FencedFrame::ReportingDestination::kSeller;
} else {
reporting_destination =
blink::FencedFrame::ReportingDestination::kComponentSeller;
}
}
auto it = reporting_metadata_.find(reporting_destination);
// Check metadata registration for given destination. If there's no map, or
// the map is empty, can't send a request. An entry with a null (not empty)
// map means the map is pending, and is handled below.
if (it == reporting_metadata_.end() ||
(it->second.reporting_url_map && it->second.reporting_url_map->empty())) {
error_message = base::StrCat(
{"This frame did not register reporting metadata for destination '",
ReportingDestinationAsString(reporting_destination), "'."});
console_message_level = blink::mojom::ConsoleMessageLevel::kWarning;
return false;
}
static base::AtomicSequenceNumber unique_id_counter;
absl::optional<AttributionReportingData> attribution_reporting_data;
const std::string devtools_request_id =
base::UnguessableToken::Create().ToString();
auto* attribution_host = AttributionHost::FromWebContents(
WebContents::FromRenderFrameHost(request_initiator_frame));
if (attribution_host &&
network::HasAttributionSupport(AttributionManager::GetSupport())) {
BeaconId beacon_id(unique_id_counter.GetNext());
if (attribution_host->NotifyFencedFrameReportingBeaconStarted(
beacon_id, navigation_id, request_initiator_frame,
devtools_request_id)) {
attribution_reporting_data.emplace(AttributionReportingData{
.beacon_id = beacon_id,
.is_automatic_beacon = navigation_id.has_value(),
.attribution_reporting_runtime_features =
attribution_reporting_runtime_features,
});
}
}
const url::Origin& request_initiator =
request_initiator_frame->GetLastCommittedOrigin();
// If the reporting URL map is pending, queue the event.
if (it->second.reporting_url_map == absl::nullopt) {
it->second.pending_events.emplace_back(
event_type, event_data, request_initiator,
std::move(attribution_reporting_data), initiator_frame_tree_node_id);
return true;
}
return SendReportInternal(it->second, event_type, event_data,
reporting_destination, request_initiator,
attribution_reporting_data,
initiator_frame_tree_node_id, error_message,
console_message_level, devtools_request_id);
}
bool FencedFrameReporter::SendReportInternal(
const ReportingDestinationInfo& reporting_destination_info,
const std::string& event_type,
const std::string& event_data,
blink::FencedFrame::ReportingDestination reporting_destination,
const url::Origin& request_initiator,
const absl::optional<AttributionReportingData>& attribution_reporting_data,
int initiator_frame_tree_node_id,
std::string& error_message,
blink::mojom::ConsoleMessageLevel& console_message_level,
const std::string& devtools_request_id) {
// The URL map should not be pending at this point.
DCHECK(reporting_destination_info.reporting_url_map);
// Check reporting url registration for given destination and event type.
const auto url_iter =
reporting_destination_info.reporting_url_map->find(event_type);
if (url_iter == reporting_destination_info.reporting_url_map->end()) {
error_message = base::StrCat(
{"This frame did not register reporting url for destination '",
ReportingDestinationAsString(reporting_destination),
"' and event_type '", event_type, "'."});
console_message_level = blink::mojom::ConsoleMessageLevel::kWarning;
NotifyFencedFrameReportingBeaconFailed(attribution_reporting_data);
return false;
}
// Validate the reporting url.
GURL url = url_iter->second;
if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS()) {
error_message = base::StrCat(
{"This frame registered invalid reporting url for destination '",
ReportingDestinationAsString(reporting_destination),
"' and event_type '", event_type, "'."});
console_message_level = blink::mojom::ConsoleMessageLevel::kError;
NotifyFencedFrameReportingBeaconFailed(attribution_reporting_data);
return false;
}
if (!GetContentClient()
->browser()
->IsPrivacySandboxReportingDestinationAttested(
browser_context_, url::Origin::Create(url), invoking_api_)) {
error_message = base::StrCat({
"The reporting destination '",
ReportingDestinationAsString(reporting_destination),
"' is not attested for '",
InvokingAPIAsString(invoking_api_),
"'.",
});
console_message_level = blink::mojom::ConsoleMessageLevel::kError;
NotifyFencedFrameReportingBeaconFailed(attribution_reporting_data);
return false;
}
// Construct the resource request.
auto request = std::make_unique<network::ResourceRequest>();
request->url = url;
request->mode = network::mojom::RequestMode::kCors;
request->request_initiator = request_initiator;
request->credentials_mode = network::mojom::CredentialsMode::kOmit;
request->method = net::HttpRequestHeaders::kPostMethod;
request->trusted_params = network::ResourceRequest::TrustedParams();
request->trusted_params->isolation_info =
net::IsolationInfo::CreateTransient();
// `attribution_reporting_data` is guaranteed to be set iff attribution
// reporting is allowed in the initiator frame.
const bool is_attribution_reporting_allowed =
attribution_reporting_data.has_value();
if (attribution_manager_ && is_attribution_reporting_allowed) {
request->attribution_reporting_eligibility =
attribution_reporting_data->is_automatic_beacon
? network::mojom::AttributionReportingEligibility::kNavigationSource
: network::mojom::AttributionReportingEligibility::kEventSource;
request->attribution_reporting_support = AttributionManager::GetSupport();
request->attribution_reporting_runtime_features =
attribution_reporting_data->attribution_reporting_runtime_features;
}
request->devtools_request_id = devtools_request_id;
FrameTreeNode* initiator_frame_tree_node =
FrameTreeNode::GloballyFindByID(initiator_frame_tree_node_id);
if (initiator_frame_tree_node) {
request->trusted_params->devtools_observer =
NetworkServiceDevToolsObserver::MakeSelfOwned(
initiator_frame_tree_node);
}
devtools_instrumentation::OnFencedFrameReportRequestSent(
initiator_frame_tree_node_id, devtools_request_id, *request);
// Create and configure `SimpleURLLoader` instance.
std::unique_ptr<network::SimpleURLLoader> simple_url_loader =
network::SimpleURLLoader::Create(std::move(request),
kReportingBeaconNetworkTag);
simple_url_loader->AttachStringForUpload(
event_data, /*upload_content_type=*/"text/plain;charset=UTF-8");
network::SimpleURLLoader* simple_url_loader_ptr = simple_url_loader.get();
AttributionDataHostManager* attribution_data_host_manager =
attribution_manager_ ? attribution_manager_->GetDataHostManager()
: nullptr;
if (attribution_data_host_manager && is_attribution_reporting_allowed) {
// Notify Attribution Reporting API for the beacons.
simple_url_loader_ptr->SetOnRedirectCallback(base::BindRepeating(
[](base::WeakPtr<AttributionDataHostManager>
attribution_data_host_manager,
BeaconId beacon_id,
network::AttributionReportingRuntimeFeatures
attribution_reporting_runtime_features,
const GURL& url_before_redirect,
const net::RedirectInfo& redirect_info,
const network::mojom::URLResponseHead& response_head,
std::vector<std::string>* removed_headers) {
if (attribution_data_host_manager) {
attribution_data_host_manager->NotifyFencedFrameReportingBeaconData(
beacon_id, attribution_reporting_runtime_features,
url_before_redirect, response_head.headers.get(),
/*is_final_response=*/false);
}
},
attribution_data_host_manager->AsWeakPtr(),
attribution_reporting_data->beacon_id,
attribution_reporting_data->attribution_reporting_runtime_features));
// Send out the reporting beacon.
simple_url_loader_ptr->DownloadHeadersOnly(
url_loader_factory_.get(),
base::BindOnce(
[](base::WeakPtr<AttributionDataHostManager>
attribution_data_host_manager,
BeaconId beacon_id,
network::AttributionReportingRuntimeFeatures
attribution_reporting_runtime_features,
std::unique_ptr<network::SimpleURLLoader> loader,
int initiator_frame_tree_node_id,
std::string devtools_request_id,
scoped_refptr<net::HttpResponseHeaders> headers) {
if (attribution_data_host_manager) {
attribution_data_host_manager
->NotifyFencedFrameReportingBeaconData(
beacon_id, attribution_reporting_runtime_features,
loader->GetFinalURL(), headers.get(),
/*is_final_response=*/true);
}
// Set up DevTools integration for the response.
devtools_instrumentation::OnFencedFrameReportResponseReceived(
initiator_frame_tree_node_id, devtools_request_id,
loader->GetFinalURL(), headers);
},
attribution_data_host_manager->AsWeakPtr(),
attribution_reporting_data->beacon_id,
attribution_reporting_data->attribution_reporting_runtime_features,
std::move(simple_url_loader), initiator_frame_tree_node_id,
devtools_request_id));
} else {
// Send out the reporting beacon.
simple_url_loader_ptr->DownloadHeadersOnly(
url_loader_factory_.get(),
base::BindOnce(
[](std::unique_ptr<network::SimpleURLLoader> loader,
int initiator_frame_tree_node_id,
std::string devtools_request_id,
scoped_refptr<net::HttpResponseHeaders> headers) {
// Set up DevTools integration for the response.
devtools_instrumentation::OnFencedFrameReportResponseReceived(
initiator_frame_tree_node_id, devtools_request_id,
loader->GetFinalURL(), headers);
},
std::move(simple_url_loader), initiator_frame_tree_node_id,
devtools_request_id));
}
return true;
}
void FencedFrameReporter::OnForEventPrivateAggregationRequestsReceived(
std::map<std::string, PrivateAggregationRequests>
private_aggregation_event_map) {
MaybeBindPrivateAggregationHost();
for (auto& [event_type, requests] : private_aggregation_event_map) {
PrivateAggregationRequests& destination_vector =
private_aggregation_event_map_[event_type];
destination_vector.insert(destination_vector.end(),
std::move_iterator(requests.begin()),
std::move_iterator(requests.end()));
}
for (const std::string& pa_event_type : received_pa_events_) {
SendPrivateAggregationRequestsForEventInternal(pa_event_type);
}
}
void FencedFrameReporter::SendPrivateAggregationRequestsForEvent(
const std::string& pa_event_type) {
if (!private_aggregation_manager_) {
// `private_aggregation_manager_` is nullptr when private aggregation
// feature flag is disabled, but a compromised renderer might still send
// events when it should not be able to. Simply ignores the events.
return;
}
MaybeBindPrivateAggregationHost();
// Always insert `pa_event_type` to `received_pa_events_`, since
// `private_aggregation_event_map_` might grow with more entries when
// reportWin() completes.
received_pa_events_.emplace(pa_event_type);
SendPrivateAggregationRequestsForEventInternal(pa_event_type);
}
void FencedFrameReporter::SendPrivateAggregationRequestsForEventInternal(
const std::string& pa_event_type) {
DCHECK(private_aggregation_host_.is_bound());
auto it = private_aggregation_event_map_.find(pa_event_type);
if (it == private_aggregation_event_map_.end()) {
return;
}
SplitContributionsIntoBatchesThenSendToHost(
/*requests=*/std::move(it->second),
/*remote_host=*/private_aggregation_host_);
// Remove the entry of key `pa_event_type` from
// `private_aggregation_event_map_` to avoid possibly sending the same
// requests more than once. As a result, receiving the same event type
// multiple times only triggers sending the event's requests once.
private_aggregation_event_map_.erase(it);
}
void FencedFrameReporter::MaybeBindPrivateAggregationHost() {
if (private_aggregation_host_.is_bound()) {
return;
}
DCHECK(private_aggregation_manager_);
DCHECK(winner_origin_.has_value() &&
winner_origin_.value().scheme() == url::kHttpsScheme);
DCHECK(main_frame_origin_.has_value() &&
main_frame_origin_.value().scheme() == url::kHttpsScheme);
bool bound = private_aggregation_manager_->BindNewReceiver(
winner_origin_.value(), main_frame_origin_.value(),
PrivateAggregationBudgetKey::Api::kProtectedAudience,
/*context_id=*/absl::nullopt,
private_aggregation_host_.BindNewPipeAndPassReceiver());
// FLEDGE's worklets should all be trustworthy, including `winner_origin_`, so
// the receiver `private_aggregation_host_` should be accepted.
DCHECK(bound);
}
base::flat_map<blink::FencedFrame::ReportingDestination,
FencedFrameReporter::ReportingUrlMap>
FencedFrameReporter::GetAdBeaconMapForTesting() {
base::flat_map<blink::FencedFrame::ReportingDestination, ReportingUrlMap> out;
for (const auto& reporting_metadata : reporting_metadata_) {
if (reporting_metadata.second.reporting_url_map) {
out.emplace(reporting_metadata.first,
*reporting_metadata.second.reporting_url_map);
}
}
return out;
}
std::set<std::string> FencedFrameReporter::GetReceivedPaEventsForTesting() {
return received_pa_events_;
}
std::map<std::string, FencedFrameReporter::PrivateAggregationRequests>
FencedFrameReporter::GetPrivateAggregationEventMapForTesting() {
std::map<std::string, FencedFrameReporter::PrivateAggregationRequests> out;
for (auto& [event_type, requests] : private_aggregation_event_map_) {
for (auction_worklet::mojom::PrivateAggregationRequestPtr& request :
requests) {
out[event_type].emplace_back(request.Clone());
}
}
return out;
}
void FencedFrameReporter::NotifyFencedFrameReportingBeaconFailed(
const absl::optional<AttributionReportingData>&
attribution_reporting_data) {
if (!attribution_reporting_data.has_value()) {
return;
}
AttributionDataHostManager* attribution_data_host_manager =
attribution_manager_ ? attribution_manager_->GetDataHostManager()
: nullptr;
if (!attribution_data_host_manager) {
return;
}
attribution_data_host_manager->NotifyFencedFrameReportingBeaconData(
attribution_reporting_data->beacon_id,
attribution_reporting_data->attribution_reporting_runtime_features,
/*reporting_url=*/GURL(), /*headers=*/nullptr,
/*is_final_response=*/true);
}
} // namespace content