chromium/content/services/auction_worklet/public/mojom/seller_worklet.mojom

// 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.

module auction_worklet.mojom;

import "content/services/auction_worklet/public/mojom/private_aggregation_request.mojom";
import "content/services/auction_worklet/public/mojom/real_time_reporting.mojom";
import "content/services/auction_worklet/public/mojom/reject_reason.mojom";
import "mojo/public/mojom/base/time.mojom";
import "services/network/public/mojom/url_loader_factory.mojom";
import "third_party/blink/public/mojom/devtools/devtools_agent.mojom";
import "third_party/blink/public/mojom/interest_group/ad_display_size.mojom";
import "third_party/blink/public/mojom/interest_group/interest_group_types.mojom";
import "url/mojom/origin.mojom";
import "url/mojom/url.mojom";

// The other seller associated with a bid. For component (nested)
// SellerWorklets, `top_level_seller` is the seller for the parent auction.
// For top-level SellerWorklets, `component_seller` is the seller in the
// nested component auction where the bid was originally made.
union ComponentAuctionOtherSeller {
  url.mojom.Origin top_level_seller;
  url.mojom.Origin component_seller;
};

// When ScoreAd() is invoked for a component seller worklet, it returns an
// additional set of parameters that are passed to the top-level seller
// worklet in place of output from the GenerateBid() call that created the bid.
struct ComponentAuctionModifiedBidParams {
  // Ad metadata to send to the top-level seller in place of
  // BidderWorkletBid::ad.
  string ad;

  // Bid value and currency to send to the top-level seller seller in place of
  // BidderWorkletBid::bid.
  double? bid;
  blink.mojom.AdCurrency? bid_currency;
};

// Input parameters specific to a component auction's ReportResult() method.
struct ComponentAuctionReportResultParams {
  // Metadata returned by the top-level seller's ReportResult() method, as JSON.
  string top_level_seller_signals;

  // The stochastically rounded numeric value of the bid returned by the
  // component seller's ScoreAd() method. May be the same value as the original
  // bid.
  double? modified_bid;
};

// Represents the time between SellerWorklet::ScoreAd and each of the
// dependencies to SellerWorklet::ScoreAdIfReady, which can help to identify
// the slowest dependency, both in absolute terms and relative to other
// dependencies. Each of the latencies recorded here may be null if that
// dependency didn't apply for this call to ScoreAd.
struct ScoreAdDependencyLatencies {
  // Load of Script
  mojo_base.mojom.TimeDelta? code_ready_latency;

  // Download of DirectFromSellerSignals
  mojo_base.mojom.TimeDelta? direct_from_seller_signals_latency;

  // Download of TrustedScoringSignals
  mojo_base.mojom.TimeDelta? trusted_scoring_signals_latency;

  // Times of each step of the ScoreAd flow, used to compute start and end
  // times for latency phase UKMs.
  mojo_base.mojom.TimeTicks deps_wait_start_time;
  mojo_base.mojom.TimeTicks score_ad_start_time;
  mojo_base.mojom.TimeTicks score_ad_finish_time;
};

// Interface for returning ScoreAd results. The advantage of having an interface
// is that it makes ScoreAd() calls cancellable, and allows callbacks passed
// over the Mojo pipe to be deleted when the Mojo pipe is, to avoid setting off
// the raw pointer lifetime validation logic.
interface ScoreAdClient {
  // Called when a ScoreAd() invocation completes.
  //
  // Parameters:
  // `score` Non-negative score the SellerWorklet assigns to the bid. A value
  //  of 0 indicates either an error running the script, or that the script
  //  indicated the bid should not be used.
  //
  // `bid_in_seller_currency` If present, denotes the conversion of bidder's
  //  bid to seller's currency. Should be present only when auction
  //  configuration specifies what the seller currency is.
  //
  // `reject_reason` The reason this bid was rejected by the auction (i.e., the
  //  reason why `score` was non-positive). Default to kNotAvailable if not set.
  //  Will be ignored if `score` is positive.
  //
  // `component_auction_modified_bid_params` If this is a component seller
  //  worklet, contains parameters to pass to the top-level seller worklet
  //  in place of values from the original bidder worklet's BidderWorkletBid.
  //
  // `scoring_signals_data_version` The value of the Data-Version header served
  //  with the trusted scoring signals. nullopt when the header wasn't present.
  //
  // `debug_loss_report_url` The URL to request if this bid does not win the
  //  auction. It's requested if the auction runs to completion and this is not
  //  the winning bid, including the case that this worklet rejects this bid
  //  outright, giving it a score <= 0. This field has the debug prefix because
  //  it's part of an interim reporting API that will be replaced with
  //  standardized reporting APIs once available. It must be a valid HTTPS URL.
  //
  // `debug_win_report_url` The URL to request if this bid wins the auction.
  //  This field has the debug prefix because it's part of an interim reporting
  //  API that will be replaced with standardized reporting APIs once available.
  //  It must be a valid HTTPS URL.
  //
  // `pa_requests` The various requests made to the Private Aggregation API.
  //
  // `real_time_contributions` Real time reporting contributions.
  //
  // `scoring_latency` How long it took to execute the scoreAd() JavaScript,
  //  (including the top-level).
  //
  // `trusted_signals_fetch_latency` How long it took to fetch the trusted
  //  scoring signals, if any. 0 if there weren't any.
  //
  // `errors` are various error messages to be used for debugging. These are too
  //  sensitive for the renderers to see. `errors` should not be assumed to be
  //  empty if `score` is positive, nor should it be assumed to be non-empty if
  //  `score` is 0.
  OnScoreAdComplete(double score,
                    RejectReason reject_reason,
                    ComponentAuctionModifiedBidParams?
                        component_auction_modified_bid_params,
                    double? bid_in_seller_currency,
                    uint32? scoring_signals_data_version,
                    url.mojom.Url? debug_loss_report_url,
                    url.mojom.Url? debug_win_report_url,
                    array<PrivateAggregationRequest> pa_requests,
                    array<RealTimeReportingContribution> real_time_contributions,
                    mojo_base.mojom.TimeDelta scoring_latency,
                    ScoreAdDependencyLatencies score_ad_dependency_latencies,
                    array<string> errors);
};

// Manages the auction workflow for one loaded FLEDGE seller worklet.
// See https://github.com/WICG/turtledove/blob/main/FLEDGE.md
//
// The SellerWorklet is functionally stateless, so methods are idempotent
// and can be called multiple times, in any order, for multiple auctions
// using the same worklet. There is no need to wait for one callback to be
// invoked before calling another method. There is no guarantee methods will
// complete in the order they are invoked.
interface SellerWorklet {
  // Calls the Javascript scoreAd() function to evaluate a bid. No data is
  // leaked between consecutive invocations of this method, or between
  // invocations of this method and ReportResult().
  //
  // In the case a worklet needs to fetch trusted scoring signals before
  // running any Javascript, the method may wait so it can merge several signals
  // fetched together. See SendPendingSignalsRequests() for more information.
  //
  // Arguments:
  // `ad_metadata_json` JSON representation of the `ad` value returned by the
  //  BidderWorklet that offered the bid.
  //
  // `bid` The numeric value of the bid offered by the BidderWorklet.
  //
  // `bid_currency` Currency of the bid offered by the BidderWorklet.
  //
  // `auction_ad_config_non_shared_params` Values in an AuctionConfig that can
  //  vary between auctions that can share a SellerWorklet.
  //
  // `direct_from_seller_seller_signals` The subresource URL of the
  //  DirectFromSellerSignals for the seller, as produced by concatenating the
  //  `directFromSellerSignals` URL prefix field passed from runAdAuction() with
  //  "?sellerSignals". Since this is fetched from a subresource bundle, it may
  //  only be fetched using the URLLoaderFactory passed in when creating the
  //  worklet.
  //
  // `direct_from_seller_seller_signals_header_ad_slot` A JSON string of the
  //  DirectFromSellerSignals for the seller. Must not be passed if
  //  `direct_from_seller_seller_signals` or
  //  `direct_from_seller_auction_signals` is passed.
  //
  // `direct_from_seller_auction_signals` The subresource URL of the
  //  directFromSellerSignals for the seller and all buyers, as produced by
  //  concatenating the `directFromSellerSignals` URL prefix field passed from
  //  runAdAuction() with "?auctionSignals". Since this is fetched from a
  //  subresource bundle, it may only be fetched using the URLLoaderFactory
  //  passed in when creating the worklet.
  //
  // `direct_from_seller_auction_signals_header_ad_slot` A JSON string of the
  //  DirectFromSellerSignals for the seller and all buyers. Must not be passed
  //  if `direct_from_seller_auction_signals` or
  //  `direct_from_seller_seller_signals` is passed.
  //
  // `browser_signals_other_seller` The origin of the other seller associated
  //  with the bid. If this is a component seller worklet, it's the
  //  top-level seller. If this is a top-level seller scoring a bid from a
  //  component auction, it's the seller in the component auction.
  //  Null if this is the top-level seller scoring its own bids.
  //
  // `component_expect_bid_currency` If this is a component auction, specifies
  //  what currency the top-level auction expects it to provide, if any.
  //  nullopt for top-level auction.
  //
  // `browser_signal_interest_group_owner` The owner of the interest group
  //  that offered the bid.
  //
  // `browser_signal_render_url` The `renderUrl` returned by the
  //  BidderWorklet making the bid.
  //
  // `browser_signal_selected_buyer_and_seller_reporting_id`
  //  The selected reporting id from the interest group's ad's
  // `selectableBuyerAndSellerReportingIds` array.
  //
  // `browser_signal_buyer_and_seller_reporting_id` This is the reporting id
  //  from from the interest group's ad's buyerAndSellerReportingId field,
  //  which is provided to both buyer and seller reporting worklets
  //  (reportWin() and reportResult() respectively). This is only provided to
  //  scoreAd() if browser_signal_selected_buyer_and_seller_reporting_id is
  //  also present.
  //
  // `browser_signal_ad_component_urls` The `adComponents` array returned by
  //  the BidderWorklet making the bid.
  //
  // `browser_signal_bidding_duration_msecs` is the duration the BiddingWorklet
  //  took to generate the bid. Taken as milliseconds to reduce granularity of
  //  timing information passed to an untrusted process.
  //
  // `browser_signal_render_size` is the size associated with the `renderUrl`
  // returned by the BidderWorklet making the bid. This argument is optional.
  // When there is no size associated with the `renderUrl`, it will be a
  // nullopt.
  // See explainer: https://github.com/WICG/turtledove/blob/main/FLEDGE.md#32-on-device-bidding
  //
  // `browser_signal_for_debugging_only_in_cooldown_or_lockout` Whether the
  // browser is under lockout or the seller's origin is under cooldown for
  // sending forDebuggingOnly reports.
  //
  // `seller_timeout` Restrict the runtime of the seller's scoring script. Any
  //  timeout higher than 500 ms will be clamped to 500 ms before passing in as
  //  `seller_timeout`. Null if not provided by the publisher page. Null will be
  //  passed to the worklet in that case.
  //
  // `trace_id` ID of a nestable asynchronous trace event of category `fledge`
  //  to use with tracing calls.
  //
  // `score_ad_client` When the ScoreAd completes, successfully or not, its
  // OnScoreAdComplete() method will be invoked with the results.
  ScoreAd(string ad_metadata_json,
          double bid,
          blink.mojom.AdCurrency? bid_currency,
          blink.mojom.AuctionAdConfigNonSharedParams
              auction_ad_config_non_shared_params,
          url.mojom.Url? direct_from_seller_seller_signals,
          string? direct_from_seller_seller_signals_header_ad_slot,
          url.mojom.Url? direct_from_seller_auction_signals,
          string? direct_from_seller_auction_signals_header_ad_slot,
          ComponentAuctionOtherSeller? browser_signals_other_seller,
          blink.mojom.AdCurrency? component_expect_bid_currency,
          url.mojom.Origin browser_signal_interest_group_owner,
          url.mojom.Url browser_signal_render_url,
          string? browser_signal_selected_buyer_and_seller_reporting_id,
          string? browser_signal_buyer_and_seller_reporting_id,
          array<url.mojom.Url> browser_signal_ad_component_render_urls,
          uint32 browser_signal_bidding_duration_msecs,
          blink.mojom.AdSize? browser_signal_render_size,
          bool browser_signal_for_debugging_only_in_cooldown_or_lockout,
          mojo_base.mojom.TimeDelta? seller_timeout,
          uint64 trace_id,
          pending_remote<ScoreAdClient> score_ad_client);

  // Hint to the worklet to send a network request for any needed trusted
  // signals data now. SellerWorklets normally wait briefy for there to be a
  // number of ScoreAd() calls before requesting trusted scoring signals so the
  // request can be batched together. This method can be called once all bids
  // have been generated to minimize the amount of time an auction spends
  // waiting on trusted signals data once the final bid has been generated. Does
  // nothing if no trusted scoring signals need to be fetched.
  SendPendingSignalsRequests();

  // Calls the Javascript reportResult() function to get the information needed
  // to report the result of the auction to the seller. May only be called once
  // ScoreAd() has successfully scored an ad, which will ensure the worklet has
  // completed loading. It does not make sense to invoke this with a score not
  // generated by a previous ScoreAd() call, so this should not limit consumers.
  // No data is leaked between consecutive invocations of this method, or
  // between invocations of this method and ScoreAd().
  //
  // Arguments:
  // `auction_ad_config_non_shared_params` Values in an AuctionConfig that can
  //  vary between auctions that can share a SellerWorklet.
  //
  // `direct_from_seller_seller_signals` The subresource URL of the
  //  DirectFromSellerSignals for the seller, as produced by concatenating the
  //  `directFromSellerSignals` URL prefix field passed from runAdAuction() with
  //  "?sellerSignals". Since this is fetched from a subresource bundle, it may
  //  only be fetched using the URLLoaderFactory passed in when creating the
  //  worklet.
  //
  // `direct_from_seller_seller_signals_header_ad_slot` A JSON string of the
  //  DirectFromSellerSignals for the seller. Must not be passed if
  //  `direct_from_seller_seller_signals` or
  //  `direct_from_seller_auction_signals` is passed.
  //
  // `direct_from_seller_auction_signals` The subresource URL of the
  //  directFromSellerSignals for the seller and all buyers, as produced by
  //  concatenating the `directFromSellerSignals` URL prefix field passed from
  //  runAdAuction() with "?auctionSignals". Since this is fetched from a
  //  subresource bundle, it may only be fetched using the URLLoaderFactory
  //  passed in when creating the worklet.
  //
  // `direct_from_seller_auction_signals_header_ad_slot` A JSON string of the
  //  DirectFromSellerSignals for the seller and all buyers. Must not be passed
  //  if `direct_from_seller_auction_signals` or
  //  `direct_from_seller_seller_signals` is passed.
  //
  // `browser_signals_other_seller` The origin of the other seller associated
  //  with the bid. If this is a component seller worklet, it's the
  //  top-level seller. If this is a top-level seller scoring a bid from a
  //  component auction, it's the seller in the component auction.
  //  Null if this is the top-level seller scoring its own bids.
  //
  // `browser_signal_interest_group_owner` The owner of the interest group
  //  that offered the winning bid.
  //
  //  `browser_signal_buyer_and_seller_reporting_id`. If the winning ad
  //  specified buyerAndSellerReportingId, and that ID passed the appropriate
  //  k-anonymity check, a value to set as
  //  browserSignals.buyerAndSellerReportingId will be included here; otherwise
  //  it is nullopt.
  //
  // `browser_signal_selected_buyer_and_seller_reporting_id` If the winning bid
  //  specified selectedBuyerAndSellerReportingId, and that ID passed the
  //  appropriate k-anonymity check, a value to set as
  //  browserSignals.selectedBuyerAndSellerReportingId will be included here;
  //  otherwise it is nullopt.
  //
  // `browser_signal_render_url` The render URL provided by the winning bid.
  //
  // `browser_signal_bid` The stochastically rounded numeric value of the
  //  winning bid.
  //
  // `browser_signal_bid_currency` The currency the bid is in. This is either
  //  the sellerCurrency from auction configuration, or unset to denote it's in
  //  the bidder's currency.
  //
  // `browser_signal_desirability` The stochastically rounded numeric value of
  //  the score returned by ScoreAd() for the winning bid.
  //
  // `browser_signal_highest_scoring_other_bid` The stochastically rounded
  //  numeric value of the bid that got the second highest score, or 0 if it's
  //  not available, either because there is no such thing or because no
  //  currency conversion was performed.
  //
  // `browser_signal_highest_scoring_other_bid_currency` The currency associated
  //  with `browser_signal_highest_scoring_other_bid`. This is either the
  //  sellerCurrency from auction configuration, if it's set, or nullopt to
  //  denote it's in the bidder's currency.
  //
  // `browser_signals_component_auction_report_result_params` Extra parameters
  //  passed to the component auction's ReportResult() method. Should be null
  //  for top-level sellers.
  //
  // `scoring_signals_data_version` The value of the Data-Version header served
  //  with the trusted scoring signals, if the header was present.
  //
  // `trace_id` ID of a nestable asynchronous trace event of category `fledge`
  //  to use with tracing calls.
  //
  // Returns:
  // `signals_for_winner` The value to pass to the winning bidder's
  //  ReportWin function, as a JSON string. Null if no value is provided.
  //
  // `report_url` The URL to request to report the result of the auction to the
  //  seller, if any.
  //
  // `ad_beacon_map` The map of ad reporting events to URLs for fenced frame
  //  reporting.
  //
  // `pa_requests` The various requests made to the Private Aggregation API.
  //
  // `reporting_latency` How long it took to run `reportResult()` JS, including
  //  the top-level.
  //
  // `errors` are various error messages to be used for debugging. These are too
  //  sensitive for the renderers to see. `errors` should not be assumed to be
  //  empty if the other values are populated, nor should it be assumed to be
  //  non-empty if the other values are null.
  ReportResult(
      blink.mojom.AuctionAdConfigNonSharedParams
          auction_ad_config_non_shared_params,
      url.mojom.Url? direct_from_seller_seller_signals,
      string? direct_from_seller_seller_signals_header_ad_slot,
      url.mojom.Url? direct_from_seller_auction_signals,
      string? direct_from_seller_auction_signals_header_ad_slot,
      ComponentAuctionOtherSeller? browser_signals_other_seller,
      url.mojom.Origin browser_signal_interest_group_owner,
      string? browser_signal_buyer_and_seller_reporting_id,
      string? browser_signal_selected_buyer_and_seller_reporting_id,
      url.mojom.Url browser_signal_render_url,
      double browser_signal_bid,
      blink.mojom.AdCurrency? browser_signal_bid_currency,
      double browser_signal_desirability,
      double browser_signal_highest_scoring_other_bid,
      blink.mojom.AdCurrency? browser_signal_highest_scoring_other_bid_currency,
      ComponentAuctionReportResultParams?
          browser_signals_component_auction_report_result_params,
      uint32? scoring_signals_data_version,
      uint64 trace_id) =>
          (string? signals_for_winner,
           url.mojom.Url? report_url,
           map<string, url.mojom.Url> ad_beacon_map,
           array<PrivateAggregationRequest> pa_requests,
           mojo_base.mojom.TimeDelta reporting_latency,
           array<string> error_msgs);

  // Establishes a debugger connection to the worklet thread.
  //
  // Arguments:
  // `thread_index` The index of the thread in the thread pool.
  ConnectDevToolsAgent(
      pending_associated_receiver<blink.mojom.DevToolsAgent> agent,
      uint32 thread_index);
};