Skip to content

Commit

Permalink
Gate privateAggregation JS object behind feature flag in FLEDGE
Browse files Browse the repository at this point in the history
Currently, the privateAggregation object is unconditionally exposed in
FLEDGE worklets. Instead, we only expose the object when the Private
Aggregation API feature is enabled.

Bug: 1346106
Change-Id: Ic9d1253c67636688898d2088e4a507abcb84f633
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3823921
Commit-Queue: Alex Turner <alexmt@chromium.org>
Reviewed-by: Nan Lin <linnan@chromium.org>
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
Reviewed-by: Russ Hamilton <behamilton@google.com>
Cr-Commit-Position: refs/heads/main@{#1035197}
  • Loading branch information
alexmturner authored and Chromium LUCI CQ committed Aug 15, 2022
1 parent de6f29c commit 63abee9
Show file tree
Hide file tree
Showing 12 changed files with 708 additions and 419 deletions.
2 changes: 0 additions & 2 deletions content/browser/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -1470,8 +1470,6 @@ source_set("browser") {
"private_aggregation/private_aggregation_budget_storage.h",
"private_aggregation/private_aggregation_budgeter.cc",
"private_aggregation/private_aggregation_budgeter.h",
"private_aggregation/private_aggregation_features.cc",
"private_aggregation/private_aggregation_features.h",
"private_aggregation/private_aggregation_host.cc",
"private_aggregation/private_aggregation_host.h",
"private_aggregation/private_aggregation_manager.cc",
Expand Down
219 changes: 143 additions & 76 deletions content/browser/interest_group/ad_auction_service_impl_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "content/browser/private_aggregation/private_aggregation_test_utils.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/common/private_aggregation_features.h"
#include "content/public/browser/browser_context.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
Expand Down Expand Up @@ -4971,82 +4972,6 @@ function scoreAd(
EXPECT_EQ(99, GetPriority(kOriginA, kInterestGroupName));
}

TEST_F(AdAuctionServiceImplTest, PrivateAggregationReportForwarded) {
constexpr char kBiddingScript[] = R"(
function generateBid(
interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals,
browserSignals) {
privateAggregation.sendHistogramReport({bucket: 1, value: 2});
return {'ad': 'example', 'bid': 1, 'render': 'https://example.com/render'};
}
)";

constexpr char kDecisionScript[] = R"(
function scoreAd(
adMetadata, bid, auctionConfig, trustedScoringSignals, browserSignals) {
return bid;
}
)";

class TestPrivateAggregationManagerImpl
: public PrivateAggregationManagerImpl {
public:
TestPrivateAggregationManagerImpl(
std::unique_ptr<PrivateAggregationBudgeter> budgeter,
std::unique_ptr<PrivateAggregationHost> host)
: PrivateAggregationManagerImpl(std::move(budgeter),
std::move(host),
/*storage_partition=*/nullptr) {}
};

base::MockRepeatingCallback<void(AggregatableReportRequest,
PrivateAggregationBudgetKey)>
mock_callback;

static_cast<StoragePartitionImpl*>(
browser_context()->GetDefaultStoragePartition())
->OverridePrivateAggregationManagerForTesting(
std::make_unique<TestPrivateAggregationManagerImpl>(
std::make_unique<MockPrivateAggregationBudgeter>(),
std::make_unique<PrivateAggregationHost>(
/*on_report_request_received=*/mock_callback.Get())));

network_responder_->RegisterScriptResponse(kBiddingUrlPath, kBiddingScript);
network_responder_->RegisterScriptResponse(kDecisionUrlPath, kDecisionScript);

blink::InterestGroup interest_group = CreateInterestGroup();
interest_group.bidding_url = kUrlA.Resolve(kBiddingUrlPath);
interest_group.priority = 2;
interest_group.ads.emplace();
blink::InterestGroup::Ad ad(
/*render_url=*/GURL("https://example.com/render"),
/*metadata=*/absl::nullopt);
interest_group.ads->emplace_back(std::move(ad));
JoinInterestGroupAndFlush(interest_group);

blink::AuctionConfig auction_config;
auction_config.seller = kOriginA;
auction_config.decision_logic_url = kUrlA.Resolve(kDecisionUrlPath);
auction_config.non_shared_params.interest_group_buyers = {kOriginA};

EXPECT_CALL(mock_callback, Run)
.WillRepeatedly(
testing::Invoke([this](AggregatableReportRequest request,
PrivateAggregationBudgetKey budget_key) {
ASSERT_EQ(request.payload_contents().contributions.size(), 1u);
EXPECT_EQ(request.payload_contents().contributions[0].bucket, 1);
EXPECT_EQ(request.payload_contents().contributions[0].value, 2);
EXPECT_EQ(request.shared_info().reporting_origin, kOriginA);
EXPECT_EQ(budget_key.api(),
PrivateAggregationBudgetKey::Api::kFledge);
EXPECT_EQ(budget_key.origin(), kOriginA);
}));

absl::optional<GURL> auction_result =
RunAdAuctionAndFlush(std::move(auction_config));
ASSERT_NE(auction_result, absl::nullopt);
}

class AdAuctionServiceImplNumAuctionLimitTest
: public AdAuctionServiceImplTest {
public:
Expand Down Expand Up @@ -5520,4 +5445,146 @@ function reportResult(auctionConfig, browserSignals) {
EXPECT_TRUE(network_responder_->ReportSent("/seller_debug_win_2"));
}

class AdAuctionServiceImplPrivateAggregationEnabledTest
: public AdAuctionServiceImplTest {
public:
AdAuctionServiceImplPrivateAggregationEnabledTest() {
feature_list_.InitAndEnableFeature(content::kPrivateAggregationApi);
}

protected:
base::test::ScopedFeatureList feature_list_;
};

TEST_F(AdAuctionServiceImplPrivateAggregationEnabledTest,
PrivateAggregationReportForwarded) {
constexpr char kBiddingScript[] = R"(
function generateBid(
interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals,
browserSignals) {
privateAggregation.sendHistogramReport({bucket: 1, value: 2});
return {'ad': 'example', 'bid': 1, 'render': 'https://example.com/render'};
}
)";

constexpr char kDecisionScript[] = R"(
function scoreAd(
adMetadata, bid, auctionConfig, trustedScoringSignals, browserSignals) {
return bid;
}
)";

class TestPrivateAggregationManagerImpl
: public PrivateAggregationManagerImpl {
public:
TestPrivateAggregationManagerImpl(
std::unique_ptr<PrivateAggregationBudgeter> budgeter,
std::unique_ptr<PrivateAggregationHost> host)
: PrivateAggregationManagerImpl(std::move(budgeter),
std::move(host),
/*storage_partition=*/nullptr) {}
};

base::MockRepeatingCallback<void(AggregatableReportRequest,
PrivateAggregationBudgetKey)>
mock_callback;

static_cast<StoragePartitionImpl*>(
browser_context()->GetDefaultStoragePartition())
->OverridePrivateAggregationManagerForTesting(
std::make_unique<TestPrivateAggregationManagerImpl>(
std::make_unique<MockPrivateAggregationBudgeter>(),
std::make_unique<PrivateAggregationHost>(
/*on_report_request_received=*/mock_callback.Get())));

network_responder_->RegisterScriptResponse(kBiddingUrlPath, kBiddingScript);
network_responder_->RegisterScriptResponse(kDecisionUrlPath, kDecisionScript);

blink::InterestGroup interest_group = CreateInterestGroup();
interest_group.bidding_url = kUrlA.Resolve(kBiddingUrlPath);
interest_group.priority = 2;
interest_group.ads.emplace();
blink::InterestGroup::Ad ad(
/*render_url=*/GURL("https://example.com/render"),
/*metadata=*/absl::nullopt);
interest_group.ads->emplace_back(std::move(ad));
JoinInterestGroupAndFlush(interest_group);

blink::AuctionConfig auction_config;
auction_config.seller = kOriginA;
auction_config.decision_logic_url = kUrlA.Resolve(kDecisionUrlPath);
auction_config.non_shared_params.interest_group_buyers = {kOriginA};

EXPECT_CALL(mock_callback, Run)
.WillRepeatedly(
testing::Invoke([this](AggregatableReportRequest request,
PrivateAggregationBudgetKey budget_key) {
ASSERT_EQ(request.payload_contents().contributions.size(), 1u);
EXPECT_EQ(request.payload_contents().contributions[0].bucket, 1);
EXPECT_EQ(request.payload_contents().contributions[0].value, 2);
EXPECT_EQ(request.shared_info().reporting_origin, kOriginA);
EXPECT_EQ(budget_key.api(),
PrivateAggregationBudgetKey::Api::kFledge);
EXPECT_EQ(budget_key.origin(), kOriginA);
}));

absl::optional<GURL> auction_result =
RunAdAuctionAndFlush(std::move(auction_config));
EXPECT_NE(auction_result, absl::nullopt);
}

class AdAuctionServiceImplPrivateAggregationDisabledTest
: public AdAuctionServiceImplTest {
public:
AdAuctionServiceImplPrivateAggregationDisabledTest() {
feature_list_.InitAndDisableFeature(content::kPrivateAggregationApi);
}

protected:
base::test::ScopedFeatureList feature_list_;
};

TEST_F(AdAuctionServiceImplPrivateAggregationDisabledTest,
PrivateAggregationNotExposed) {
constexpr char kBiddingScript[] = R"(
function generateBid(
interestGroup, auctionSignals, perBuyerSignals, trustedBiddingSignals,
browserSignals) {
privateAggregation.sendHistogramReport({bucket: 1, value: 2});
return {'ad': 'example', 'bid': 1, 'render': 'https://example.com/render'};
}
)";

constexpr char kDecisionScript[] = R"(
function scoreAd(
adMetadata, bid, auctionConfig, trustedScoringSignals, browserSignals) {
return bid;
}
)";

network_responder_->RegisterScriptResponse(kBiddingUrlPath, kBiddingScript);
network_responder_->RegisterScriptResponse(kDecisionUrlPath, kDecisionScript);

blink::InterestGroup interest_group = CreateInterestGroup();
interest_group.bidding_url = kUrlA.Resolve(kBiddingUrlPath);
interest_group.priority = 2;
interest_group.ads.emplace();
blink::InterestGroup::Ad ad(
/*render_url=*/GURL("https://example.com/render"),
/*metadata=*/absl::nullopt);
interest_group.ads->emplace_back(std::move(ad));
JoinInterestGroupAndFlush(interest_group);

blink::AuctionConfig auction_config;
auction_config.seller = kOriginA;
auction_config.decision_logic_url = kUrlA.Resolve(kDecisionUrlPath);
auction_config.non_shared_params.interest_group_buyers = {kOriginA};

absl::optional<GURL> auction_result =
RunAdAuctionAndFlush(std::move(auction_config));

// privateAggregation should cause a ReferenceError.
EXPECT_EQ(auction_result, absl::nullopt);
}

} // namespace content
47 changes: 46 additions & 1 deletion content/browser/interest_group/auction_runner_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "content/browser/interest_group/interest_group_manager_impl.h"
#include "content/browser/interest_group/interest_group_storage.h"
#include "content/common/aggregatable_report.mojom-shared.h"
#include "content/common/private_aggregation_features.h"
#include "content/public/browser/site_instance.h"
#include "content/public/test/test_renderer_host.h"
#include "content/services/auction_worklet/auction_v8_helper.h"
Expand Down Expand Up @@ -1495,11 +1496,13 @@ class AuctionRunnerTest : public testing::Test,
std::vector<auction_worklet::mojom::PreviousWinPtr> bidder2_prev_wins;
};

AuctionRunnerTest()
explicit AuctionRunnerTest(bool should_enable_private_aggregation = true)
: task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
mojo::SetDefaultProcessErrorHandler(base::BindRepeating(
&AuctionRunnerTest::OnBadMessage, base::Unretained(this)));
DebuggableAuctionWorkletTracker::GetInstance()->AddObserver(this);
scoped_feature_list_.InitWithFeatureState(
content::kPrivateAggregationApi, should_enable_private_aggregation);
}

~AuctionRunnerTest() override {
Expand Down Expand Up @@ -2060,6 +2063,8 @@ class AuctionRunnerTest : public testing::Test,
std::set<url::Origin> disallowed_sellers_;
std::set<url::Origin> disallowed_buyers_;

base::test::ScopedFeatureList scoped_feature_list_;

base::test::TaskEnvironment task_environment_;

// RunLoop that's quit on auction completion.
Expand Down Expand Up @@ -9100,5 +9105,45 @@ TEST_F(AuctionRunnerBiddingAndScoringDebugReportingAPIEnabledTest,
GURL("https://seller0.test/win/11")));
}

// Enable and test forDebuggingOnly.reportAdAuctionLoss() and
// forDebuggingOnly.reportAdAuctionWin() APIs.
class AuctionRunnerPrivateAggregationAPIDisabledTest
: public AuctionRunnerTest {
public:
AuctionRunnerPrivateAggregationAPIDisabledTest()
: AuctionRunnerTest(/*should_enable_private_aggregation=*/false) {}
};

TEST_F(AuctionRunnerPrivateAggregationAPIDisabledTest, ReportsNotSent) {
auction_worklet::AddJavascriptResponse(
&url_loader_factory_, kBidder1Url,
MakeBidScript(kSeller, "1", "https://ad1.com/", /*num_ad_components=*/2,
kBidder1, kBidder1Name,
/*has_signals=*/true, "k1", "a",
/*report_post_auction_signals=*/true));
auction_worklet::AddJavascriptResponse(
&url_loader_factory_, kBidder2Url,
MakeBidScript(kSeller, "2", "https://ad2.com/", /*num_ad_components=*/2,
kBidder2, kBidder2Name,
/*has_signals=*/true, "l2", "b",
/*report_post_auction_signals=*/true));
auction_worklet::AddJavascriptResponse(
&url_loader_factory_, kSellerUrl,
MakeAuctionScript(/*report_post_auction_signals=*/true));
auction_worklet::AddBidderJsonResponse(
&url_loader_factory_,
GURL(kBidder1TrustedSignalsUrl.spec() +
"?hostname=publisher1.com&keys=k1,k2"),
kBidder1SignalsJson);
auction_worklet::AddBidderJsonResponse(
&url_loader_factory_,
GURL(kBidder2TrustedSignalsUrl.spec() +
"?hostname=publisher1.com&keys=l1,l2"),
kBidder2SignalsJson);

const Result& res = RunStandardAuction();
EXPECT_TRUE(res.private_aggregation_requests.empty());
}

} // namespace
} // namespace content
2 changes: 1 addition & 1 deletion content/browser/storage_partition_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@
#include "content/browser/notifications/platform_notification_context_impl.h"
#include "content/browser/payments/payment_app_context_impl.h"
#include "content/browser/preloading/prerender/prerender_host_registry.h"
#include "content/browser/private_aggregation/private_aggregation_features.h"
#include "content/browser/private_aggregation/private_aggregation_manager_impl.h"
#include "content/browser/push_messaging/push_messaging_context.h"
#include "content/browser/quota/quota_context.h"
Expand All @@ -93,6 +92,7 @@
#include "content/browser/ssl_private_key_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/worker_host/shared_worker_service_impl.h"
#include "content/common/private_aggregation_features.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
Expand Down
7 changes: 6 additions & 1 deletion content/common/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,8 @@ source_set("common") {
"origin_util.cc",
"partition_alloc_support.cc",
"partition_alloc_support.h",
"private_aggregation_features.cc",
"private_aggregation_features.h",
"process_type.cc",
"process_visibility_tracker.cc",
"process_visibility_tracker.h",
Expand Down Expand Up @@ -431,7 +433,10 @@ if (is_linux || is_chromeos) {

# See comment at the top of //content/BUILD.gn for how this works.
group("for_content_tests") {
visibility = [ "//content/test/*" ]
visibility = [
"//content/services/auction_worklet:tests",
"//content/test/*",
]
if (!is_component_build) {
public_deps = [ ":common" ]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/private_aggregation/private_aggregation_features.h"
#include "content/common/private_aggregation_features.h"

#include "base/feature_list.h"

namespace content {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_PRIVATE_AGGREGATION_PRIVATE_AGGREGATION_FEATURES_H_
#define CONTENT_BROWSER_PRIVATE_AGGREGATION_PRIVATE_AGGREGATION_FEATURES_H_
#ifndef CONTENT_COMMON_PRIVATE_AGGREGATION_FEATURES_H_
#define CONTENT_COMMON_PRIVATE_AGGREGATION_FEATURES_H_

#include "base/feature_list.h"
#include "content/common/content_export.h"

namespace content {

// Enables the Private Aggregation API. Note that this API also requires the
// `kPrivacySandboxAggregationService` to be enabled to successfully send
// reports.
extern const base::Feature kPrivateAggregationApi;
CONTENT_EXPORT extern const base::Feature kPrivateAggregationApi;

} // namespace content

#endif // CONTENT_BROWSER_PRIVATE_AGGREGATION_PRIVATE_AGGREGATION_FEATURES_H_
#endif // CONTENT_COMMON_PRIVATE_AGGREGATION_FEATURES_H_

0 comments on commit 63abee9

Please sign in to comment.