#include "content/services/auction_worklet/bidder_worklet.h"
#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "base/check.h"
#include "base/containers/contains.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/bind_post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_event.h"
#include "base/types/optional_util.h"
#include "content/public/common/content_features.h"
#include "content/services/auction_worklet/auction_v8_helper.h"
#include "content/services/auction_worklet/auction_v8_logger.h"
#include "content/services/auction_worklet/auction_worklet_util.h"
#include "content/services/auction_worklet/bidder_lazy_filler.h"
#include "content/services/auction_worklet/deprecated_url_lazy_filler.h"
#include "content/services/auction_worklet/direct_from_seller_signals_requester.h"
#include "content/services/auction_worklet/for_debugging_only_bindings.h"
#include "content/services/auction_worklet/private_aggregation_bindings.h"
#include "content/services/auction_worklet/public/cpp/auction_network_events_delegate.h"
#include "content/services/auction_worklet/public/mojom/auction_worklet_service.mojom.h"
#include "content/services/auction_worklet/public/mojom/bidder_worklet.mojom-shared.h"
#include "content/services/auction_worklet/public/mojom/bidder_worklet.mojom.h"
#include "content/services/auction_worklet/public/mojom/private_aggregation_request.mojom.h"
#include "content/services/auction_worklet/public/mojom/real_time_reporting.mojom.h"
#include "content/services/auction_worklet/real_time_reporting_bindings.h"
#include "content/services/auction_worklet/register_ad_beacon_bindings.h"
#include "content/services/auction_worklet/register_ad_macro_bindings.h"
#include "content/services/auction_worklet/report_bindings.h"
#include "content/services/auction_worklet/set_bid_bindings.h"
#include "content/services/auction_worklet/set_priority_bindings.h"
#include "content/services/auction_worklet/set_priority_signals_override_bindings.h"
#include "content/services/auction_worklet/shared_storage_bindings.h"
#include "content/services/auction_worklet/trusted_signals.h"
#include "content/services/auction_worklet/trusted_signals_request_manager.h"
#include "content/services/auction_worklet/worklet_loader.h"
#include "content/services/auction_worklet/worklet_util.h"
#include "context_recycler.h"
#include "gin/converter.h"
#include "gin/dictionary.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/struct_ptr.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/interest_group/ad_auction_constants.h"
#include "third_party/blink/public/common/interest_group/ad_auction_currencies.h"
#include "third_party/blink/public/common/interest_group/ad_display_size.h"
#include "third_party/blink/public/common/interest_group/ad_display_size_utils.h"
#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
#include "v8-statistics.h"
#include "v8/include/v8-container.h"
#include "v8/include/v8-context.h"
#include "v8/include/v8-exception.h"
#include "v8/include/v8-forward.h"
#include "v8/include/v8-object.h"
#include "v8/include/v8-primitive.h"
#include "v8/include/v8-template.h"
#include "v8/include/v8-wasm.h"
namespace auction_worklet {
namespace {
class DeepFreezeAllowAll : public v8::Context::DeepFreezeDelegate { … };
bool AppendJsonValueOrNull(AuctionV8Helper* const v8_helper,
v8::Local<v8::Context> context,
const std::string* maybe_json,
v8::LocalVector<v8::Value>* args) { … }
v8::Local<v8::Value> GetDirectFromSellerSignals(
const DirectFromSellerSignalsRequester::Result& subresource_bundle_result,
const std::optional<std::string>& header_result,
AuctionV8Helper& v8_helper,
v8::Local<v8::Context> context,
std::vector<std::string>& errors) { … }
bool HasKAnonFailureComponent(
const auction_worklet::mojom::PrivateAggregationRequestPtr& request) { … }
std::optional<base::TimeDelta> NullOptIfZero(base::TimeDelta delta) { … }
void TrimExtraAdComponents(mojom::BidderWorkletBid& bid,
std::optional<size_t> target_num_ad_components) { … }
void TrimAndCollectBid(mojom::BidderWorkletBidPtr bid,
std::optional<size_t> target_num_ad_components,
std::vector<mojom::BidderWorkletBidPtr>& out) { … }
void HandleComponentsKAnon(
const mojom::BidderWorkletNonSharedParams* bidder_worklet_non_shared_params,
mojom::BidderWorkletBidPtr bid,
std::optional<size_t> target_num_ad_components,
size_t num_mandatory_ad_components,
std::vector<mojom::BidderWorkletBidPtr>& out) { … }
std::vector<mojom::BidderWorkletBidPtr> ClassifyBidsAndApplyComponentAdLimits(
mojom::KAnonymityBidMode kanon_mode,
const mojom::BidderWorkletNonSharedParams* bidder_worklet_non_shared_params,
const GURL& script_source_url,
std::vector<SetBidBindings::BidAndWorkletOnlyMetadata> bid_info) { … }
size_t GetNumberOfGroupByOriginContextsToKeep() { … }
BidderWorklet::SignalsOriginRelation ClassifyTrustedSignals(
const GURL& script_source_url,
const std::optional<url::Origin>& trusted_bidding_signals_origin) { … }
bool SetDataVersion(
BidderWorklet::SignalsOriginRelation trusted_signals_relation,
std::optional<uint32_t> bidding_signals_data_version,
gin::Dictionary& browser_signals_dict) { … }
}
BidderWorklet::BidderWorklet(
std::vector<scoped_refptr<AuctionV8Helper>> v8_helpers,
std::vector<mojo::PendingRemote<mojom::AuctionSharedStorageHost>>
shared_storage_hosts,
bool pause_for_debugger_on_start,
mojo::PendingRemote<network::mojom::URLLoaderFactory>
pending_url_loader_factory,
mojo::PendingRemote<auction_worklet::mojom::AuctionNetworkEventsHandler>
auction_network_events_handler,
const GURL& script_source_url,
const std::optional<GURL>& wasm_helper_url,
const std::optional<GURL>& trusted_bidding_signals_url,
const std::string& trusted_bidding_signals_slot_size_param,
const url::Origin& top_window_origin,
mojom::AuctionWorkletPermissionsPolicyStatePtr permissions_policy_state,
std::optional<uint16_t> experiment_group_id,
mojom::TrustedSignalsPublicKeyPtr public_key)
: … { … }
BidderWorklet::~BidderWorklet() { … }
std::vector<int> BidderWorklet::context_group_ids_for_testing() const { … }
size_t BidderWorklet::GetNextThreadIndex() { … }
bool BidderWorklet::IsKAnon(
const mojom::BidderWorkletNonSharedParams* bidder_worklet_non_shared_params,
const std::string& key) { … }
bool BidderWorklet::IsMainAdKAnon(
const mojom::BidderWorkletNonSharedParams* bidder_worklet_non_shared_params,
const GURL& script_source_url,
const SetBidBindings::BidAndWorkletOnlyMetadata& bid_and_metadata) { … }
bool BidderWorklet::IsComponentAdKAnon(
const mojom::BidderWorkletNonSharedParams* bidder_worklet_non_shared_params,
const blink::AdDescriptor& ad_component_descriptor) { … }
bool BidderWorklet::SupportMultiBid() { … }
void BidderWorklet::BeginGenerateBid(
mojom::BidderWorkletNonSharedParamsPtr bidder_worklet_non_shared_params,
mojom::KAnonymityBidMode kanon_mode,
const url::Origin& interest_group_join_origin,
const std::optional<GURL>& direct_from_seller_per_buyer_signals,
const std::optional<GURL>& direct_from_seller_auction_signals,
const url::Origin& browser_signal_seller_origin,
const std::optional<url::Origin>& browser_signal_top_level_seller_origin,
const base::TimeDelta browser_signal_recency,
mojom::BiddingBrowserSignalsPtr bidding_browser_signals,
base::Time auction_start_time,
const std::optional<blink::AdSize>& requested_ad_size,
uint16_t multi_bid_limit,
uint64_t trace_id,
mojo::PendingAssociatedRemote<mojom::GenerateBidClient> generate_bid_client,
mojo::PendingAssociatedReceiver<mojom::GenerateBidFinalizer>
bid_finalizer) { … }
void BidderWorklet::SendPendingSignalsRequests() { … }
void BidderWorklet::ReportWin(
bool is_for_additional_bid,
const std::optional<std::string>& interest_group_name_reporting_id,
const std::optional<std::string>& buyer_reporting_id,
const std::optional<std::string>& buyer_and_seller_reporting_id,
const std::optional<std::string>& selected_buyer_and_seller_reporting_id,
const std::optional<std::string>& auction_signals_json,
const std::optional<std::string>& per_buyer_signals_json,
const std::optional<GURL>& direct_from_seller_per_buyer_signals,
const std::optional<std::string>&
direct_from_seller_per_buyer_signals_header_ad_slot,
const std::optional<GURL>& direct_from_seller_auction_signals,
const std::optional<std::string>&
direct_from_seller_auction_signals_header_ad_slot,
const std::string& seller_signals_json,
mojom::KAnonymityBidMode kanon_mode,
bool bid_is_kanon,
const GURL& browser_signal_render_url,
double browser_signal_bid,
const std::optional<blink::AdCurrency>& browser_signal_bid_currency,
double browser_signal_highest_scoring_other_bid,
const std::optional<blink::AdCurrency>&
browser_signal_highest_scoring_other_bid_currency,
bool browser_signal_made_highest_scoring_other_bid,
std::optional<double> browser_signal_ad_cost,
std::optional<uint16_t> browser_signal_modeling_signals,
uint8_t browser_signal_join_count,
uint8_t browser_signal_recency,
const url::Origin& browser_signal_seller_origin,
const std::optional<url::Origin>& browser_signal_top_level_seller_origin,
const std::optional<base::TimeDelta> browser_signal_reporting_timeout,
std::optional<uint32_t> bidding_signals_data_version,
uint64_t trace_id,
ReportWinCallback report_win_callback) { … }
void BidderWorklet::ConnectDevToolsAgent(
mojo::PendingAssociatedReceiver<blink::mojom::DevToolsAgent> agent,
uint32_t thread_index) { … }
void BidderWorklet::FinishGenerateBid(
const std::optional<std::string>& auction_signals_json,
const std::optional<std::string>& per_buyer_signals_json,
const std::optional<base::TimeDelta> per_buyer_timeout,
const std::optional<blink::AdCurrency>& expected_buyer_currency,
const std::optional<GURL>& direct_from_seller_per_buyer_signals,
const std::optional<std::string>&
direct_from_seller_per_buyer_signals_header_ad_slot,
const std::optional<GURL>& direct_from_seller_auction_signals,
const std::optional<std::string>&
direct_from_seller_auction_signals_header_ad_slot) { … }
BidderWorklet::GenerateBidTask::GenerateBidTask() = default;
BidderWorklet::GenerateBidTask::~GenerateBidTask() = default;
BidderWorklet::ReportWinTask::ReportWinTask() = default;
BidderWorklet::ReportWinTask::~ReportWinTask() = default;
BidderWorklet::V8State::V8State(
scoped_refptr<AuctionV8Helper> v8_helper,
scoped_refptr<AuctionV8Helper::DebugId> debug_id,
mojo::PendingRemote<mojom::AuctionSharedStorageHost>
shared_storage_host_remote,
const GURL& script_source_url,
const url::Origin& top_window_origin,
mojom::AuctionWorkletPermissionsPolicyStatePtr permissions_policy_state,
const std::optional<GURL>& wasm_helper_url,
const std::optional<GURL>& trusted_bidding_signals_url,
base::WeakPtr<BidderWorklet> parent)
: … { … }
void BidderWorklet::V8State::SetWorkletScript(
WorkletLoader::Result worklet_script) { … }
void BidderWorklet::V8State::SetWasmHelper(
WorkletWasmLoader::Result wasm_helper) { … }
BidderWorklet::V8State::SingleGenerateBidResult::SingleGenerateBidResult() =
default;
BidderWorklet::V8State::SingleGenerateBidResult::SingleGenerateBidResult(
std::unique_ptr<ContextRecycler> context_recycler_for_rerun,
std::vector<SetBidBindings::BidAndWorkletOnlyMetadata> bids,
std::optional<uint32_t> bidding_signals_data_version,
std::optional<GURL> debug_loss_report_url,
std::optional<GURL> debug_win_report_url,
std::optional<double> set_priority,
base::flat_map<std::string, mojom::PrioritySignalsDoublePtr>
update_priority_signals_overrides,
PrivateAggregationRequests pa_requests,
RealTimeReportingContributions real_time_contributions,
mojom::RejectReason reject_reason,
std::vector<std::string> error_msgs)
: … { … }
BidderWorklet::V8State::SingleGenerateBidResult::SingleGenerateBidResult(
SingleGenerateBidResult&&) = default;
BidderWorklet::V8State::SingleGenerateBidResult::~SingleGenerateBidResult() =
default;
BidderWorklet::V8State::SingleGenerateBidResult&
BidderWorklet::V8State::SingleGenerateBidResult::operator=(
SingleGenerateBidResult&&) = default;
void BidderWorklet::V8State::ReportWin(
bool is_for_additional_bid,
const std::optional<std::string>& interest_group_name_reporting_id,
const std::optional<std::string>& buyer_reporting_id,
const std::optional<std::string>& buyer_and_seller_reporting_id,
const std::optional<std::string>& selected_buyer_and_seller_reporting_id,
const std::optional<std::string>& auction_signals_json,
const std::optional<std::string>& per_buyer_signals_json,
DirectFromSellerSignalsRequester::Result
direct_from_seller_result_per_buyer_signals,
const std::optional<std::string>&
direct_from_seller_per_buyer_signals_header_ad_slot,
DirectFromSellerSignalsRequester::Result
direct_from_seller_result_auction_signals,
const std::optional<std::string>&
direct_from_seller_auction_signals_header_ad_slot,
const std::string& seller_signals_json,
mojom::KAnonymityBidMode kanon_mode,
bool bid_is_kanon,
const GURL& browser_signal_render_url,
double browser_signal_bid,
const std::optional<blink::AdCurrency>& browser_signal_bid_currency,
double browser_signal_highest_scoring_other_bid,
const std::optional<blink::AdCurrency>&
browser_signal_highest_scoring_other_bid_currency,
bool browser_signal_made_highest_scoring_other_bid,
const std::optional<double>& browser_signal_ad_cost,
const std::optional<uint16_t>& browser_signal_modeling_signals,
uint8_t browser_signal_join_count,
uint8_t browser_signal_recency,
const url::Origin& browser_signal_seller_origin,
const std::optional<url::Origin>& browser_signal_top_level_seller_origin,
const std::optional<base::TimeDelta> browser_signal_reporting_timeout,
const std::optional<uint32_t>& bidding_signals_data_version,
uint64_t trace_id,
ReportWinCallbackInternal callback) { … }
void BidderWorklet::V8State::GenerateBid(
mojom::BidderWorkletNonSharedParamsPtr bidder_worklet_non_shared_params,
mojom::KAnonymityBidMode kanon_mode,
const url::Origin& interest_group_join_origin,
const std::optional<std::string>& auction_signals_json,
const std::optional<std::string>& per_buyer_signals_json,
DirectFromSellerSignalsRequester::Result
direct_from_seller_result_per_buyer_signals,
const std::optional<std::string>&
direct_from_seller_per_buyer_signals_header_ad_slot,
DirectFromSellerSignalsRequester::Result
direct_from_seller_result_auction_signals,
const std::optional<std::string>&
direct_from_seller_auction_signals_header_ad_slot,
const std::optional<base::TimeDelta> per_buyer_timeout,
const std::optional<blink::AdCurrency>& expected_buyer_currency,
const url::Origin& browser_signal_seller_origin,
const std::optional<url::Origin>& browser_signal_top_level_seller_origin,
const base::TimeDelta browser_signal_recency,
mojom::BiddingBrowserSignalsPtr bidding_browser_signals,
base::Time auction_start_time,
const std::optional<blink::AdSize>& requested_ad_size,
uint16_t multi_bid_limit,
scoped_refptr<TrustedSignals::Result> trusted_bidding_signals_result,
bool trusted_bidding_signals_fetch_failed,
uint64_t trace_id,
base::ScopedClosureRunner cleanup_generate_bid_task,
GenerateBidCallbackInternal callback) { … }
std::optional<BidderWorklet::V8State::SingleGenerateBidResult>
BidderWorklet::V8State::RunGenerateBidOnce(
const mojom::BidderWorkletNonSharedParams& bidder_worklet_non_shared_params,
const url::Origin& interest_group_join_origin,
const std::string* auction_signals_json,
const std::string* per_buyer_signals_json,
const DirectFromSellerSignalsRequester::Result&
direct_from_seller_result_per_buyer_signals,
const std::optional<std::string>&
direct_from_seller_per_buyer_signals_header_ad_slot,
const DirectFromSellerSignalsRequester::Result&
direct_from_seller_result_auction_signals,
const std::optional<std::string>&
direct_from_seller_auction_signals_header_ad_slot,
const std::optional<base::TimeDelta> per_buyer_timeout,
const std::optional<blink::AdCurrency>& expected_buyer_currency,
const url::Origin& browser_signal_seller_origin,
const url::Origin* browser_signal_top_level_seller_origin,
const base::TimeDelta browser_signal_recency,
const mojom::BiddingBrowserSignalsPtr& bidding_browser_signals,
base::Time auction_start_time,
const std::optional<blink::AdSize>& requested_ad_size,
uint16_t multi_bid_limit,
const scoped_refptr<TrustedSignals::Result>& trusted_bidding_signals_result,
uint64_t trace_id,
std::unique_ptr<ContextRecycler> context_recycler_for_rerun,
bool restrict_to_kanon_ads) { … }
std::unique_ptr<ContextRecycler>
BidderWorklet::V8State::CreateContextRecyclerAndRunTopLevelForGenerateBid(
uint64_t trace_id,
AuctionV8Helper::TimeLimit& total_timeout,
bool should_deep_freeze,
std::vector<std::string>& errors_out) { … }
void BidderWorklet::V8State::ConnectDevToolsAgent(
mojo::PendingAssociatedReceiver<blink::mojom::DevToolsAgent> agent) { … }
BidderWorklet::V8State::~V8State() { … }
void BidderWorklet::V8State::FinishInit(
mojo::PendingRemote<mojom::AuctionSharedStorageHost>
shared_storage_host_remote) { … }
void BidderWorklet::V8State::PostResumeToUserThread(
base::WeakPtr<BidderWorklet> parent,
scoped_refptr<base::SequencedTaskRunner> user_thread) { … }
void BidderWorklet::V8State::PostReportWinCallbackToUserThread(
ReportWinCallbackInternal callback,
const std::optional<GURL>& report_url,
base::flat_map<std::string, GURL> ad_beacon_map,
base::flat_map<std::string, std::string> ad_macro_map,
PrivateAggregationRequests pa_requests,
base::TimeDelta reporting_latency,
std::vector<std::string> errors) { … }
void BidderWorklet::V8State::PostErrorBidCallbackToUserThread(
GenerateBidCallbackInternal callback,
base::TimeDelta bidding_latency,
PrivateAggregationRequests non_kanon_pa_requests,
RealTimeReportingContributions real_time_contributions,
std::vector<std::string> error_msgs) { … }
void BidderWorklet::ResumeIfPaused() { … }
void BidderWorklet::Start() { … }
void BidderWorklet::OnScriptDownloaded(
std::vector<WorkletLoader::Result> worklet_scripts,
std::optional<std::string> error_msg) { … }
void BidderWorklet::OnWasmDownloaded(
std::vector<WorkletWasmLoader::Result> worklet_scripts,
std::optional<std::string> error_msg) { … }
void BidderWorklet::MaybeRecordCodeWait() { … }
void BidderWorklet::RunReadyTasks() { … }
void BidderWorklet::OnTrustedBiddingSignalsDownloaded(
GenerateBidTaskList::iterator task,
scoped_refptr<TrustedSignals::Result> result,
std::optional<std::string> error_msg) { … }
void BidderWorklet::OnGenerateBidClientDestroyed(
GenerateBidTaskList::iterator task) { … }
void BidderWorklet::SignalsReceivedCallback(
GenerateBidTaskList::iterator task) { … }
void BidderWorklet::HandleDirectFromSellerForGenerateBid(
const std::optional<GURL>& direct_from_seller_per_buyer_signals,
const std::optional<GURL>& direct_from_seller_auction_signals,
GenerateBidTaskList::iterator task) { … }
void BidderWorklet::OnDirectFromSellerPerBuyerSignalsDownloadedGenerateBid(
GenerateBidTaskList::iterator task,
DirectFromSellerSignalsRequester::Result result) { … }
void BidderWorklet::OnDirectFromSellerAuctionSignalsDownloadedGenerateBid(
GenerateBidTaskList::iterator task,
DirectFromSellerSignalsRequester::Result result) { … }
bool BidderWorklet::IsReadyToGenerateBid(const GenerateBidTask& task) const { … }
void BidderWorklet::GenerateBidIfReady(GenerateBidTaskList::iterator task) { … }
void BidderWorklet::OnDirectFromSellerPerBuyerSignalsDownloadedReportWin(
ReportWinTaskList::iterator task,
DirectFromSellerSignalsRequester::Result result) { … }
void BidderWorklet::OnDirectFromSellerAuctionSignalsDownloadedReportWin(
ReportWinTaskList::iterator task,
DirectFromSellerSignalsRequester::Result result) { … }
bool BidderWorklet::IsReadyToReportWin(const ReportWinTask& task) const { … }
void BidderWorklet::RunReportWinIfReady(ReportWinTaskList::iterator task) { … }
void BidderWorklet::DeliverBidCallbackOnUserThread(
GenerateBidTaskList::iterator task,
std::vector<mojom::BidderWorkletBidPtr> bids,
std::optional<uint32_t> bidding_signals_data_version,
std::optional<GURL> debug_loss_report_url,
std::optional<GURL> debug_win_report_url,
std::optional<double> set_priority,
base::flat_map<std::string, mojom::PrioritySignalsDoublePtr>
update_priority_signals_overrides,
PrivateAggregationRequests pa_requests,
PrivateAggregationRequests non_kanon_pa_requests,
RealTimeReportingContributions real_time_contributions,
base::TimeDelta bidding_latency,
mojom::RejectReason reject_reason,
std::vector<std::string> error_msgs) { … }
void BidderWorklet::CleanUpBidTaskOnUserThread(
GenerateBidTaskList::iterator task) { … }
void BidderWorklet::DeliverReportWinOnUserThread(
ReportWinTaskList::iterator task,
std::optional<GURL> report_url,
base::flat_map<std::string, GURL> ad_beacon_map,
base::flat_map<std::string, std::string> ad_macro_map,
PrivateAggregationRequests pa_requests,
base::TimeDelta reporting_latency,
std::vector<std::string> errors) { … }
bool BidderWorklet::IsCodeReady() const { … }
}