blob: 1091dbf2c07de5a8ed0652836611c906d1e340a6 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_INTEREST_GROUP_AUCTION_RUNNER_H_
#define CONTENT_BROWSER_INTEREST_GROUP_AUCTION_RUNNER_H_
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/interest_group/auction_metrics_recorder.h"
#include "content/browser/interest_group/auction_nonce_manager.h"
#include "content/browser/interest_group/auction_worklet_manager.h"
#include "content/browser/interest_group/interest_group_auction.h"
#include "content/browser/interest_group/interest_group_auction_reporter.h"
#include "content/common/content_export.h"
#include "content/services/auction_worklet/public/mojom/private_aggregation_request.mojom-forward.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "services/network/public/mojom/client_security_state.mojom.h"
#include "third_party/blink/public/common/interest_group/interest_group.h"
#include "third_party/blink/public/mojom/interest_group/ad_auction_service.mojom.h"
#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom.h"
#include "url/origin.h"
namespace blink {
struct AuctionConfig;
}
namespace content {
class AdAuctionPageData;
class InterestGroupAuctionReporter;
class BrowserContext;
class InterestGroupManagerImpl;
class PrivateAggregationManager;
struct DebugReportLockoutAndCooldowns;
// An AuctionRunner loads and runs the bidder and seller worklets, along with
// their reporting phases and produces the result via a callback. Most of the
// logic is handled by InterestGroupAuction, with the AuctionRunner handling
// state transitions and assembling the final results of the auction.
//
// All auctions must be created on the same thread. This is just needed because
// the code to assign unique tracing IDs is not threadsafe.
class CONTENT_EXPORT AuctionRunner : public blink::mojom::AbortableAdAuction {
public:
// After each auction, delay the update of interest groups so that data in the
// InterestGroupCachingStorage is not invalidated while a page's other
// auctions are likely still running.
static constexpr base::TimeDelta kPostAuctionInterestGroupUpdateDelay =
base::Seconds(3);
// Max reporting timeout for seller's reportResult() and buyer's reportWin().
static constexpr base::TimeDelta kMaxReportingTimeout = base::Seconds(5);
using PrivateAggregationRequests =
std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr>;
// Invoked when a FLEDGE auction is complete.
//
// `aborted_by_script` is true only if the auction was successfully
// interrupted by the call to Abort().
//
// `winning_group_id` owner and name of the winning interest group (if any).
//
// `requested_ad_size` requested size for the ad auction (if any). Stored into
// the fenced frame config container size.
//
// `ad_descriptor` URL of auction winning ad to render with optional
// size. Null if there is no winner.
//
// `ad_component_descriptors` is the list of ad component URLs with
// optional size returned by the winning bidder. Null if there is no winner or
// no list was returned.
//
// `errors` are various error messages to be used for debugging. These are too
// sensitive for the renderers to see.
//
// `interest_group_auction_reporter` is the InterestGroupAuctionReporter to be
// used to report the result of the auction.
//
// `contained_server_auction` is true if any component of the auction was a
// server auction.
//
// `contained_on_device_auction` is true if the auction contained any
// on-device component or if there was only a top-level auction.
//
// `result` is the result of the auction.
using RunAuctionCallback = base::OnceCallback<void(
AuctionRunner* auction_runner,
bool aborted_by_script,
std::optional<blink::InterestGroupKey> winning_group_id,
std::optional<blink::AdSize> requested_ad_size,
std::optional<blink::AdDescriptor> ad_descriptor,
std::vector<blink::AdDescriptor> ad_component_descriptors,
std::vector<std::string> errors,
std::unique_ptr<InterestGroupAuctionReporter>
interest_group_auction_reporter,
bool contained_server_auction,
bool contained_on_device_auction,
AuctionResult result)>;
// Returns true if `origin` is allowed to use the interest group API. Will be
// called on worklet / interest group origins before using them in any
// interest group API.
using IsInterestGroupApiAllowedCallback =
InterestGroupAuction::IsInterestGroupApiAllowedCallback;
using AreReportingOriginsAttestedCallback =
base::RepeatingCallback<bool(const std::vector<url::Origin>&)>;
using AdAuctionPageDataCallback =
base::RepeatingCallback<AdAuctionPageData*()>;
// Creates an entire FLEDGE auction. Single-use object.
//
// Arguments: `auction_worklet_manager`, `interest_group_manager`,
// `auction_nonce_manager`, `browser_context`, and
// `private_aggregation_manager` must remain valid, and
// `log_private_aggregation_requests_callback` must be safe to call until the
// AuctionRunner and any InterestGroupAuctionReporter it returns are
// destroyed.
//
// `ad_auction_page_data_callback` must remain safe to call for lifetime of
// AuctionRunner. It is permitted to return nullptr, in circumstances where
// the auction is not expected to be able to proceed. The value it returns
// may become invalid upon return to the event loop and therefore should not
// be stored long-term.
//
// `auction_config` is the configuration provided by client JavaScript in the
// renderer in order to initiate the auction.
//
// `main_frame_origin` is the origin of the main frame where the auction is
// running. Used for issuing reports.
//
// `frame_origin` is the origin of the frame running the auction. Used for
// issuing reports.
//
// `client_security_state` is the client security state of the frame that
// issued the auction request -- this is used for post-auction interest
// group updates, and sending reports.
//
// `url_loader_factory` will be used to issue reporting requests and request
// trusted KVv2 signals. It should be backed by a trusted URLLoaderFactory
// associated with the frame running the auction.
//
// `is_interest_group_api_allowed_callback` will be called on all buyer and
// seller origins, and those for which it returns false will not be allowed
// to participate in the auction.
//
// `attestation_callback` will be called on all interest group
// updates' ad allowed reporting origins, and those updates which the
// callback returns false will not update the interest group.
//
// `callback` is invoked on auction completion. It should synchronously
// destroy this AuctionRunner object. `callback` won't be invoked until
// after CreateAndStart() returns.
static std::unique_ptr<AuctionRunner> CreateAndStart(
AuctionMetricsRecorder* auction_metrics_recorder,
DwaAuctionMetricsManager* dwa_auction_metrics_manager,
AuctionWorkletManager* auction_worklet_manager,
AuctionNonceManager* auction_nonce_manager,
InterestGroupManagerImpl* interest_group_manager,
BrowserContext* browser_context,
PrivateAggregationManager* private_aggregation_manager,
AdAuctionPageDataCallback ad_auction_page_data_callback,
InterestGroupAuctionReporter::LogPrivateAggregationRequestsCallback
log_private_aggregation_requests_callback,
const blink::AuctionConfig& auction_config,
const url::Origin& main_frame_origin,
const url::Origin& frame_origin,
std::optional<std::string> user_agent_override,
network::mojom::ClientSecurityStatePtr client_security_state,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
IsInterestGroupApiAllowedCallback is_interest_group_api_allowed_callback,
AreReportingOriginsAttestedCallback attestation_callback,
mojo::PendingReceiver<AbortableAdAuction> abort_receiver,
RunAuctionCallback callback);
explicit AuctionRunner(const AuctionRunner&) = delete;
AuctionRunner& operator=(const AuctionRunner&) = delete;
~AuctionRunner() override;
// AbortableAdAuction implementation.
void ResolvedPromiseParam(
blink::mojom::AuctionAdConfigAuctionIdPtr auction_id,
blink::mojom::AuctionAdConfigField field,
const std::optional<std::string>& json_value) override;
void ResolvedPerBuyerSignalsPromise(
blink::mojom::AuctionAdConfigAuctionIdPtr auction_id,
const std::optional<base::flat_map<url::Origin, std::string>>&
per_buyer_signals) override;
void ResolvedBuyerTkvSignalsPromise(
blink::mojom::AuctionAdConfigAuctionIdPtr auction_id,
const url::Origin& buyer,
const std::optional<std::string>& buyer_tkv_signals) override;
void ResolvedBuyerTimeoutsPromise(
blink::mojom::AuctionAdConfigAuctionIdPtr auction_id,
blink::mojom::AuctionAdConfigBuyerTimeoutField field,
const blink::AuctionConfig::BuyerTimeouts& buyer_timeouts) override;
void ResolvedBuyerCurrenciesPromise(
blink::mojom::AuctionAdConfigAuctionIdPtr auction_id,
const blink::AuctionConfig::BuyerCurrencies& buyer_currencies) override;
void ResolvedDirectFromSellerSignalsPromise(
blink::mojom::AuctionAdConfigAuctionIdPtr auction_id,
const std::optional<blink::DirectFromSellerSignals>&
direct_from_seller_signals) override;
void ResolvedDirectFromSellerSignalsHeaderAdSlotPromise(
blink::mojom::AuctionAdConfigAuctionIdPtr auction_id,
const std::optional<std::string>&
direct_from_seller_signals_header_ad_slot) override;
void ResolvedDeprecatedRenderURLReplacementsPromise(
blink::mojom::AuctionAdConfigAuctionIdPtr auction,
const std::vector<blink::AuctionConfig::AdKeywordReplacement>&
deprecated_render_url_replacements) override;
void ResolvedAuctionAdResponsePromise(
blink::mojom::AuctionAdConfigAuctionIdPtr auction_id,
mojo_base::BigBuffer response) override;
void ResolvedAdditionalBids(
blink::mojom::AuctionAdConfigAuctionIdPtr auction) override;
void Abort() override;
// Normalize reporting timeouts, including those in component auction configs.
void NormalizeReportingTimeouts();
// Fails the auction, invoking `callback_` and prevents any future calls into
// `this` by closing mojo pipes and disposing of weak pointers. The owner must
// be able to safely delete `this` when the callback is invoked. May only be
// invoked if the auction has not yet completed.
//
// `interest_groups_that_bid` is a list of the interest groups that bid in the
// auction.
void FailAuction(bool aborted_by_script,
blink::InterestGroupSet interest_groups_that_bid =
blink::InterestGroupSet());
private:
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
enum class State {
kNotYetStarted = 0,
kLoadingGroupsPhase = 1,
kBiddingAndScoringPhase = 2,
kSucceeded = 3,
kFailed = 4,
kMaxValue = kFailed
};
AuctionRunner(
AuctionMetricsRecorder* auction_metrics_recorder,
DwaAuctionMetricsManager* dwa_auction_metrics_manager,
AuctionWorkletManager* auction_worklet_manager,
AuctionNonceManager* auction_nonce_manager,
InterestGroupManagerImpl* interest_group_manager,
BrowserContext* browser_context,
PrivateAggregationManager* private_aggregation_manager,
AdAuctionPageDataCallback ad_auction_page_data_callback,
InterestGroupAuctionReporter::LogPrivateAggregationRequestsCallback
log_private_aggregation_requests_callback,
auction_worklet::mojom::KAnonymityBidMode kanon_mode,
const blink::AuctionConfig& auction_config,
const url::Origin& main_frame_origin,
const url::Origin& frame_origin,
std::optional<std::string> user_agent_override,
network::mojom::ClientSecurityStatePtr client_security_state,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
IsInterestGroupApiAllowedCallback is_interest_group_api_allowed_callback,
AreReportingOriginsAttestedCallback attestation_callback,
mojo::PendingReceiver<AbortableAdAuction> abort_receiver,
RunAuctionCallback callback);
// Tells `auction_` to start the loading interest groups phase.
void StartAuction();
// Invoked asynchronously by `auction_` once all interest groups have loaded.
// Fails the auction if `success` is false. Otherwise, starts the bidding and
// scoring phase if flag kEnableSamplingDebugReports is disabled, or starts
// loading cooldown for sending forDebuggingOnly reports if enabled.
void OnLoadInterestGroupsComplete(bool success);
// Invoked asynchronously by `interest_group_manager_` once the state of the
// cooldown for sending forDebuggingOnly reports have loaded. Only invoked
// when flag kEnableSamplingDebugReports is enabled.
void OnLoadDebugReportLockoutAndCooldownsComplete(
std::optional<DebugReportLockoutAndCooldowns>
debug_report_lockout_and_cooldowns);
// Invoked asynchronously by `auction_` once the bidding and scoring phase is
// complete. Either fails the auction (in which case it records the interest
// groups that bid) or starts the reporting phase, depending on the value of
// `success`.
void OnBidsGeneratedAndScored(base::TimeTicks start_time, bool success);
// Invoked asynchronously by `auction_` once the reporting phase has
// completed. Records `interest_groups_that_bid`. If `success` is false, fails
// the auction. Otherwise, records which interest group won the auction and
// collects parameters needed to invoke the auction callback.
void OnReportingPhaseComplete(
blink::InterestGroupSet interest_groups_that_bid,
bool success);
// After an auction completes (success or failure -- wherever `callback_` is
// invoked), updates the set of interest groups that participated in the
// auction.
void UpdateInterestGroupsPostAuction();
// Notify relevant InterestGroupAuctions of progress in resolving promises in
// config, as appropriate. Manages `promise_fields_in_auction_config_`.
void NotifyPromiseResolved(
const blink::mojom::AuctionAdConfigAuctionId& auction_id,
const blink::AuctionConfig& config);
// Looks up the decoder from AdAuctionPageData, if that's available.
data_decoder::DataDecoder* GetDataDecoder(const url::Origin& origin);
// Returns whether this auction includes any server component or top-level
// auction (in the first bool) and on-device component or top-level auction
// (in the second bool).
std::pair<bool, bool> IncludesServerAndOnDeviceAuctions();
const raw_ptr<InterestGroupManagerImpl> interest_group_manager_;
// Needed to create `FencedFrameReporter`.
const raw_ptr<BrowserContext> browser_context_;
const raw_ptr<PrivateAggregationManager> private_aggregation_manager_;
const url::Origin main_frame_origin_;
const url::Origin frame_origin_;
// ClientSecurityState built from the frame that issued the auction request;
// will be used to update interest groups that participated in the auction
// after the auction.
const network::mojom::ClientSecurityStatePtr client_security_state_;
std::optional<std::string> user_agent_override_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// For checking if operations like running auctions, updating interest groups,
// etc. are allowed or not.
IsInterestGroupApiAllowedCallback is_interest_group_api_allowed_callback_;
AdAuctionPageDataCallback ad_auction_page_data_callback_;
AreReportingOriginsAttestedCallback attestation_callback_;
mojo::Receiver<blink::mojom::AbortableAdAuction> abort_receiver_;
// Configuration.
// Whether k-anonymity enforcement or simulation (or none) are performed.
const auction_worklet::mojom::KAnonymityBidMode kanon_mode_;
// Use a smart pointer so can pass ownership to InterestGroupAuctionReporter
// without invalidating pointers.
std::unique_ptr<blink::AuctionConfig> owned_auction_config_;
RunAuctionCallback callback_;
// Number of fields in `owned_auction_config_` that are promises; decremented
// as they get resolved.
int promise_fields_in_auction_config_;
InterestGroupAuction auction_;
State state_ = State::kNotYetStarted;
base::WeakPtrFactory<AuctionRunner> weak_ptr_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_INTEREST_GROUP_AUCTION_RUNNER_H_