#include "content/browser/fenced_frame/fenced_frame_reporter.h"
#include <functional>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <type_traits>
#include <utility>
#include "base/memory/scoped_refptr.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/attribution_reporting/attribution_manager.h"
#include "content/browser/attribution_reporting/test/mock_attribution_data_host_manager.h"
#include "content/browser/attribution_reporting/test/mock_attribution_manager.h"
#include "content/browser/interest_group/test_interest_group_private_aggregation_manager.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/test/test_renderer_host.h"
#include "content/services/auction_worklet/public/mojom/private_aggregation_request.mojom.h"
#include "content/test/test_content_browser_client.h"
#include "net/base/isolation_info.h"
#include "net/base/network_isolation_key.h"
#include "net/http/http_request_headers.h"
#include "services/network/public/cpp/data_element.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/fenced_frame/fenced_frame_utils.h"
#include "third_party/blink/public/common/fenced_frame/redacted_fenced_frame_config.h"
#include "third_party/blink/public/mojom/aggregation_service/aggregatable_report.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace content {
namespace {
using ::testing::_;
using FinalizedPrivateAggregationRequests =
FencedFrameReporter::FinalizedPrivateAggregationRequests;
const auction_worklet::mojom::FinalizedPrivateAggregationRequestPtr
kPrivateAggregationRequest =
auction_worklet::mojom::FinalizedPrivateAggregationRequest::New(
blink::mojom::AggregatableReportHistogramContribution::New(
1,
2,
std::nullopt),
blink::mojom::DebugModeDetails::New(),
std::nullopt);
const auction_worklet::mojom::FinalizedPrivateAggregationRequestPtr
kPrivateAggregationRequest2 =
auction_worklet::mojom::FinalizedPrivateAggregationRequest::New(
blink::mojom::AggregatableReportHistogramContribution::New(
3,
4,
1),
blink::mojom::DebugModeDetails::New(),
std::nullopt);
template <typename... Ts>
auto ElementsAreRequests(Ts&... requests) {
static_assert(
std::conjunction<std::is_same<
std::remove_const_t<Ts>,
auction_worklet::mojom::FinalizedPrivateAggregationRequestPtr>...>::
value);
return testing::UnorderedElementsAre(testing::Eq(std::ref(requests))...);
}
class InterestGroupEnabledContentBrowserClient
: public TestContentBrowserClient {
public:
bool IsPrivacySandboxReportingDestinationAttested(
content::BrowserContext* browser_context,
const url::Origin& destination_origin,
content::PrivacySandboxInvokingAPI invoking_api) override {
return true;
}
};
class FencedFrameReporterTest : public RenderViewHostTestHarness {
public:
FencedFrameReporterTest() {
scoped_feature_list_.InitWithFeatures(
{blink::features::kFencedFramesAutomaticBeaconCredentials,
blink::features::kFencedFramesReportEventHeaderChanges},
{});
}
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory() {
return test_url_loader_factory_.GetSafeWeakWrapper();
}
AttributionManager* attribution_manager() {
return AttributionManager::FromBrowserContext(browser_context());
}
void SetUp() override {
old_content_browser_client_ =
SetBrowserClientForTesting(&test_content_browser_client_);
RenderViewHostTestHarness::SetUp();
NavigateAndCommit(main_frame_url_);
}
void TearDown() override {
SetBrowserClientForTesting(old_content_browser_client_);
RenderViewHostTestHarness::TearDown();
}
void ValidateRequest(const network::ResourceRequest& request,
const GURL& expected_url,
const std::optional<std::string>& event_data) {
EXPECT_EQ(request.url, expected_url);
EXPECT_EQ(request.mode, network::mojom::RequestMode::kCors);
EXPECT_EQ(request.credentials_mode, network::mojom::CredentialsMode::kOmit);
EXPECT_TRUE(request.trusted_params->isolation_info.network_isolation_key()
.IsTransient());
EXPECT_EQ(request.referrer, main_frame_origin_.GetURL());
EXPECT_NE(request.referrer, main_frame_url_);
EXPECT_EQ(
request.referrer_policy,
net::ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN);
if (!event_data.has_value()) {
EXPECT_EQ(request.method, net::HttpRequestHeaders::kGetMethod);
EXPECT_EQ(request.request_initiator, main_frame_origin_);
return;
}
EXPECT_EQ(request.request_initiator, report_url_declarer_origin_);
EXPECT_EQ(request.method, net::HttpRequestHeaders::kPostMethod);
EXPECT_EQ(request.headers.GetHeader(net::HttpRequestHeaders::kContentType),
"text/plain;charset=UTF-8");
ASSERT_TRUE(request.request_body);
ASSERT_EQ(request.request_body->elements()->size(), 1u);
ASSERT_EQ((*request.request_body->elements())[0].type(),
network::DataElement::Tag::kBytes);
EXPECT_EQ((*request.request_body->elements())[0]
.As<network::DataElementBytes>()
.AsStringPiece(),
*event_data);
}
protected:
RenderFrameHostImpl* main_rfh_impl() {
return static_cast<RenderFrameHostImpl*>(main_rfh());
}
const base::HistogramTester& histogram_tester() const {
return histogram_tester_;
}
void ShutDownAttributionManager() {
auto* partition = static_cast<StoragePartitionImpl*>(
browser_context()->GetDefaultStoragePartition());
partition->OverrideAttributionManagerForTesting(
nullptr);
}
network::TestURLLoaderFactory test_url_loader_factory_;
const GURL main_frame_url_{"https://main_frame.test/mypage.html"};
const GURL report_url_declarer_{"https://report_declarer.test/"};
const GURL report_destination_{"https://report_destination.test"};
const GURL report_destination2_{"https://report_destination2.test"};
const GURL report_destination3_{"https://report_destination3.test"};
const url::Origin main_frame_origin_ = url::Origin::Create(main_frame_url_);
const url::Origin report_url_declarer_origin_ =
url::Origin::Create(report_url_declarer_);
const url::Origin report_destination_origin_ =
url::Origin::Create(report_destination_);
const url::Origin report_destination2_origin_ =
url::Origin::Create(report_destination2_);
const url::Origin report_destination3_origin_ =
url::Origin::Create(report_destination3_);
TestInterestGroupPrivateAggregationManager private_aggregation_manager_{
main_frame_origin_};
InterestGroupEnabledContentBrowserClient test_content_browser_client_;
raw_ptr<ContentBrowserClient> old_content_browser_client_;
private:
base::test::ScopedFeatureList scoped_feature_list_;
base::HistogramTester histogram_tester_;
};
TEST_F(FencedFrameReporterTest, NoReportNoMap) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForSharedStorage(
shared_url_loader_factory(), browser_context(),
report_url_declarer_origin_,
{{"event_type", report_destination_}});
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_FALSE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(error_message,
"This frame did not register reporting metadata for destination "
"'Buyer'.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kWarning);
EXPECT_FALSE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kSeller, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(error_message,
"This frame did not register reporting metadata for destination "
"'Seller'.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kWarning);
EXPECT_FALSE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kDirectSeller, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(error_message,
"This frame did not register reporting metadata for destination "
"'ComponentSeller'.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kWarning);
EXPECT_FALSE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kComponentSeller,
main_rfh_impl(), error_message, console_message_level));
EXPECT_EQ(error_message,
"This frame did not register reporting metadata for destination "
"'ComponentSeller'.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kWarning);
EXPECT_FALSE(reporter->SendReport(
DestinationURLEvent(report_destination_),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(error_message,
"This frame did not register reporting metadata for destination "
"'Buyer'.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kWarning);
reporter = FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt);
EXPECT_FALSE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kSharedStorageSelectUrl,
main_rfh_impl(), error_message, console_message_level));
EXPECT_EQ(error_message,
"This frame did not register reporting metadata for destination "
"'SharedStorageSelectUrl'.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kWarning);
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
}
TEST_F(FencedFrameReporterTest, NoReportEmptyMap) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForSharedStorage(shared_url_loader_factory(),
browser_context(),
report_url_declarer_origin_,
{});
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_FALSE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kSharedStorageSelectUrl,
main_rfh_impl(), error_message, console_message_level));
EXPECT_EQ(error_message,
"This frame did not register reporting metadata for destination "
"'SharedStorageSelectUrl'.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kWarning);
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
}
TEST_F(FencedFrameReporterTest, NoReportEventTypeNotRegistered) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForSharedStorage(
shared_url_loader_factory(), browser_context(),
report_url_declarer_origin_,
{{"registered_event_type", report_destination_}});
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_FALSE(reporter->SendReport(
DestinationEnumEvent("unregistered_event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kSharedStorageSelectUrl,
main_rfh_impl(), error_message, console_message_level));
EXPECT_EQ(
error_message,
"This frame did not register reporting url for destination "
"'SharedStorageSelectUrl' and event_type 'unregistered_event_type'.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kWarning);
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
}
TEST_F(FencedFrameReporterTest, NoReportBadUrl) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForSharedStorage(
shared_url_loader_factory(), browser_context(),
report_url_declarer_origin_,
{{"no_url", GURL()},
{"data_url", GURL("data:,only http is allowed")}});
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_FALSE(reporter->SendReport(
DestinationEnumEvent("no_url", "event_data"),
blink::FencedFrame::ReportingDestination::kSharedStorageSelectUrl,
main_rfh_impl(), error_message, console_message_level));
EXPECT_EQ(error_message,
"This frame registered invalid reporting url for destination "
"'SharedStorageSelectUrl' and event_type 'no_url'.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kError);
EXPECT_FALSE(reporter->SendReport(
DestinationEnumEvent("data_url", "event_data"),
blink::FencedFrame::ReportingDestination::kSharedStorageSelectUrl,
main_rfh_impl(), error_message, console_message_level));
EXPECT_EQ(error_message,
"This frame registered invalid reporting url for destination "
"'SharedStorageSelectUrl' and event_type 'data_url'.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kError);
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
}
TEST_F(FencedFrameReporterTest, SendReports) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForSharedStorage(
shared_url_loader_factory(), browser_context(),
report_url_declarer_origin_,
{{"event_type", report_destination_},
{"event_type2", report_destination2_}});
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kSharedStorageSelectUrl,
main_rfh_impl(), error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination_, "event_data");
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data2"),
blink::FencedFrame::ReportingDestination::kSharedStorageSelectUrl,
main_rfh_impl(), error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 2);
ValidateRequest((*test_url_loader_factory_.pending_requests())[1].request,
report_destination_, "event_data2");
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type2", "event_data3"),
blink::FencedFrame::ReportingDestination::kSharedStorageSelectUrl,
main_rfh_impl(), error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 3);
ValidateRequest((*test_url_loader_factory_.pending_requests())[2].request,
report_destination2_, "event_data3");
}
TEST_F(FencedFrameReporterTest, SendFledgeReportsAfterMapsReceived) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt,
{{report_destination_origin_}});
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kSeller,
report_url_declarer_origin_,
{{"event_type", report_destination_}});
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kComponentSeller,
report_url_declarer_origin_,
{{"event_type", report_destination2_}});
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kBuyer,
report_url_declarer_origin_,
{{"event_type", report_destination3_}},
FencedFrameReporter::ReportingMacros());
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kSeller, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination_, "event_data");
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kComponentSeller,
main_rfh_impl(), error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 2);
ValidateRequest((*test_url_loader_factory_.pending_requests())[1].request,
report_destination2_, "event_data");
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 3);
ValidateRequest((*test_url_loader_factory_.pending_requests())[2].request,
report_destination3_, "event_data");
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kDirectSeller, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 4);
ValidateRequest((*test_url_loader_factory_.pending_requests())[3].request,
report_destination2_, "event_data");
EXPECT_TRUE(reporter->SendReport(
DestinationURLEvent(report_destination_),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 5);
ValidateRequest((*test_url_loader_factory_.pending_requests())[4].request,
report_destination_, std::nullopt);
}
TEST_F(FencedFrameReporterTest, SendReportsFledgeBeforeMapsReceived) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
true, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt,
{{report_destination_origin_}});
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kSeller, main_rfh_impl(),
error_message, console_message_level));
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kComponentSeller,
main_rfh_impl(), error_message, console_message_level));
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kDirectSeller, main_rfh_impl(),
error_message, console_message_level));
EXPECT_TRUE(reporter->SendReport(
DestinationURLEvent(report_destination_),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kSeller,
report_url_declarer_origin_,
{{"event_type", report_destination_}});
EXPECT_EQ(test_url_loader_factory_.NumPending(), 2);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination_, "event_data");
ValidateRequest((*test_url_loader_factory_.pending_requests())[1].request,
report_destination_, "event_data");
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kComponentSeller,
report_url_declarer_origin_,
{{"event_type", report_destination2_}});
EXPECT_EQ(test_url_loader_factory_.NumPending(), 3);
ValidateRequest((*test_url_loader_factory_.pending_requests())[2].request,
report_destination2_, "event_data");
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kBuyer,
report_url_declarer_origin_,
{{"event_type", report_destination3_}},
FencedFrameReporter::ReportingMacros());
EXPECT_EQ(test_url_loader_factory_.NumPending(), 5);
ValidateRequest((*test_url_loader_factory_.pending_requests())[3].request,
report_destination3_, "event_data");
ValidateRequest((*test_url_loader_factory_.pending_requests())[4].request,
report_destination_, std::nullopt);
}
TEST_F(FencedFrameReporterTest, SendFledgeReportsBeforeMapsReceivedWithErrors) {
auto attribution_data_host_manager =
std::make_unique<MockAttributionDataHostManager>();
auto* mock_attribution_data_host_manager =
attribution_data_host_manager.get();
auto mock_manager = std::make_unique<MockAttributionManager>();
mock_manager->SetDataHostManager(std::move(attribution_data_host_manager));
static_cast<StoragePartitionImpl*>(
browser_context()->GetDefaultStoragePartition())
->OverrideAttributionManagerForTesting(std::move(mock_manager));
EXPECT_CALL(*mock_attribution_data_host_manager,
NotifyFencedFrameReportingBeaconData(_, _, nullptr,
true))
.Times(3);
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt,
{{report_destination_origin_}});
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type2", "event_data"),
blink::FencedFrame::ReportingDestination::kSeller, main_rfh_impl(),
error_message, console_message_level));
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kSeller,
report_url_declarer_origin_,
{{"event_type", report_destination_}});
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kComponentSeller,
main_rfh_impl(), error_message, console_message_level));
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kComponentSeller,
report_url_declarer_origin_,
{{"event_type", GURL("data:,only http is allowed")}});
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_TRUE(reporter->SendReport(
DestinationURLEvent(report_destination_),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kBuyer,
report_url_declarer_origin_,
{},
FencedFrameReporter::ReportingMacros());
EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination_, std::nullopt);
}
TEST_F(FencedFrameReporterTest, CustomDestinationURLNoOrEmptyAllowlist) {
static const std::optional<std::vector<url::Origin>> test_cases[] = {
std::nullopt, {{}}};
for (const auto& test_case : test_cases) {
SCOPED_TRACE(test_case.has_value());
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt,
test_case);
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kBuyer,
report_url_declarer_origin_,
{{}},
FencedFrameReporter::ReportingMacros());
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_FALSE(reporter->SendReport(
DestinationURLEvent(report_destination_),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(error_message,
"This frame attempted to send a report to a custom destination "
"URL with macro substitution, but no origins are allowed by its "
"allowlist.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kError);
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
}
}
TEST_F(FencedFrameReporterTest, CustomDestinationURLNoAdMacroMap) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt,
{});
reporter->OnUrlMappingReady(blink::FencedFrame::ReportingDestination::kBuyer,
report_url_declarer_origin_,
{{}},
std::nullopt);
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_FALSE(reporter->SendReport(
DestinationURLEvent(report_destination_),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(error_message,
"This frame attempted to send a report to a custom destination URL "
"with macro substitution, which is not supported by the API that "
"created this frame's fenced frame config.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kError);
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
}
TEST_F(FencedFrameReporterTest, CustomDestinationURLEmptyAdMacroMap) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt,
{{report_destination_origin_}});
reporter->OnUrlMappingReady(blink::FencedFrame::ReportingDestination::kBuyer,
report_url_declarer_origin_,
{{}},
{{}});
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
GURL report_destination_template{
"https://report_destination.test?foo=${FOO}&bar=${BAR}&foo2=${FOO}"};
GURL report_destination_substituted{
"https://report_destination.test?foo=${FOO}&bar=${BAR}&foo2=${FOO}"};
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_TRUE(reporter->SendReport(
DestinationURLEvent(report_destination_template),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination_substituted, std::nullopt);
}
TEST_F(FencedFrameReporterTest, CustomDestinationURLCompleteMacroSubstitution) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt,
{{report_destination_origin_}});
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kBuyer,
report_url_declarer_origin_,
{{}},
FencedFrameReporter::ReportingMacros(
{{"${FOO}", "foosub"}, {"${BAR}", "barsub"}}));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
GURL report_destination_template{
"https://report_destination.test?foo=${FOO}&bar=${BAR}&foo2=${FOO}"};
GURL report_destination_substituted{
"https://report_destination.test?foo=foosub&bar=barsub&foo2=foosub"};
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_TRUE(reporter->SendReport(
DestinationURLEvent(report_destination_template),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination_substituted, std::nullopt);
}
TEST_F(FencedFrameReporterTest, CustomDestinationURLPartialMacroSubstitution) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt,
{{report_destination_origin_}});
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kBuyer,
report_url_declarer_origin_,
{{}},
FencedFrameReporter::ReportingMacros({{"${FOO}", "${FOO}${FOO}"}}));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
GURL report_destination_template{
"https://report_destination.test?foo=${FOO}&bar=${BAR}&foo2=${FOO}"};
GURL report_destination_substituted{
"https://"
"report_destination.test?foo=${FOO}${FOO}&bar=${BAR}&foo2=${FOO}${FOO}"};
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_TRUE(reporter->SendReport(
DestinationURLEvent(report_destination_template),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination_substituted, std::nullopt);
}
TEST_F(FencedFrameReporterTest, CustomDestinationURLNestedMacro) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt,
{{report_destination_origin_}});
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kBuyer,
report_url_declarer_origin_,
{{}},
FencedFrameReporter::ReportingMacros(
{{"${FOO}", "foo"}, {"${${FOO}}", "${FOO}"}}));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
GURL report_destination_template{
"https://report_destination.test?foo=${${FOO}}&foo2=${FOO}"};
GURL report_destination_substituted{
"https://"
"report_destination.test?foo=${FOO}&foo2=foo"};
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_TRUE(reporter->SendReport(
DestinationURLEvent(report_destination_template),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination_substituted, std::nullopt);
}
TEST_F(FencedFrameReporterTest, CustomDestinationHTTPURL) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt,
{{report_destination_origin_}});
reporter->OnUrlMappingReady(blink::FencedFrame::ReportingDestination::kBuyer,
report_url_declarer_origin_,
{{}},
FencedFrameReporter::ReportingMacros({}));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
GURL custom_report_destination{"http://report_destination.test"};
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_FALSE(reporter->SendReport(
DestinationURLEvent(custom_report_destination),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(
error_message,
"This frame attempted to send a report to an invalid custom "
"destination URL. No further reports to custom destination URLs will "
"be allowed for this fenced frame config.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kError);
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
}
TEST_F(FencedFrameReporterTest, CustomDestinationInvalidURL) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt,
{{report_destination_origin_}});
reporter->OnUrlMappingReady(blink::FencedFrame::ReportingDestination::kBuyer,
report_url_declarer_origin_,
{{}},
FencedFrameReporter::ReportingMacros({}));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
GURL custom_report_destination{"https://"};
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_FALSE(reporter->SendReport(
DestinationURLEvent(custom_report_destination),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(
error_message,
"This frame attempted to send a report to an invalid custom "
"destination URL. No further reports to custom destination URLs will "
"be allowed for this fenced frame config.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kError);
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
}
TEST_F(FencedFrameReporterTest, CustomDestinationInvalidURLAfterMacros) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt,
{{report_destination_origin_}});
reporter->OnUrlMappingReady(blink::FencedFrame::ReportingDestination::kBuyer,
report_url_declarer_origin_,
{{}},
FencedFrameReporter::ReportingMacros(
{{"https://report_destination.test", ""}}));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
GURL custom_report_destination{"https://report_destination.test"};
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_FALSE(reporter->SendReport(
DestinationURLEvent(custom_report_destination),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(error_message,
"This frame attempted to send a report to a custom destination URL "
"that is invalid after macro substitution. No further reports to "
"custom destination URLs will be allowed for this fenced frame "
"config.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kError);
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
}
TEST_F(FencedFrameReporterTest, CustomDestinationURLAllowlist) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt,
{{report_destination_origin_, report_destination2_origin_}});
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kBuyer,
report_url_declarer_origin_,
{{"event_type", report_destination_}},
FencedFrameReporter::ReportingMacros());
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_TRUE(reporter->SendReport(
DestinationURLEvent(report_destination_),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination_, std::nullopt);
EXPECT_TRUE(reporter->SendReport(
DestinationURLEvent(report_destination2_),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 2);
ValidateRequest((*test_url_loader_factory_.pending_requests())[1].request,
report_destination2_, std::nullopt);
EXPECT_FALSE(reporter->SendReport(
DestinationURLEvent(report_destination3_),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(
error_message,
"This frame attempted to send a report to a custom destination URL "
"with macro substitution to a disallowed origin. No further "
"reports to custom destination URLs will be allowed for this fenced "
"frame config.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kError);
EXPECT_EQ(test_url_loader_factory_.NumPending(), 2);
EXPECT_FALSE(reporter->SendReport(
DestinationURLEvent(report_destination_),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(
error_message,
"This frame attempted to send a report to a custom destination URL "
"with macro substitution, but this functionality is disabled because "
"a request was previously attempted to a disallowed origin.");
EXPECT_EQ(console_message_level, blink::mojom::ConsoleMessageLevel::kError);
EXPECT_EQ(test_url_loader_factory_.NumPending(), 2);
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 3);
ValidateRequest((*test_url_loader_factory_.pending_requests())[2].request,
report_destination_, "event_data");
NavigateAndCommit(report_destination2_);
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 4);
}
TEST_F(FencedFrameReporterTest, SendFledgeReportsNoMapReceived) {
auto attribution_data_host_manager =
std::make_unique<MockAttributionDataHostManager>();
auto* mock_attribution_data_host_manager =
attribution_data_host_manager.get();
auto mock_manager = std::make_unique<MockAttributionManager>();
mock_manager->SetDataHostManager(std::move(attribution_data_host_manager));
static_cast<StoragePartitionImpl*>(
browser_context()->GetDefaultStoragePartition())
->OverrideAttributionManagerForTesting(std::move(mock_manager));
EXPECT_CALL(*mock_attribution_data_host_manager,
NotifyFencedFrameReportingBeaconData(_, _, nullptr,
true));
{
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt);
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type2", "event_data"),
blink::FencedFrame::ReportingDestination::kSeller, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
}
}
TEST_F(FencedFrameReporterTest, FledgeEventsReceivedAfterRequestsReady) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt);
std::map<std::string, FinalizedPrivateAggregationRequests>
private_aggregation_event_map;
private_aggregation_event_map["event_type"].push_back(
kPrivateAggregationRequest.Clone());
private_aggregation_event_map["event_type2"].push_back(
kPrivateAggregationRequest2.Clone());
std::map<std::string, FinalizedPrivateAggregationRequests>
private_aggregation_event_map2;
private_aggregation_event_map2["event_type"].push_back(
kPrivateAggregationRequest2.Clone());
private_aggregation_event_map2["event_type3"].push_back(
kPrivateAggregationRequest2.Clone());
reporter->OnForEventPrivateAggregationRequestsReceived(
std::move(private_aggregation_event_map));
reporter->OnForEventPrivateAggregationRequestsReceived(
std::move(private_aggregation_event_map2));
EXPECT_THAT(
reporter->GetPrivateAggregationEventMapForTesting(),
testing::UnorderedElementsAre(
testing::Pair("event_type",
ElementsAreRequests(kPrivateAggregationRequest,
kPrivateAggregationRequest2)),
testing::Pair("event_type2",
ElementsAreRequests(kPrivateAggregationRequest2)),
testing::Pair("event_type3",
ElementsAreRequests(kPrivateAggregationRequest2))));
EXPECT_TRUE(
private_aggregation_manager_.TakePrivateAggregationRequests().empty());
reporter->SendPrivateAggregationRequestsForEvent("event_type");
EXPECT_THAT(private_aggregation_manager_.TakePrivateAggregationRequests(),
testing::UnorderedElementsAre(testing::Pair(
report_destination_origin_,
ElementsAreRequests(kPrivateAggregationRequest,
kPrivateAggregationRequest2))));
EXPECT_THAT(
reporter->GetPrivateAggregationEventMapForTesting(),
testing::UnorderedElementsAre(
testing::Pair("event_type2",
ElementsAreRequests(kPrivateAggregationRequest2)),
testing::Pair("event_type3",
ElementsAreRequests(kPrivateAggregationRequest2))));
reporter->SendPrivateAggregationRequestsForEvent("event_type2");
EXPECT_THAT(private_aggregation_manager_.TakePrivateAggregationRequests(),
testing::UnorderedElementsAre(testing::Pair(
report_destination_origin_,
ElementsAreRequests(kPrivateAggregationRequest2))));
EXPECT_THAT(
reporter->GetPrivateAggregationEventMapForTesting(),
testing::UnorderedElementsAre(testing::Pair(
"event_type3", ElementsAreRequests(kPrivateAggregationRequest2))));
reporter->SendPrivateAggregationRequestsForEvent("event_type");
EXPECT_THAT(private_aggregation_manager_.TakePrivateAggregationRequests(),
testing::UnorderedElementsAre());
reporter->SendPrivateAggregationRequestsForEvent("event_type4");
EXPECT_THAT(private_aggregation_manager_.TakePrivateAggregationRequests(),
testing::UnorderedElementsAre());
}
TEST_F(FencedFrameReporterTest, FledgeEventsReceivedBeforeRequestsReady) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt);
reporter->SendPrivateAggregationRequestsForEvent("event_type");
reporter->SendPrivateAggregationRequestsForEvent("event_type");
reporter->SendPrivateAggregationRequestsForEvent("event_type3");
EXPECT_THAT(reporter->GetReceivedPaEventsForTesting(),
testing::UnorderedElementsAre("event_type", "event_type3"));
EXPECT_TRUE(
private_aggregation_manager_.TakePrivateAggregationRequests().empty());
std::map<std::string, FinalizedPrivateAggregationRequests>
private_aggregation_event_map;
private_aggregation_event_map["event_type"].push_back(
kPrivateAggregationRequest.Clone());
private_aggregation_event_map["event_type2"].push_back(
kPrivateAggregationRequest2.Clone());
reporter->OnForEventPrivateAggregationRequestsReceived(
std::move(private_aggregation_event_map));
EXPECT_THAT(reporter->GetReceivedPaEventsForTesting(),
testing::UnorderedElementsAre("event_type", "event_type3"));
EXPECT_THAT(private_aggregation_manager_.TakePrivateAggregationRequests(),
testing::UnorderedElementsAre(testing::Pair(
report_destination_origin_,
ElementsAreRequests(kPrivateAggregationRequest))));
reporter->SendPrivateAggregationRequestsForEvent("event_type2");
EXPECT_THAT(private_aggregation_manager_.TakePrivateAggregationRequests(),
testing::UnorderedElementsAre(testing::Pair(
report_destination_origin_,
ElementsAreRequests(kPrivateAggregationRequest2))));
EXPECT_THAT(reporter->GetReceivedPaEventsForTesting(),
testing::UnorderedElementsAre("event_type", "event_type3",
"event_type2"));
reporter->SendPrivateAggregationRequestsForEvent("event_type");
EXPECT_THAT(private_aggregation_manager_.TakePrivateAggregationRequests(),
testing::UnorderedElementsAre());
std::map<std::string, FinalizedPrivateAggregationRequests>
private_aggregation_event_map2;
private_aggregation_event_map2["event_type"].push_back(
kPrivateAggregationRequest2.Clone());
private_aggregation_event_map2["event_type2"].push_back(
kPrivateAggregationRequest.Clone());
reporter->OnForEventPrivateAggregationRequestsReceived(
std::move(private_aggregation_event_map2));
EXPECT_THAT(private_aggregation_manager_.TakePrivateAggregationRequests(),
testing::UnorderedElementsAre(testing::Pair(
report_destination_origin_,
ElementsAreRequests(kPrivateAggregationRequest,
kPrivateAggregationRequest2))));
}
TEST_F(FencedFrameReporterTest, FledgeEventsReceivedUnexpectedly) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false,
nullptr, main_frame_origin_,
report_destination_origin_,
std::nullopt);
reporter->SendPrivateAggregationRequestsForEvent("event_type");
EXPECT_TRUE(reporter->GetReceivedPaEventsForTesting().empty());
EXPECT_TRUE(
private_aggregation_manager_.TakePrivateAggregationRequests().empty());
}
TEST_F(FencedFrameReporterTest, AttributionManagerShutDown_NoCrash) {
EXPECT_TRUE(attribution_manager());
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForSharedStorage(
shared_url_loader_factory(), browser_context(),
report_url_declarer_origin_,
{{"event_type", report_destination_}});
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kSharedStorageSelectUrl,
main_rfh_impl(), error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination_, "event_data");
ShutDownAttributionManager();
EXPECT_FALSE(attribution_manager());
EXPECT_TRUE(test_url_loader_factory_.SimulateResponseForPendingRequest(
report_destination_.spec(), ""));
}
TEST_F(FencedFrameReporterTest, SendReportsRecordHistogramsEnum) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForSharedStorage(
shared_url_loader_factory(), browser_context(),
report_url_declarer_origin_,
{{"event_type", report_destination_},
{"event_type2", report_destination2_}});
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kSharedStorageSelectUrl,
main_rfh_impl(), error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination_, "event_data");
test_url_loader_factory_.SimulateResponseForPendingRequest(
report_destination_.spec(), "");
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
histogram_tester().ExpectTotalCount(
blink::kFencedFrameBeaconReportingHttpResultUMA, 1);
histogram_tester().ExpectBucketCount(
blink::kFencedFrameBeaconReportingHttpResultUMA,
blink::FencedFrameBeaconReportingResult::kDestinationEnumSuccess, 1);
EXPECT_TRUE(reporter->SendReport(
DestinationEnumEvent("event_type", "event_data"),
blink::FencedFrame::ReportingDestination::kSharedStorageSelectUrl,
main_rfh_impl(), error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination_, "event_data");
test_url_loader_factory_.SimulateResponseForPendingRequest(
report_destination_.spec(), "", net::HTTP_NOT_FOUND);
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
histogram_tester().ExpectTotalCount(
blink::kFencedFrameBeaconReportingHttpResultUMA, 2);
histogram_tester().ExpectBucketCount(
blink::kFencedFrameBeaconReportingHttpResultUMA,
blink::FencedFrameBeaconReportingResult::kDestinationEnumSuccess, 1);
histogram_tester().ExpectBucketCount(
blink::kFencedFrameBeaconReportingHttpResultUMA,
blink::FencedFrameBeaconReportingResult::kDestinationEnumFailure, 1);
}
TEST_F(FencedFrameReporterTest, SendReportsRecordHistogramsURL) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt,
{{report_destination_origin_}});
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kSeller,
report_url_declarer_origin_,
{{"event_type", report_destination_}});
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kComponentSeller,
report_url_declarer_origin_,
{{"event_type", report_destination2_}});
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kBuyer,
report_url_declarer_origin_,
{{"event_type", report_destination3_}},
FencedFrameReporter::ReportingMacros());
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_TRUE(reporter->SendReport(
DestinationURLEvent(report_destination_),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination_, std::nullopt);
test_url_loader_factory_.SimulateResponseForPendingRequest(
report_destination_.spec(), "");
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
histogram_tester().ExpectTotalCount(
blink::kFencedFrameBeaconReportingHttpResultUMA, 1);
histogram_tester().ExpectBucketCount(
blink::kFencedFrameBeaconReportingHttpResultUMA,
blink::FencedFrameBeaconReportingResult::kDestinationUrlSuccess, 1);
EXPECT_TRUE(reporter->SendReport(
DestinationURLEvent(report_destination_),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination_, std::nullopt);
test_url_loader_factory_.SimulateResponseForPendingRequest(
report_destination_.spec(), "", net::HTTP_NOT_FOUND);
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
histogram_tester().ExpectTotalCount(
blink::kFencedFrameBeaconReportingHttpResultUMA, 2);
histogram_tester().ExpectBucketCount(
blink::kFencedFrameBeaconReportingHttpResultUMA,
blink::FencedFrameBeaconReportingResult::kDestinationUrlSuccess, 1);
histogram_tester().ExpectBucketCount(
blink::kFencedFrameBeaconReportingHttpResultUMA,
blink::FencedFrameBeaconReportingResult::kDestinationUrlFailure, 1);
}
TEST_F(FencedFrameReporterTest, SendReportsRecordHistogramsAutomaticBeacon) {
scoped_refptr<FencedFrameReporter> reporter =
FencedFrameReporter::CreateForFledge(
shared_url_loader_factory(), browser_context(),
false, &private_aggregation_manager_,
main_frame_origin_,
report_destination_origin_,
std::nullopt,
{{report_destination_origin_}});
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kSeller,
report_url_declarer_origin_,
{{blink::kFencedFrameTopNavigationStartBeaconType, report_destination_}});
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kComponentSeller,
report_url_declarer_origin_,
{{blink::kFencedFrameTopNavigationStartBeaconType,
report_destination2_}});
reporter->OnUrlMappingReady(
blink::FencedFrame::ReportingDestination::kBuyer,
report_url_declarer_origin_,
{{blink::kFencedFrameTopNavigationStartBeaconType, report_destination3_}},
FencedFrameReporter::ReportingMacros());
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
std::string error_message;
blink::mojom::ConsoleMessageLevel console_message_level =
blink::mojom::ConsoleMessageLevel::kError;
EXPECT_TRUE(reporter->SendReport(
AutomaticBeaconEvent(
blink::mojom::AutomaticBeaconType::kTopNavigationStart,
"event_data3"),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination3_, "event_data3");
test_url_loader_factory_.SimulateResponseForPendingRequest(
report_destination3_.spec(), "");
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
histogram_tester().ExpectTotalCount(
blink::kFencedFrameBeaconReportingHttpResultUMA, 1);
histogram_tester().ExpectBucketCount(
blink::kFencedFrameBeaconReportingHttpResultUMA,
blink::FencedFrameBeaconReportingResult::kAutomaticSuccess, 1);
EXPECT_TRUE(reporter->SendReport(
AutomaticBeaconEvent(
blink::mojom::AutomaticBeaconType::kTopNavigationStart,
"event_data3"),
blink::FencedFrame::ReportingDestination::kBuyer, main_rfh_impl(),
error_message, console_message_level));
EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
ValidateRequest((*test_url_loader_factory_.pending_requests())[0].request,
report_destination3_, "event_data3");
test_url_loader_factory_.SimulateResponseForPendingRequest(
report_destination3_.spec(), "", net::HTTP_NOT_FOUND);
EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
histogram_tester().ExpectTotalCount(
blink::kFencedFrameBeaconReportingHttpResultUMA, 2);
histogram_tester().ExpectBucketCount(
blink::kFencedFrameBeaconReportingHttpResultUMA,
blink::FencedFrameBeaconReportingResult::kAutomaticSuccess, 1);
histogram_tester().ExpectBucketCount(
blink::kFencedFrameBeaconReportingHttpResultUMA,
blink::FencedFrameBeaconReportingResult::kAutomaticFailure, 1);
}
}
}