Skip to content

Commit

Permalink
FLEDGE: Support promises for direct_from_seller_signals
Browse files Browse the repository at this point in the history
Bug: 1394750

Change-Id: If0d0c6744929bdfe47a06407bf6d6a66ff80e0e2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4189080
Commit-Queue: Maks Orlovich <morlovich@chromium.org>
Reviewed-by: Ken Buchanan <kenrb@chromium.org>
Reviewed-by: Caleb Raitto <caraitto@chromium.org>
Reviewed-by: Kentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1104487}
  • Loading branch information
Maks Orlovich authored and Chromium LUCI CQ committed Feb 13, 2023
1 parent 3c75433 commit 79903dc
Show file tree
Hide file tree
Showing 24 changed files with 1,182 additions and 470 deletions.
42 changes: 37 additions & 5 deletions content/browser/interest_group/auction_runner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,40 @@ void AuctionRunner::ResolvedBuyerTimeoutsPromise(
NotifyPromiseResolved(auction_id.get(), config);
}

void AuctionRunner::ResolvedDirectFromSellerSignalsPromise(
blink::mojom::AuctionAdConfigAuctionIdPtr auction_id,
const absl::optional<blink::DirectFromSellerSignals>&
direct_from_seller_signals) {
if (state_ == State::kFailed) {
return;
}

blink::AuctionConfig* config =
LookupAuction(*owned_auction_config_, auction_id);
if (!config) {
mojo::ReportBadMessage(
"Invalid auction ID in ResolvedDirectFromSellerSignalsPromise");
return;
}

if (!config->direct_from_seller_signals.is_promise()) {
mojo::ReportBadMessage(
"ResolvedDirectFromSellerSignalsPromise updating non-promise");
return;
}

if (!config->IsDirectFromSellerSignalsValid(direct_from_seller_signals)) {
mojo::ReportBadMessage(
"ResolvedDirectFromSellerSignalsPromise with invalid signals");
return;
}

config->direct_from_seller_signals =
blink::AuctionConfig::MaybePromiseDirectFromSellerSignals::FromValue(
direct_from_seller_signals);
NotifyPromiseResolved(auction_id.get(), config);
}

void AuctionRunner::Abort() {
// Don't abort if the auction already finished (either as success or failure;
// this includes the case of multiple promise arguments rejecting).
Expand Down Expand Up @@ -248,8 +282,7 @@ AuctionRunner::AuctionRunner(
owned_auction_config_(
std::make_unique<blink::AuctionConfig>(auction_config)),
callback_(std::move(callback)),
promise_fields_in_auction_config_(
owned_auction_config_->non_shared_params.NumPromises()),
promise_fields_in_auction_config_(owned_auction_config_->NumPromises()),
auction_(kanon_mode_,
owned_auction_config_.get(),
/*parent=*/nullptr,
Expand Down Expand Up @@ -339,10 +372,9 @@ void AuctionRunner::NotifyPromiseResolved(
blink::AuctionConfig* config) {
--promise_fields_in_auction_config_;
DCHECK_EQ(promise_fields_in_auction_config_,
owned_auction_config_->non_shared_params.NumPromises());
owned_auction_config_->NumPromises());

if (!auction_id->is_main_auction() &&
config->non_shared_params.NumPromises() == 0) {
if (!auction_id->is_main_auction() && config->NumPromises() == 0) {
auction_.NotifyComponentConfigPromisesResolved(
auction_id->get_component_auction());
}
Expand Down
4 changes: 4 additions & 0 deletions content/browser/interest_group/auction_runner.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,10 @@ class CONTENT_EXPORT AuctionRunner : public blink::mojom::AbortableAdAuction {
void ResolvedBuyerTimeoutsPromise(
blink::mojom::AuctionAdConfigAuctionIdPtr auction_id,
const blink::AuctionConfig::BuyerTimeouts& buyer_timeouts) override;
void ResolvedDirectFromSellerSignalsPromise(
blink::mojom::AuctionAdConfigAuctionIdPtr auction_id,
const absl::optional<blink::DirectFromSellerSignals>&
direct_from_seller_signals) override;
void Abort() override;

// Fails the auction, invoking `callback_` and prevents any future calls into
Expand Down
137 changes: 136 additions & 1 deletion content/browser/interest_group/auction_runner_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,10 @@ class AuctionRunnerTest : public RenderViewHostTestHarness,
blink::AuctionConfig auction_config;
auction_config.seller = url::Origin::Create(seller_decision_logic_url);
auction_config.decision_logic_url = seller_decision_logic_url;
if (pass_promise_for_direct_from_seller_signals_) {
auction_config.direct_from_seller_signals = blink::AuctionConfig::
MaybePromiseDirectFromSellerSignals::FromPromise();
}

auction_config.non_shared_params.interest_group_buyers = std::move(buyers);

Expand Down Expand Up @@ -1896,6 +1900,9 @@ class AuctionRunnerTest : public RenderViewHostTestHarness,
bool use_promise_for_auction_signals_ = false;
bool use_promise_for_per_buyer_signals_ = false;
bool use_promise_for_buyer_timeouts_ = false;

// Unlike others, this is only test with promises at this level.
bool pass_promise_for_direct_from_seller_signals_ = false;
absl::optional<uint16_t> seller_experiment_group_id_;
absl::optional<uint16_t> all_buyer_experiment_group_id_;
std::map<url::Origin, uint16_t> per_buyer_experiment_group_id_;
Expand Down Expand Up @@ -5598,6 +5605,90 @@ TEST_F(AuctionRunnerTest, PromiseSignalsBadAuctionId3) {
TakeBadMessage());
}

TEST_F(AuctionRunnerTest, PromiseSignalsBadAuctionId4) {
pass_promise_for_direct_from_seller_signals_ = true;

auction_worklet::AddJavascriptResponse(
&url_loader_factory_, kBidder1Url,
MakeBidScript(kSeller, "1", "https://ad1.com/", /*num_ad_components=*/0,
kBidder1, kBidder1Name));
auction_worklet::AddJavascriptResponse(
&url_loader_factory_, kBidder2Url,
MakeBidScript(kSeller, "2", "https://ad2.com/", /*num_ad_components=*/0,
kBidder2, kBidder2Name));
auction_worklet::AddJavascriptResponse(&url_loader_factory_, kSellerUrl,
MakeAuctionScript());

std::vector<StorageInterestGroup> bidders;
bidders.emplace_back(MakeInterestGroup(
kBidder1, kBidder1Name, kBidder1Url,
/*trusted_bidding_signals_url=*/absl::nullopt,
/*trusted_bidding_signals_keys=*/{}, GURL("https://ad1.com"),
/*ad_component_urls=*/absl::nullopt));
bidders.emplace_back(MakeInterestGroup(
kBidder2, kBidder2Name, kBidder2Url,
/*trusted_bidding_signals_url=*/absl::nullopt,
/*trusted_bidding_signals_keys=*/{}, GURL("https://ad2.com"),
/*ad_component_urls=*/absl::nullopt));
StartAuction(kSellerUrl, std::move(bidders));

// Can't complete yet.
task_environment()->RunUntilIdle();
EXPECT_FALSE(auction_run_loop_->AnyQuitCalled());

// Feed in directFromSellerSignals with wrong component ID.
abortable_ad_auction_->ResolvedDirectFromSellerSignalsPromise(
blink::mojom::AuctionAdConfigAuctionId::NewComponentAuction(0),
absl::nullopt);
auction_run_loop_->RunUntilIdle();
EXPECT_EQ("Invalid auction ID in ResolvedDirectFromSellerSignalsPromise",
TakeBadMessage());
}

TEST_F(AuctionRunnerTest, PromiseInvalidDirectFromSellerSignals) {
pass_promise_for_direct_from_seller_signals_ = true;

auction_worklet::AddJavascriptResponse(
&url_loader_factory_, kBidder1Url,
MakeBidScript(kSeller, "1", "https://ad1.com/", /*num_ad_components=*/0,
kBidder1, kBidder1Name));
auction_worklet::AddJavascriptResponse(
&url_loader_factory_, kBidder2Url,
MakeBidScript(kSeller, "2", "https://ad2.com/", /*num_ad_components=*/0,
kBidder2, kBidder2Name));
auction_worklet::AddJavascriptResponse(&url_loader_factory_, kSellerUrl,
MakeAuctionScript());

std::vector<StorageInterestGroup> bidders;
bidders.emplace_back(MakeInterestGroup(
kBidder1, kBidder1Name, kBidder1Url,
/*trusted_bidding_signals_url=*/absl::nullopt,
/*trusted_bidding_signals_keys=*/{}, GURL("https://ad1.com"),
/*ad_component_urls=*/absl::nullopt));
bidders.emplace_back(MakeInterestGroup(
kBidder2, kBidder2Name, kBidder2Url,
/*trusted_bidding_signals_url=*/absl::nullopt,
/*trusted_bidding_signals_keys=*/{}, GURL("https://ad2.com"),
/*ad_component_urls=*/absl::nullopt));
StartAuction(kSellerUrl, std::move(bidders));

// Can't complete yet.
task_environment()->RunUntilIdle();
EXPECT_FALSE(auction_run_loop_->AnyQuitCalled());

blink::DirectFromSellerSignals direct_from_seller_signals;
direct_from_seller_signals.prefix =
GURL("https://seller.test/?query_invalid");

// Feed in directFromSellerSignals with wrong component ID.
abortable_ad_auction_->ResolvedDirectFromSellerSignalsPromise(
blink::mojom::AuctionAdConfigAuctionId::NewMainAuction(0),
std::move(direct_from_seller_signals));
auction_run_loop_->RunUntilIdle();
EXPECT_EQ("ResolvedDirectFromSellerSignalsPromise with invalid signals",
TakeBadMessage());
}

// Trying to update auctionSignals which wasn't originally passed in as a
// promise.
TEST_F(AuctionRunnerTest, PromiseSignalsUpdateNonPromise) {
Expand Down Expand Up @@ -5816,7 +5907,7 @@ TEST_F(AuctionRunnerTest, PromiseSignalsUpdateNonPromise5) {

// Trying to update buyer timeouts twice.
TEST_F(AuctionRunnerTest, PromiseSignalsUpdateNonPromise6) {
// Have two kind of promises so we don't just finish after first update
// Have two kind of promises so we don't just finish after first update.
use_promise_for_per_buyer_signals_ = true;
use_promise_for_buyer_timeouts_ = true;

Expand Down Expand Up @@ -5859,6 +5950,50 @@ TEST_F(AuctionRunnerTest, PromiseSignalsUpdateNonPromise6) {
TakeBadMessage());
}

// Trying to update direct from seller signals twice.
TEST_F(AuctionRunnerTest, PromiseSignalsUpdateNonPromise7) {
// Have two kind of promises so we don't just finish after first update.
use_promise_for_per_buyer_signals_ = true;
pass_promise_for_direct_from_seller_signals_ = true;

auction_worklet::AddJavascriptResponse(
&url_loader_factory_, kBidder1Url,
MakeBidScript(kSeller, "1", "https://ad1.com/", /*num_ad_components=*/0,
kBidder1, kBidder1Name));
auction_worklet::AddJavascriptResponse(
&url_loader_factory_, kBidder2Url,
MakeBidScript(kSeller, "2", "https://ad2.com/", /*num_ad_components=*/0,
kBidder2, kBidder2Name));
auction_worklet::AddJavascriptResponse(&url_loader_factory_, kSellerUrl,
MakeAuctionScript());

std::vector<StorageInterestGroup> bidders;
bidders.emplace_back(MakeInterestGroup(
kBidder1, kBidder1Name, kBidder1Url,
/*trusted_bidding_signals_url=*/absl::nullopt,
/*trusted_bidding_signals_keys=*/{}, GURL("https://ad1.com"),
/*ad_component_urls=*/absl::nullopt));
bidders.emplace_back(MakeInterestGroup(
kBidder2, kBidder2Name, kBidder2Url,
/*trusted_bidding_signals_url=*/absl::nullopt,
/*trusted_bidding_signals_keys=*/{}, GURL("https://ad2.com"),
/*ad_component_urls=*/absl::nullopt));
StartAuction(kSellerUrl, std::move(bidders));

// Can't complete yet.
task_environment()->RunUntilIdle();
EXPECT_FALSE(auction_run_loop_->AnyQuitCalled());

// Feed in direct from seller signals twice.
abortable_ad_auction_->ResolvedDirectFromSellerSignalsPromise(
blink::mojom::AuctionAdConfigAuctionId::NewMainAuction(0), absl::nullopt);
abortable_ad_auction_->ResolvedDirectFromSellerSignalsPromise(
blink::mojom::AuctionAdConfigAuctionId::NewMainAuction(0), absl::nullopt);
task_environment()->RunUntilIdle();
EXPECT_EQ("ResolvedDirectFromSellerSignalsPromise updating non-promise",
TakeBadMessage());
}

// Test the case where the ProcessManager initially prevents creating worklets,
// due to being at its process limit.
TEST_F(AuctionRunnerTest, ProcessManagerBlocksWorkletCreation) {
Expand Down

0 comments on commit 79903dc

Please sign in to comment.