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

#include "content/browser/interest_group/interest_group_auction.h"

#include <stdint.h>

#include <algorithm>
#include <cmath>
#include <iterator>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/base64.h"
#include "base/check.h"
#include "base/containers/flat_set.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/json/json_string_value_serializer.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/rand_util.h"
#include "base/ranges/algorithm.h"
#include "base/strings/escape.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_id_helper.h"
#include "base/types/optional_ref.h"
#include "base/uuid.h"
#include "content/browser/interest_group/ad_auction_page_data.h"
#include "content/browser/interest_group/additional_bid_result.h"
#include "content/browser/interest_group/additional_bids_util.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_process_manager.h"
#include "content/browser/interest_group/auction_result.h"
#include "content/browser/interest_group/auction_url_loader_factory_proxy.h"
#include "content/browser/interest_group/auction_worklet_manager.h"
#include "content/browser/interest_group/debuggable_auction_worklet.h"
#include "content/browser/interest_group/header_direct_from_seller_signals.h"
#include "content/browser/interest_group/interest_group_auction_reporter.h"
#include "content/browser/interest_group/interest_group_caching_storage.h"
#include "content/browser/interest_group/interest_group_k_anonymity_manager.h"
#include "content/browser/interest_group/interest_group_manager_impl.h"
#include "content/browser/interest_group/interest_group_pa_report_util.h"
#include "content/browser/interest_group/interest_group_priority_util.h"
#include "content/browser/interest_group/storage_interest_group.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/services/auction_worklet/public/mojom/bidder_worklet.mojom-forward.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/seller_worklet.mojom.h"
#include "crypto/sha2.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/associated_receiver_set.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "net/third_party/quiche/src/quiche/oblivious_http/buffers/oblivious_http_response.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
#include "services/network/public/mojom/client_security_state.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
#include "third_party/abseil-cpp/absl/types/optional.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_utils.h"
#include "third_party/blink/public/common/interest_group/auction_config.h"
#include "third_party/blink/public/common/interest_group/interest_group.h"
#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace content {

// The BiddingAndAuctionEncryptionMediaType feature controls the format we use
// for the request to the Bidding and Auction Service. anything. When enabled
// we add an extra byte to the request.
CONTENT_EXPORT BASE_FEATURE(kBiddingAndAuctionEncryptionMediaType,
                            "BiddingAndAuctionEncryptionMediaType",
                            base::FEATURE_DISABLED_BY_DEFAULT);
// While we would prefer to reference the constants from quiche for the defaults
// here, they are only available as absl::string_view objects which are not
// easily convertible to null-terminated strings. Previously we used the .data()
// accessor which worked due to undefined behavior.
const base::FeatureParam<std::string>
    kBiddingAndAuctionEncryptionRequestMediaType{
        &kBiddingAndAuctionEncryptionMediaType,
        "BiddingAndAuctionEncryptionRequestMediaType", "message/bhttp request"};
const base::FeatureParam<std::string>
    kBiddingAndAuctionEncryptionResponseMediaType{
        &kBiddingAndAuctionEncryptionMediaType,
        "BiddingAndAuctionEncryptionResponseMediaType",
        "message/bhttp response"};

namespace {

constexpr base::TimeDelta kMaxPerBuyerTimeout = base::Milliseconds(500);

// For group freshness metrics.
constexpr base::TimeDelta kGroupFreshnessMin = base::Minutes(1);
constexpr base::TimeDelta kGroupFreshnessMax = base::Days(30);
constexpr int kGroupFreshnessBuckets = 100;

// All URLs received from worklets must be valid HTTPS URLs. It's up to callers
// to call ReportBadMessage() on invalid URLs.
bool IsUrlValid(const GURL& url) {
  return url.is_valid() && url.SchemeIs(url::kHttpsScheme);
}

bool IsKAnon(const base::flat_map<std::string, bool>& kanon_keys,
             const std::string& key) {
  auto it = kanon_keys.find(key);
  return it != kanon_keys.end() && it->second;
}

bool IsKAnon(const base::flat_map<std::string, bool>& kanon_keys,
             const blink::InterestGroup& interest_group,
             const auction_worklet::mojom::BidderWorkletBid* bid) {
  if (!IsKAnon(kanon_keys,
               blink::KAnonKeyForAdBid(interest_group, bid->ad_descriptor))) {
    return false;
  }
  if (bid->ad_component_descriptors.has_value()) {
    for (const blink::AdDescriptor& component :
         bid->ad_component_descriptors.value()) {
      if (!IsKAnon(kanon_keys, blink::KAnonKeyForAdComponentBid(component))) {
        return false;
      }
    }
  }
  return true;
}

base::flat_map<auction_worklet::mojom::KAnonKeyPtr, bool> KAnonKeysToMojom(
    const base::flat_map<std::string, bool>& kanon_keys) {
  std::vector<std::pair<auction_worklet::mojom::KAnonKeyPtr, bool>> result;
  for (const auto& key : kanon_keys) {
    result.emplace_back(auction_worklet::mojom::KAnonKey::New(key.first),
                        key.second);
  }
  return std::move(result);
}

// Finds InterestGroup::Ad in `ads` that matches `ad_descriptor`, if any.
// Returns nullptr if `ad_descriptor` is invalid.
const blink::InterestGroup::Ad* FindMatchingAd(
    const std::vector<blink::InterestGroup::Ad>& ads,
    const base::flat_map<std::string, bool>& kanon_keys,
    const blink::InterestGroup& interest_group,
    InterestGroupAuction::Bid::BidRole bid_role,
    bool is_component_ad,
    const blink::AdDescriptor& ad_descriptor) {
  // TODO(mmenke): Validate render URLs on load and make this a DCHECK just
  // before the return instead, since then `ads` will necessarily only contain
  // valid URLs at that point.
  if (!IsUrlValid(ad_descriptor.url)) {
    return nullptr;
  }

  if (ad_descriptor.size && !IsValidAdSize(ad_descriptor.size.value())) {
    return nullptr;
  }

  if (bid_role != InterestGroupAuction::Bid::BidRole::kUnenforcedKAnon) {
    const std::string kanon_key =
        is_component_ad
            ? blink::KAnonKeyForAdComponentBid(ad_descriptor)
            : blink::KAnonKeyForAdBid(interest_group, ad_descriptor);
    if (!IsKAnon(kanon_keys, kanon_key)) {
      return nullptr;
    }
  }

  for (const auto& ad : ads) {
    if (ad.render_url != ad_descriptor.url) {
      continue;
    }
    if (!ad.size_group && !ad_descriptor.size) {
      // Neither `blink::InterestGroup::Ad` nor the ad from the bid have any
      // size specifications. They are considered as matching ad as long as
      // they have the same url.
      return &ad;
    }
    if (!ad.size_group != !ad_descriptor.size) {
      // When only one of the two ads has a size specification, they are
      // considered matching. The caller is responsible for discarding the
      // extraneous size information
      return &ad;
    }
    // Both `blink::InterestGroup::Ad` and the ad from the bid have size
    // specifications. They are considered as matching ad only if their
    // size also matches.
    auto has_matching_ad_size = [&interest_group,
                                 &ad_descriptor](const std::string& ad_size) {
      return interest_group.ad_sizes->at(ad_size) == *ad_descriptor.size;
    };
    if (base::ranges::any_of(interest_group.size_groups->at(ad.size_group),
                             has_matching_ad_size)) {
      // Each size group may also correspond to multiple ad sizes. If any of
      // those ad sizes matches with the ad size from `ad_descriptor`, they are
      // considered as matching ads.
      return &ad;
    }
  }

  return nullptr;
}

// Checks that `bid` is a valid bid value for an auction.
bool IsValidBid(double bid) {
  return !std::isnan(bid) && std::isfinite(bid) && bid > 0;
}

struct BidStatesDescByPriority {
  bool operator()(const std::unique_ptr<InterestGroupAuction::BidState>& a,
                  const std::unique_ptr<InterestGroupAuction::BidState>& b) {
    return a->calculated_priority > b->calculated_priority;
  }
  bool operator()(const std::unique_ptr<InterestGroupAuction::BidState>& a,
                  double b_priority) {
    return a->calculated_priority > b_priority;
  }
  bool operator()(double a_priority,
                  const std::unique_ptr<InterestGroupAuction::BidState>& b) {
    return a_priority > b->calculated_priority;
  }
};

struct BidStatesDescByPriorityAndGroupByJoinOrigin {
  bool operator()(const std::unique_ptr<InterestGroupAuction::BidState>& a,
                  const std::unique_ptr<InterestGroupAuction::BidState>& b) {
    return std::tie(a->calculated_priority, a->bidder->joining_origin,
                    a->bidder->interest_group.execution_mode) >
           std::tie(b->calculated_priority, b->bidder->joining_origin,
                    b->bidder->interest_group.execution_mode);
  }
};

bool IsBidRoleUsedForWinner(
    auction_worklet::mojom::KAnonymityBidMode kanon_mode,
    InterestGroupAuction::Bid::BidRole bid_role) {
  if (kanon_mode == auction_worklet::mojom::KAnonymityBidMode::kEnforce) {
    return bid_role != InterestGroupAuction::Bid::BidRole::kUnenforcedKAnon;
  } else {
    return bid_role != InterestGroupAuction::Bid::BidRole::kEnforcedKAnon;
  }
}

static const char* ScoreAdTraceEventName(const InterestGroupAuction::Bid& bid) {
  if (bid.bid_role == InterestGroupAuction::Bid::BidRole::kEnforcedKAnon) {
    return "seller_worklet_score_kanon_enforced_ad";
  } else {
    return "seller_worklet_score_ad";
  }
}

// Returns true iff `interest_group` grants `seller` all the capabilities in
// `capabilities`.
bool GroupSatisfiesAllCapabilities(const blink::InterestGroup& interest_group,
                                   blink::SellerCapabilitiesType capabilities,
                                   const url::Origin& seller) {
  if (interest_group.seller_capabilities) {
    auto it = interest_group.seller_capabilities->find(seller);
    if (it != interest_group.seller_capabilities->end()) {
      return it->second.HasAll(capabilities);
    }
  }
  return interest_group.all_sellers_capabilities.HasAll(capabilities);
}

// Helper for ReportPaBuyersValueIfAllowed() -- returns true iff
// `interest_group`'s seller capabilities has authorized `capability` for
// `seller`.
bool CanReportPaBuyersValue(const blink::InterestGroup& interest_group,
                            blink::SellerCapabilities capability,
                            const url::Origin& seller) {
  return GroupSatisfiesAllCapabilities(interest_group, {capability}, seller);
}

// Helper for ReportPaBuyersValueIfAllowed() -- returns the bucket base
// of `buyer`, if present in `config`'s `auction_report_buyer_keys`.
absl::optional<absl::uint128> BucketBaseForReportPaBuyers(
    const blink::AuctionConfig& config,
    const url::Origin& buyer) {
  if (!config.non_shared_params.auction_report_buyer_keys) {
    return absl::nullopt;
  }
  // Find the index of the buyer in `buyers`. It should be present, since we
  // only load interest groups belonging to owners from `buyers`.
  DCHECK(config.non_shared_params.interest_group_buyers);
  const std::vector<url::Origin>& buyers =
      *config.non_shared_params.interest_group_buyers;
  absl::optional<size_t> index;
  for (size_t i = 0; i < buyers.size(); i++) {
    if (buyer == buyers.at(i)) {
      index = i;
      break;
    }
  }
  DCHECK(index);
  // Use that index to get the associated bucket base, if present.
  if (*index >= config.non_shared_params.auction_report_buyer_keys->size()) {
    return absl::nullopt;
  }
  return config.non_shared_params.auction_report_buyer_keys->at(*index);
}

// Helper for ReportPaBuyersValueIfAllowed() -- returns the
// AuctionReportBuyersConfig for `buyer_report_type`, if it exists in
// `auction_report_buyers` in `config`.
absl::optional<blink::AuctionConfig::NonSharedParams::AuctionReportBuyersConfig>
ReportBuyersConfigForPaBuyers(
    blink::AuctionConfig::NonSharedParams::BuyerReportType buyer_report_type,
    const blink::AuctionConfig& config) {
  if (!config.non_shared_params.auction_report_buyers) {
    return absl::nullopt;
  }
  const auto& report_buyers = *config.non_shared_params.auction_report_buyers;
  auto it = report_buyers.find(buyer_report_type);
  if (it == report_buyers.end()) {
    return absl::nullopt;
  }
  return it->second;
}

// Takes private aggregation requests for `state`, if there are any, and moves
// them into `private_aggregation_requests_reserved` and
// `private_aggregation_requests_non_reserved`.
//
// Calculates bucket/value using `signals` and `top_level_signals` as needed.
//
// `winner` points to the BidState associated with the winning bid, if there
// is one.
//
// `signals` are the PostAuctionSignals from the auction `state` was a part of.
void TakePrivateAggregationRequestsForBidState(
    std::unique_ptr<InterestGroupAuction::BidState>& state,
    bool is_component_auction,
    const InterestGroupAuction::BidState* winner,
    const InterestGroupAuction::BidState* non_kanon_winner,
    const InterestGroupAuction::PostAuctionSignals& signals,
    const absl::optional<InterestGroupAuction::PostAuctionSignals>&
        top_level_signals,
    std::map<InterestGroupAuctionReporter::PrivateAggregationKey,
             InterestGroupAuctionReporter::PrivateAggregationRequests>&
        private_aggregation_requests_reserved,
    std::map<std::string,
             InterestGroupAuctionReporter::PrivateAggregationRequests>&
        private_aggregation_requests_non_reserved) {
  bool is_winner = state.get() == winner;
  for (auto& [key, requests] : state->private_aggregation_requests) {
    const url::Origin& origin = key.reporting_origin;
    InterestGroupAuction::PrivateAggregationPhase phase = key.phase;
    const absl::optional<url::Origin>& aggregation_coordinator_origin =
        key.aggregation_coordinator_origin;
    double winning_bid_to_use = signals.winning_bid;
    double highest_scoring_other_bid_to_use = signals.highest_scoring_other_bid;
    // When component auctions are in use, a BuyerHelper for a component
    // auction calls here for the scoreAd() aggregation calls from the
    // top-level; in that case the relevant signals are in
    // `top_level_signals` and not `signals`. `highest_scoring_other_bid`
    // is also not reported for top-levels.
    if (phase ==
            InterestGroupAuction::PrivateAggregationPhase::kTopLevelSeller &&
        is_component_auction) {
      highest_scoring_other_bid_to_use = 0;
      winning_bid_to_use =
          top_level_signals.has_value() ? top_level_signals->winning_bid : 0.0;
    }

    for (auction_worklet::mojom::PrivateAggregationRequestPtr& request :
         requests) {
      absl::optional<PrivateAggregationRequestWithEventType> converted_request =
          FillInPrivateAggregationRequest(
              std::move(request), winning_bid_to_use,
              highest_scoring_other_bid_to_use, state->reject_reason,
              state->pa_timings(phase), is_winner);
      if (converted_request.has_value()) {
        PrivateAggregationRequestWithEventType converted_request_value =
            std::move(converted_request.value());
        const absl::optional<std::string>& event_type =
            converted_request_value.event_type;
        if (event_type.has_value()) {
          // The request has a non-reserved event type.
          private_aggregation_requests_non_reserved[event_type.value()]
              .emplace_back(std::move(converted_request_value.request));
        } else {
          InterestGroupAuctionReporter::PrivateAggregationKey agg_key = {
              origin, aggregation_coordinator_origin};
          private_aggregation_requests_reserved[std::move(agg_key)]
              .emplace_back(std::move(converted_request_value.request));
        }
      }
    }
  }
  if (non_kanon_winner == state.get()) {
    const url::Origin& bidder = state->bidder->interest_group.owner;
    const absl::optional<url::Origin>& aggregation_coordinator_origin =
        state->bidder->interest_group.aggregation_coordinator_origin;
    for (auction_worklet::mojom::PrivateAggregationRequestPtr& request :
         state->non_kanon_private_aggregation_requests) {
      absl::optional<PrivateAggregationRequestWithEventType> converted_request =
          FillInPrivateAggregationRequest(
              std::move(request), signals.winning_bid,
              signals.highest_scoring_other_bid,
              auction_worklet::mojom::RejectReason::kBelowKAnonThreshold,
              state->pa_timings(
                  InterestGroupAuction::PrivateAggregationPhase::kBidder),
              false);
      if (converted_request.has_value()) {
        InterestGroupAuctionReporter::PrivateAggregationKey agg_key = {
            bidder, aggregation_coordinator_origin};
        PrivateAggregationRequestWithEventType converted_request_value =
            std::move(converted_request.value());
        // Only reserved types are supported for k-anon failures.
        // This *should* be guaranteed by `FillInPrivateAggregationRequest`
        // since we passed in `false` for `is_winner`.
        DCHECK(!converted_request_value.event_type.has_value());
        private_aggregation_requests_reserved[std::move(agg_key)].emplace_back(
            std::move(converted_request_value.request));
      }
    }
  }
}

// Adds debug reporting URLs for `bid_state` to `debug_win_report_urls` and
// `debug_loss_report_urls`, if there are any, filling in report URL template
// parameters as needed. The URLs are moved away from `bid_state`.
//
// `winner` points to the BidState associated with the winning bid, if there
// is one.
//
// `signals` are the PostAuctionSignals from the auction `state` was a part of.
//
// `top_level_signals` are the PostAuctionSignals of the top-level auction, if
// the computation is for a component auction, and nullopt otherwise.
void TakeDebugReportUrlsForBidState(
    std::unique_ptr<InterestGroupAuction::BidState>& bid_state,
    const InterestGroupAuction::BidState* winner,
    const InterestGroupAuction::PostAuctionSignals& signals,
    const absl::optional<InterestGroupAuction::PostAuctionSignals>&
        top_level_signals,
    std::vector<GURL>& debug_win_report_urls,
    std::vector<GURL>& debug_loss_report_urls) {
  if (bid_state.get() == winner) {
    if (winner->bidder_debug_win_report_url.has_value()) {
      debug_win_report_urls.emplace_back(
          InterestGroupAuction::FillPostAuctionSignals(
              std::move(winner->bidder_debug_win_report_url).value(), signals));
    }
    if (winner->seller_debug_win_report_url.has_value()) {
      debug_win_report_urls.emplace_back(
          InterestGroupAuction::FillPostAuctionSignals(
              std::move(winner->seller_debug_win_report_url).value(), signals,
              top_level_signals));
    }
    // `top_level_signals` is passed as parameter `signals` for top-level
    // seller.
    if (winner->top_level_seller_debug_win_report_url.has_value()) {
      debug_win_report_urls.emplace_back(
          InterestGroupAuction::FillPostAuctionSignals(
              std::move(winner->top_level_seller_debug_win_report_url).value(),
              top_level_signals.value()));
    }
    return;
  }
  if (bid_state->bidder_debug_loss_report_url.has_value()) {
    // Losing and rejected bidders should not get highest_scoring_other_bid
    // and made_highest_scoring_other_bid signals. (And also the currency
    // bit for those).
    debug_loss_report_urls.emplace_back(
        InterestGroupAuction::FillPostAuctionSignals(
            std::move(bid_state->bidder_debug_loss_report_url).value(),
            InterestGroupAuction::PostAuctionSignals(
                signals.winning_bid, signals.winning_bid_currency,
                signals.made_winning_bid, /*highest_scoring_other_bid=*/0.0,
                /*highest_scoring_other_bid_currency=*/absl::nullopt,
                /*made_highest_scoring_other_bid=*/false),
            /*top_level_signals=*/absl::nullopt, bid_state->reject_reason));
  }
  // TODO(qingxinwu): Add reject reason to seller debug loss report as well.
  if (bid_state->seller_debug_loss_report_url.has_value()) {
    debug_loss_report_urls.emplace_back(
        InterestGroupAuction::FillPostAuctionSignals(
            std::move(bid_state->seller_debug_loss_report_url).value(), signals,
            top_level_signals));
  }
  // `top_level_signals` is passed as parameter `signals` for top-level
  // seller.
  if (bid_state->top_level_seller_debug_loss_report_url.has_value()) {
    debug_loss_report_urls.emplace_back(
        InterestGroupAuction::FillPostAuctionSignals(
            std::move(bid_state->top_level_seller_debug_loss_report_url)
                .value(),
            top_level_signals.value()));
  }
}

// Retrieves the timeout from `buyer_timeouts` associated with `buyer`, if any.
// Used for both `buyer_timeouts` and `buyer_cumulative_timeouts`, stored in
// AuctionConfigs. Callers should use PerBuyerTimeout() and
// PerBuyerCumulativeTimeout() instead, since those apply the timeout limit,
// when applicable.
absl::optional<base::TimeDelta> PerBuyerTimeoutHelper(
    const url::Origin& buyer,
    const blink::AuctionConfig::MaybePromiseBuyerTimeouts& buyer_timeouts) {
  DCHECK(!buyer_timeouts.is_promise());
  const auto& per_buyer_timeouts = buyer_timeouts.value().per_buyer_timeouts;
  if (per_buyer_timeouts.has_value()) {
    auto it = per_buyer_timeouts->find(buyer);
    if (it != per_buyer_timeouts->end()) {
      return it->second;
    }
  }
  const auto& all_buyers_timeout = buyer_timeouts.value().all_buyers_timeout;
  if (all_buyers_timeout.has_value()) {
    return all_buyers_timeout.value();
  }
  return absl::nullopt;
}

absl::optional<base::TimeDelta> PerBuyerTimeout(
    const url::Origin& buyer,
    const blink::AuctionConfig& auction_config) {
  absl::optional<base::TimeDelta> out = PerBuyerTimeoutHelper(
      buyer, auction_config.non_shared_params.buyer_timeouts);
  if (!out) {
    return out;
  }
  return std::min(*out, kMaxPerBuyerTimeout);
}

absl::optional<base::TimeDelta> PerBuyerCumulativeTimeout(
    const url::Origin& buyer,
    const blink::AuctionConfig& auction_config) {
  return PerBuyerTimeoutHelper(
      buyer, auction_config.non_shared_params.buyer_cumulative_timeouts);
}

absl::optional<blink::AdCurrency> PerBuyerCurrency(
    const url::Origin& buyer,
    const blink::AuctionConfig& auction_config) {
  const blink::AuctionConfig::MaybePromiseBuyerCurrencies& buyer_currencies =
      auction_config.non_shared_params.buyer_currencies;
  DCHECK(!buyer_currencies.is_promise());
  const auto& per_buyer_currencies =
      buyer_currencies.value().per_buyer_currencies;
  if (per_buyer_currencies.has_value()) {
    auto it = per_buyer_currencies->find(buyer);
    if (it != per_buyer_currencies->end()) {
      return it->second;
    }
  }
  const auto& all_buyers_currency =
      buyer_currencies.value().all_buyers_currency;
  return all_buyers_currency;  // Maybe nullopt.
}

}  // namespace

InterestGroupAuction::PostAuctionSignals::PostAuctionSignals() = default;

InterestGroupAuction::PostAuctionSignals::PostAuctionSignals(
    double winning_bid,
    absl::optional<blink::AdCurrency> winning_bid_currency,
    bool made_winning_bid)
    : winning_bid(winning_bid),
      winning_bid_currency(std::move(winning_bid_currency)),
      made_winning_bid(made_winning_bid) {}

InterestGroupAuction::PostAuctionSignals::PostAuctionSignals(
    double winning_bid,
    absl::optional<blink::AdCurrency> winning_bid_currency,
    bool made_winning_bid,
    double highest_scoring_other_bid,
    absl::optional<blink::AdCurrency> highest_scoring_other_bid_currency,
    bool made_highest_scoring_other_bid)
    : winning_bid(winning_bid),
      winning_bid_currency(std::move(winning_bid_currency)),
      made_winning_bid(made_winning_bid),
      highest_scoring_other_bid(highest_scoring_other_bid),
      highest_scoring_other_bid_currency(
          std::move(highest_scoring_other_bid_currency)),
      made_highest_scoring_other_bid(made_highest_scoring_other_bid) {}

InterestGroupAuction::PostAuctionSignals::~PostAuctionSignals() = default;

// static
void InterestGroupAuction::PostAuctionSignals::FillWinningBidInfo(
    const url::Origin& owner,
    absl::optional<url::Origin> winner_owner,
    double winning_bid,
    absl::optional<double> winning_bid_in_seller_currency,
    const absl::optional<blink::AdCurrency>& seller_currency,
    bool& out_made_winning_bid,
    double& out_winning_bid,
    absl::optional<blink::AdCurrency>& out_winning_bid_currency) {
  out_made_winning_bid = false;
  if (winner_owner.has_value()) {
    out_made_winning_bid = owner == *winner_owner;
  }

  if (seller_currency.has_value()) {
    out_winning_bid = winning_bid_in_seller_currency.value_or(0.0);
    out_winning_bid_currency = *seller_currency;
  } else {
    out_winning_bid = winning_bid;
    out_winning_bid_currency = absl::nullopt;
  }
}

// static
void InterestGroupAuction::PostAuctionSignals::
    FillRelevantHighestScoringOtherBidInfo(
        const url::Origin& owner,
        absl::optional<url::Origin> highest_scoring_other_bid_owner,
        double highest_scoring_other_bid,
        absl::optional<double> highest_scoring_other_bid_in_seller_currency,
        const absl::optional<blink::AdCurrency>& seller_currency,
        bool& out_made_highest_scoring_other_bid,
        double& out_highest_scoring_other_bid,
        absl::optional<blink::AdCurrency>&
            out_highest_scoring_other_bid_currency) {
  out_made_highest_scoring_other_bid = false;
  if (highest_scoring_other_bid_owner.has_value()) {
    DCHECK_GT(highest_scoring_other_bid, 0);
    out_made_highest_scoring_other_bid =
        owner == highest_scoring_other_bid_owner.value();
  }

  if (seller_currency.has_value()) {
    out_highest_scoring_other_bid =
        highest_scoring_other_bid_in_seller_currency.value_or(0);
    out_highest_scoring_other_bid_currency = *seller_currency;
  } else {
    out_highest_scoring_other_bid = highest_scoring_other_bid;
    out_highest_scoring_other_bid_currency = absl::nullopt;
  }
}

InterestGroupAuction::BidState::PrivateAggregationPhaseKey::
    PrivateAggregationPhaseKey(
        url::Origin reporting_origin,
        PrivateAggregationPhase phase,
        absl::optional<url::Origin> aggregation_coordinator_origin)
    : reporting_origin(reporting_origin),
      phase(phase),
      aggregation_coordinator_origin(aggregation_coordinator_origin) {}

InterestGroupAuction::BidState::PrivateAggregationPhaseKey::
    PrivateAggregationPhaseKey(const PrivateAggregationPhaseKey&) = default;

InterestGroupAuction::BidState::PrivateAggregationPhaseKey&
InterestGroupAuction::BidState::PrivateAggregationPhaseKey::operator=(
    const PrivateAggregationPhaseKey&) = default;

InterestGroupAuction::BidState::PrivateAggregationPhaseKey::
    PrivateAggregationPhaseKey(PrivateAggregationPhaseKey&&) = default;

InterestGroupAuction::BidState::PrivateAggregationPhaseKey&
InterestGroupAuction::BidState::PrivateAggregationPhaseKey::operator=(
    PrivateAggregationPhaseKey&&) = default;

InterestGroupAuction::BidState::PrivateAggregationPhaseKey::
    ~PrivateAggregationPhaseKey() = default;

InterestGroupAuction::BidState::~BidState() {
  if (trace_id.has_value()) {
    EndTracing();
  }
  if (trace_id_for_kanon_scoring.has_value()) {
    EndTracingKAnonScoring();
  }
}

InterestGroupAuction::BidState::BidState(BidState&&) = default;

InterestGroupAuction::BidState::BidState(
    const SingleStorageInterestGroup&& bidder)
    : bidder(std::move(bidder)) {}

void InterestGroupAuction::BidState::BeginTracing() {
  DCHECK(!trace_id.has_value());

  trace_id = base::trace_event::GetNextGlobalTraceId();

  const blink::InterestGroup& interest_group = bidder->interest_group;
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2("fledge", "bid", *trace_id, "bidding_url",
                                    interest_group.bidding_url,
                                    "interest_group_name", interest_group.name);
}

void InterestGroupAuction::BidState::EndTracing() {
  DCHECK(trace_id.has_value());

  TRACE_EVENT_NESTABLE_ASYNC_END0("fledge", "bid", *trace_id);
  trace_id = absl::nullopt;
}

void InterestGroupAuction::BidState::BeginTracingKAnonScoring() {
  DCHECK(!trace_id_for_kanon_scoring.has_value());

  trace_id_for_kanon_scoring = base::trace_event::GetNextGlobalTraceId();

  const blink::InterestGroup& interest_group = bidder->interest_group;
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN2("fledge", "score_kanon_enforced_ad",
                                    *trace_id_for_kanon_scoring, "bidding_url",
                                    interest_group.bidding_url,
                                    "interest_group_name", interest_group.name);
}

void InterestGroupAuction::BidState::EndTracingKAnonScoring() {
  DCHECK(trace_id_for_kanon_scoring.has_value());

  TRACE_EVENT_NESTABLE_ASYNC_END0("fledge", "score_kanon_enforced_ad",
                                  *trace_id_for_kanon_scoring);
  trace_id_for_kanon_scoring = absl::nullopt;
}

InterestGroupAuction::Bid::Bid(
    BidRole bid_role,
    std::string ad_metadata,
    double bid,
    absl::optional<blink::AdCurrency> bid_currency,
    absl::optional<double> ad_cost,
    blink::AdDescriptor ad_descriptor,
    std::vector<blink::AdDescriptor> ad_component_descriptors,
    absl::optional<uint16_t> modeling_signals,
    base::TimeDelta bid_duration,
    absl::optional<uint32_t> bidding_signals_data_version,
    const blink::InterestGroup::Ad* bid_ad,
    BidState* bid_state,
    InterestGroupAuction* auction)
    : bid_role(bid_role),
      ad_metadata(std::move(ad_metadata)),
      bid(bid),
      bid_currency(std::move(bid_currency)),
      ad_cost(std::move(ad_cost)),
      ad_descriptor(std::move(ad_descriptor)),
      ad_component_descriptors(std::move(ad_component_descriptors)),
      modeling_signals(modeling_signals),
      bid_duration(bid_duration),
      bidding_signals_data_version(bidding_signals_data_version),
      interest_group(&bid_state->bidder->interest_group),
      bid_ad(bid_ad),
      bid_state(bid_state),
      auction(auction) {
  DCHECK(IsValidBid(bid));
}

InterestGroupAuction::Bid::Bid(Bid&) = default;

InterestGroupAuction::Bid::~Bid() = default;

std::vector<GURL> InterestGroupAuction::Bid::GetAdComponentUrls() const {
  std::vector<GURL> ad_component_urls;
  ad_component_urls.reserve(ad_component_descriptors.size());
  base::ranges::transform(
      ad_component_descriptors, std::back_inserter(ad_component_urls),
      [](const blink::AdDescriptor& ad_component_descriptor) {
        return ad_component_descriptor.url;
      });
  return ad_component_urls;
}

InterestGroupAuction::ScoredBid::ScoredBid(
    double score,
    absl::optional<uint32_t> scoring_signals_data_version,
    std::unique_ptr<Bid> bid,
    absl::optional<double> bid_in_seller_currency,
    auction_worklet::mojom::ComponentAuctionModifiedBidParamsPtr
        component_auction_modified_bid_params)
    : score(score),
      scoring_signals_data_version(scoring_signals_data_version),
      bid(std::move(bid)),
      bid_in_seller_currency(std::move(bid_in_seller_currency)),
      component_auction_modified_bid_params(
          std::move(component_auction_modified_bid_params)) {
  DCHECK_GT(score, 0);
}

InterestGroupAuction::ScoredBid::~ScoredBid() = default;

// Every interest group owner participating in an auctions gets its own
// BuyerHelper. The class is responsible for handing buyer-side calls during
// the bidding/scoring phase.
//
// In particular, it handles:
// * Sorting interest groups that share a bidder by priority.
// * Deciding which interest groups get to bid.
// * Creating BidderWorklets.
// * Calling BidderWorklet::GenerateBid().
// * Tracking how many interest groups the buyer owns that still need to
// bid.
class InterestGroupAuction::BuyerHelper
    : public auction_worklet::mojom::GenerateBidClient {
 public:
  // `auction` is expected to own the BuyerHelper, and therefore outlive it.
  BuyerHelper(InterestGroupAuction* auction,
              std::vector<SingleStorageInterestGroup>&& interest_groups)
      : auction_(auction), owner_(interest_groups[0]->interest_group.owner) {
    DCHECK(!interest_groups.empty());

    // Move interest groups to `bid_states_` and update priorities using
    // `priority_vector`, if present. Delete groups where the calculation
    // results in a priority < 0.
    for (SingleStorageInterestGroup& bidder : interest_groups) {
      double priority = bidder->interest_group.priority;

      if (bidder->interest_group.priority_vector &&
          !bidder->interest_group.priority_vector->empty()) {
        priority = CalculateInterestGroupPriority(
            *auction_->config_, *bidder, auction_->auction_start_time_,
            *bidder->interest_group.priority_vector);
        // Only filter interest groups with priority < 0 if the negative
        // priority is the result of a `priority_vector` multiplication.
        //
        // TODO(mmenke): If we can make this the standard behavior for the
        // `priority` field as well, the API would be more consistent.
        if (priority < 0) {
          auction_->auction_metrics_recorder_
              ->RecordBidFilteredDuringInterestGroupLoad();
          continue;
        }
      }

      if (bidder->interest_group.enable_bidding_signals_prioritization) {
        enable_bidding_signals_prioritization_ = true;
      }
      auto state = std::make_unique<BidState>(std::move(bidder));
      state->calculated_priority = priority;
      bid_states_.emplace_back(std::move(state));
    }

    size_limit_ = auction_->config_->non_shared_params.all_buyers_group_limit;
    const auto limit_iter =
        auction_->config_->non_shared_params.per_buyer_group_limits.find(
            owner_);
    if (limit_iter !=
        auction_->config_->non_shared_params.per_buyer_group_limits.cend()) {
      size_limit_ = static_cast<size_t>(limit_iter->second);
    }
    size_limit_ = std::min(bid_states_.size(), size_limit_);
    if (size_limit_ == 0) {
      bid_states_.clear();
      return;
    }

    if (!enable_bidding_signals_prioritization_) {
      ApplySizeLimitAndSort();
    } else {
      // When not applying the size limit yet, still sort by priority, since
      // worklets preserve the order they see requests in. This allows higher
      // priority interest groups will get to bid first, and also groups
      // interest groups by the origin they joined to potentially improve
      // Javscript context reuse.
      SortByPriorityAndGroupByJoinOrigin();
    }

    // Figure out which BidState is last for each key, as it will be responsible
    // for sending out the trusted bidder signals request.
    std::set<AuctionWorkletManager::WorkletKey> seen_keys;
    for (auto it = bid_states_.rbegin(); it != bid_states_.rend(); ++it) {
      std::unique_ptr<BidState>& bid_state = *it;
      auto [iter, success] =
          seen_keys.insert(auction_->BidderWorkletKey(*bid_state));
      bid_state->send_pending_trusted_signals_after_generate_bid = success;
    }
  }

  ~BuyerHelper() override = default;

  // Requests bidder worklets and starts generating bids. May generate no bids,
  // 1 bid, or multiple bids. Invokes owning InterestGroupAuction's
  // ScoreBidIfReady() for each bid generated, and OnBidderDone() once all bids
  // have been generated. OnBidderDone() is always invoked asynchronously.
  void StartGeneratingBids() {
    DCHECK(!bid_states_.empty());
    DCHECK_EQ(0, num_outstanding_bids_);
    num_outstanding_bids_ = bid_states_.size();
    num_outstanding_bidding_signals_received_calls_ = num_outstanding_bids_;
    start_generating_bids_time_ = base::TimeTicks::Now();

    // Request processes for all bidder worklets.
    for (auto& bid_state : bid_states_) {
      auto worklet_key = auction_->BidderWorkletKey(*bid_state);
      auction_->auction_metrics_recorder_->ReportBidderWorkletKey(worklet_key);
      auction_->auction_worklet_manager_->RequestWorkletByKey(
          worklet_key,
          base::BindOnce(&BuyerHelper::OnBidderWorkletReceived,
                         base::Unretained(this), bid_state.get()),
          base::BindOnce(&BuyerHelper::OnBidderWorkletGenerateBidFatalError,
                         base::Unretained(this), bid_state.get()),
          bid_state->worklet_handle);
    }
  }

  // auction_worklet::mojom::GenerateBidClient implementation:

  void OnBiddingSignalsReceived(
      const base::flat_map<std::string, double>& priority_vector,
      base::TimeDelta trusted_signals_fetch_latency,
      base::OnceClosure resume_generate_bid_callback) override {
    BidState* state = generate_bid_client_receiver_set_.current_context();
    const blink::InterestGroup& interest_group = state->bidder->interest_group;
    state->pa_timings(PrivateAggregationPhase::kBidder).signals_fetch_time =
        trusted_signals_fetch_latency;
    auction_->ReportTrustedSignalsFetchLatency(interest_group,
                                               trusted_signals_fetch_latency);
    absl::optional<double> new_priority;
    if (!priority_vector.empty()) {
      new_priority = CalculateInterestGroupPriority(
          *auction_->config_, *(state->bidder), auction_->auction_start_time_,
          priority_vector,
          (interest_group.priority_vector &&
           !interest_group.priority_vector->empty())
              ? state->calculated_priority
              : absl::optional<double>());
      if (*new_priority < 0) {
        auction_->auction_metrics_recorder_
            ->RecordBidFilteredDuringReprioritization();
      }
    }
    OnBiddingSignalsReceivedInternal(state, new_priority,
                                     std::move(resume_generate_bid_callback));
  }

  void OnGenerateBidComplete(
      auction_worklet::mojom::BidderWorkletBidPtr mojo_bid,
      auction_worklet::mojom::BidderWorkletKAnonEnforcedBidPtr mojo_kanon_bid,
      uint32_t bidding_signals_data_version,
      bool has_bidding_signals_data_version,
      const absl::optional<GURL>& debug_loss_report_url,
      const absl::optional<GURL>& debug_win_report_url,
      double set_priority,
      bool has_set_priority,
      base::flat_map<std::string,
                     auction_worklet::mojom::PrioritySignalsDoublePtr>
          update_priority_signals_overrides,
      PrivateAggregationRequests pa_requests,
      PrivateAggregationRequests non_kanon_pa_requests,
      base::TimeDelta bidding_latency,
      auction_worklet::mojom::GenerateBidDependencyLatenciesPtr
          generate_bid_dependency_latencies,
      auction_worklet::mojom::RejectReason reject_reason,
      const std::vector<std::string>& errors) override {
    BidState* state = generate_bid_client_receiver_set_.current_context();
    const blink::InterestGroup& interest_group = state->bidder->interest_group;
    state->pa_timings(PrivateAggregationPhase::kBidder).script_run_time =
        bidding_latency;
    auction_->ReportBiddingLatency(interest_group, bidding_latency);

    // This is intentionally recorded here as opposed to in
    // OnGenerateBidCompleteInternal in order to exclude bids that were
    // filtered during reprioritization. It also excludes those bids that
    // encountered a fatal error, except for timeouts; those we record to this
    // metric separately and explicitly in OnTimeout.
    auction_->auction_metrics_recorder_->RecordBidForOneInterestGroupLatency(
        base::TimeTicks::Now() - start_generating_bids_time_);
    auction_->auction_metrics_recorder_->RecordGenerateBidDependencyLatencies(
        *generate_bid_dependency_latencies);
    OnGenerateBidCompleteInternal(
        state, std::move(mojo_bid), std::move(mojo_kanon_bid),
        bidding_signals_data_version, has_bidding_signals_data_version,
        debug_loss_report_url, debug_win_report_url, set_priority,
        has_set_priority, std::move(update_priority_signals_overrides),
        std::move(pa_requests), std::move(non_kanon_pa_requests), reject_reason,
        errors);
  }

  // Closes all Mojo pipes, releases all weak pointers, and stops the timeout
  // timer.
  void ClosePipes() {
    weak_ptr_factory_.InvalidateWeakPtrs();

    for (auto& bid_state : bid_states_) {
      CloseBidStatePipes(*bid_state);
    }
    // No need to clear `generate_bid_client_receiver_set_`, since
    // CloseBidStatePipes() should take care of that.
    DCHECK(generate_bid_client_receiver_set_.empty());

    // Need to stop the timer - this is called on completion and on certain
    // errors. Don't want the timer to trigger anything after there's been a
    // failure already.
    cumulative_buyer_timeout_timer_.Stop();
  }

  // Returns true if this buyer has any interest groups that will potentially
  // bid in an auction -- that is, not all interest groups have been filtered
  // out.
  bool has_potential_bidder() const { return !bid_states_.empty(); }

  size_t num_potential_bidders() const { return bid_states_.size(); }

  const url::Origin& owner() const { return owner_; }

  void GetInterestGroupsThatBidAndReportBidCounts(
      blink::InterestGroupSet& interest_groups) const {
    size_t bid_count = 0;
    for (const auto& bid_state : bid_states_) {
      if (bid_state->made_bid) {
        interest_groups.emplace(bid_state->bidder->interest_group.owner,
                                bid_state->bidder->interest_group.name);
        auction_->interest_group_manager_->NotifyInterestGroupAccessed(
            InterestGroupManagerImpl::InterestGroupObserver::kBid,
            bid_state->bidder->interest_group.owner,
            bid_state->bidder->interest_group.name);
        bid_count++;
      }
    }
    for (const auto& bid_state : bid_states_) {
      if (auction_->ReportBidCount(bid_state->bidder->interest_group,
                                   bid_count)) {
        break;
      }
    }
  }

  // Adds debug reporting URLs to `debug_win_report_urls` and
  // `debug_loss_report_urls`, if there are any, filling in report URL template
  // parameters as needed.
  //
  // `winner` points to the BidState associated with the winning bid, if there
  // is one. If it's not a BidState managed by `this`, it has no effect.
  //
  // `signals` are the PostAuctionSignals from the auction `this` was a part of.
  //
  // `top_level_signals` are the PostAuctionSignals of the top-level auction, if
  // this is a component auction, and nullopt otherwise.
  void TakeDebugReportUrls(
      const BidState* winner,
      const PostAuctionSignals& signals,
      const absl::optional<PostAuctionSignals>& top_level_signals,
      std::vector<GURL>& debug_win_report_urls,
      std::vector<GURL>& debug_loss_report_urls) {
    for (std::unique_ptr<BidState>& bid_state : bid_states_) {
      TakeDebugReportUrlsForBidState(bid_state, winner, signals,
                                     top_level_signals, debug_win_report_urls,
                                     debug_loss_report_urls);
    }
  }

  // Returns private aggregation requests, if there are any. Calculate
  // bucket/value using `signals` as needed.
  //
  // `winner` points to the BidState associated with the winning bid, if there
  // is one. If it's not a BidState managed by `this`, it has no effect.
  //
  // `signals` are the PostAuctionSignals from the auction `this` was a part of.
  void TakePrivateAggregationRequests(
      const BidState* winner,
      const BidState* non_kanon_winner,
      const PostAuctionSignals& signals,
      const absl::optional<PostAuctionSignals>& top_level_signals,
      std::map<InterestGroupAuctionReporter::PrivateAggregationKey,
               PrivateAggregationRequests>&
          private_aggregation_requests_reserved,
      std::map<std::string, PrivateAggregationRequests>&
          private_aggregation_requests_non_reserved) {
    for (std::unique_ptr<BidState>& state : bid_states_) {
      TakePrivateAggregationRequestsForBidState(
          state, /*is_component_auction=*/auction_->parent_, winner,
          non_kanon_winner, signals, top_level_signals,
          private_aggregation_requests_reserved,
          private_aggregation_requests_non_reserved);
    }
  }

  void NotifyConfigPromisesResolved() {
    DCHECK(auction_->config_promises_resolved_);

    NotifyConfigDependencyResolved();
  }

  // Called when promises resolve, or directFromSellerSignalsHeaderAdSlot
  // finishes parsing and finding a matching ad slot response.
  void NotifyConfigDependencyResolved() {
    // If there are no outstanding bids, just do nothing. It's safest to exit
    // early in the case that bidder worklet process crashed or failed to fetch
    // the necessary script(s) before all config promises were resolved, rather
    // than rely on everything handling that case correctly.
    if (num_outstanding_bids_ == 0) {
      return;
    }

    MaybeStartCumulativeTimeoutTimer();

    for (const auto& bid_state : bid_states_) {
      FinishGenerateBidIfReady(bid_state.get());
    }
  }

  std::unique_ptr<Bid> TryToCreateBidFromServerResponse(
      InterestGroupAuction::Bid::BidRole bid_role,
      double bid,
      blink::AdDescriptor ad_descriptor,
      std::vector<blink::AdDescriptor> ad_component_descriptors) {
    CHECK_EQ(1u, bid_states_.size());
    BidState* bid_state = bid_states_[0].get();
    bid_state->made_bid = true;

    auction_worklet::mojom::KAnonymityBidMode kanon_mode =
        auction_->kanon_mode();
    bid_state->kanon_keys = ComputeKAnon(bid_state->bidder, kanon_mode);

    // Check bid validity.
    const blink::InterestGroup& interest_group =
        bid_state->bidder->interest_group;

    // 1. Ads must be in the interest group (at specified k-anon level)
    const blink::InterestGroup::Ad* matching_ad = FindMatchingAd(
        *interest_group.ads, bid_state->kanon_keys, interest_group, bid_role,
        /*is_component_ad=*/false, ad_descriptor);
    if (!matching_ad) {
      // Bid render url must match the interest group.
      return nullptr;
    }
    for (const auto& ad_component_descriptor : ad_component_descriptors) {
      const blink::InterestGroup::Ad* matching_ad_component = FindMatchingAd(
          *interest_group.ad_components, bid_state->kanon_keys, interest_group,
          bid_role, /*is_component_ad=*/true, ad_component_descriptor);
      if (!matching_ad_component) {
        // Bid ad components must match the interest group.
        return nullptr;
      }
    }

    // 2. Reporting URLs must be okay
    // TODO(1457931): Implement reporting

    return std::make_unique<Bid>(
        bid_role, matching_ad->metadata.value_or("null"), bid,
        /*bid_currency=*/absl::nullopt,
        /*ad_cost=*/absl::nullopt, std::move(ad_descriptor),
        std::move(ad_component_descriptors),
        /*modeling_signals=*/absl::nullopt,
        /*bid_duration=*/base::Seconds(0),
        /*bidding_signals_data_version=*/absl::nullopt, matching_ad, bid_state,
        auction_);
  }

 private:
  // Sorts by descending priority, also grouping entries within each priority
  // band to permit context reuse if the executionMode allows it.
  void SortByPriorityAndGroupByJoinOrigin() {
    std::sort(bid_states_.begin(), bid_states_.end(),
              BidStatesDescByPriorityAndGroupByJoinOrigin());
  }

  // Applies `size_limit_`, removing the lowest priority interest groups first,
  // and then sorts the remaining interest groups.
  void ApplySizeLimitAndSort() {
    SortByPriorityAndGroupByJoinOrigin();

    // Randomize order of interest groups with lowest allowed priority. This
    // effectively performs a random sample among interest groups with the
    // same priority.
    double min_priority = bid_states_[size_limit_ - 1]->calculated_priority;
    auto rand_begin = std::lower_bound(bid_states_.begin(), bid_states_.end(),
                                       min_priority, BidStatesDescByPriority());
    auto rand_end = std::upper_bound(rand_begin, bid_states_.end(),
                                     min_priority, BidStatesDescByPriority());
    base::RandomShuffle(rand_begin, rand_end);
    for (size_t i = size_limit_; i < bid_states_.size(); ++i) {
      // Need to close pipes explicitly, as the state's GenerateBidClientPipe is
      // owned by `generate_bid_client_receiver_set_`, deleting the bid isn't
      // sufficient.
      CloseBidStatePipes(*bid_states_[i]);
    }
    auction_->auction_metrics_recorder_->RecordBidsFilteredByPerBuyerLimits(
        bid_states_.size() - size_limit_);
    bid_states_.resize(size_limit_);

    // Restore the origin grouping within lowest priority band among the
    // subset that was kept after shuffling.
    std::sort(rand_begin, bid_states_.end(),
              BidStatesDescByPriorityAndGroupByJoinOrigin());
  }

  // Called when the `bid_state` BidderWorklet crashes or fails to load.
  // Invokes OnGenerateBidCompleteInternal() for the worklet with a failure.
  void OnBidderWorkletGenerateBidFatalError(
      BidState* bid_state,
      AuctionWorkletManager::FatalErrorType fatal_error_type,
      const std::vector<std::string>& errors) {
    auction_->auction_metrics_recorder_
        ->RecordBidAbortedByBidderWorkletFatalError();

    // Add error(s) directly to error list.
    if (fatal_error_type ==
        AuctionWorkletManager::FatalErrorType::kWorkletCrash) {
      // Ignore default error message in case of crash. Instead, use a more
      // specific one.
      OnFatalError(
          bid_state,
          {base::StrCat({bid_state->bidder->interest_group.bidding_url->spec(),
                         " crashed while trying to run generateBid()."})});
    } else {
      OnFatalError(bid_state, errors);
    }
  }

  // Called in the case of a fatal error that prevents the `bid_state` worklet
  // from bidding.
  void OnFatalError(BidState* bid_state, std::vector<std::string> errors) {
    auction_->errors_.insert(auction_->errors_.end(),
                             std::make_move_iterator(errors.begin()),
                             std::make_move_iterator(errors.end()));

    // If waiting on bidding signals, the bidder needs to be removed in the same
    // way as if it had a new negative priority value, so reuse that logic. The
    // bidder needs to be removed, and the remaining bidders potentially need to
    // have the size limit applied and have their generate bid calls resumed, if
    // they were waiting on this bidder. Therefore, can't just call
    // OnGenerateBidCompleteInternal().
    if (!bid_state->bidding_signals_received) {
      OnBiddingSignalsReceivedInternal(bid_state,
                                       /*new_priority=*/-1,
                                       base::OnceClosure());
      return;
    }

    // Otherwise call OnGenerateBidCompleteInternal() directly to complete the
    // bid. This will also result in closing pipes. If
    // `enable_bidding_signals_prioritization_` is true, the closed pipe will be
    // noticed, and it will be removed before applying the priority filter.
    OnGenerateBidCompleteInternal(
        bid_state,
        /*mojo_bid=*/auction_worklet::mojom::BidderWorkletBidPtr(),
        /*mojo_kanon_bid=*/
        auction_worklet::mojom::BidderWorkletKAnonEnforcedBidPtr(),
        /*bidding_signals_data_version=*/0,
        /*has_bidding_signals_data_version=*/false,
        /*debug_loss_report_url=*/absl::nullopt,
        /*debug_win_report_url=*/absl::nullopt,
        /*set_priority=*/0,
        /*has_set_priority=*/false,
        /*update_priority_signals_overrides=*/{},
        /*pa_requests=*/{},
        /*non_kanon_pa_requests=*/{},
        /*reject_reason=*/auction_worklet::mojom::RejectReason::kNotAvailable,
        /*errors=*/{});
  }

  base::flat_map<std::string, bool> ComputeKAnon(
      const SingleStorageInterestGroup& storage_interest_group,
      auction_worklet::mojom::KAnonymityBidMode kanon_mode) {
    if (kanon_mode == auction_worklet::mojom::KAnonymityBidMode::kNone) {
      return {};
    }

    // k-anon cache is always checked against the same time, to avoid weird
    // behavior of validity changing in the middle of the auction.
    base::Time start_time = auction_->auction_start_time_;

    std::vector<std::pair<std::string, bool>> kanon_entries;
    for (const auto& ad_kanon : storage_interest_group->bidding_ads_kanon) {
      if (IsKAnonymous(ad_kanon, start_time)) {
        kanon_entries.emplace_back(ad_kanon.key, true);
      }
    }
    for (const auto& component_ad_kanon :
         storage_interest_group->component_ads_kanon) {
      if (IsKAnonymous(component_ad_kanon, start_time)) {
        kanon_entries.emplace_back(component_ad_kanon.key, true);
      }
    }
    return base::flat_map<std::string, bool>(std::move(kanon_entries));
  }

  // Invoked whenever the AuctionWorkletManager has provided a BidderWorket
  // for the bidder identified by `bid_state`. Starts generating a bid.
  void OnBidderWorkletReceived(BidState* bid_state) {
    if (!bidder_process_received_) {
      // All bidder worklets are expected to be loaded in the same process, so
      // as soon as any worklet has been received, can set this to true.
      bidder_process_received_ = true;
      MaybeStartCumulativeTimeoutTimer();
    }

    const blink::InterestGroup& interest_group =
        bid_state->bidder->interest_group;

    bid_state->BeginTracing();
    TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("fledge", "bidder_worklet_generate_bid",
                                      *bid_state->trace_id);

    mojo::PendingAssociatedRemote<auction_worklet::mojom::GenerateBidClient>
        pending_remote;
    bid_state->generate_bid_client_receiver_id =
        generate_bid_client_receiver_set_.Add(
            this, pending_remote.InitWithNewEndpointAndPassReceiver(),
            bid_state);
    auction_worklet::mojom::KAnonymityBidMode kanon_mode =
        auction_->kanon_mode();
    bid_state->kanon_keys = ComputeKAnon(bid_state->bidder, kanon_mode);
    SubresourceUrlBuilder* url_builder =
        auction_->SubresourceUrlBuilderIfReady();
    if (url_builder) {
      bid_state->worklet_handle->AuthorizeSubresourceUrls(*url_builder);
      bid_state->handled_direct_from_seller_signals_in_begin_generate_bid =
          true;
    }
    bid_state->worklet_handle->GetBidderWorklet()->BeginGenerateBid(
        auction_worklet::mojom::BidderWorkletNonSharedParams::New(
            interest_group.name,
            interest_group.enable_bidding_signals_prioritization,
            interest_group.priority_vector, interest_group.execution_mode,
            interest_group.update_url,
            interest_group.trusted_bidding_signals_keys,
            interest_group.user_bidding_signals, interest_group.ads,
            interest_group.ad_components,
            KAnonKeysToMojom(bid_state->kanon_keys)),
        kanon_mode, bid_state->bidder->joining_origin,
        GetDirectFromSellerPerBuyerSignals(
            url_builder, bid_state->bidder->interest_group.owner),
        GetDirectFromSellerAuctionSignals(url_builder),
        auction_->config_->seller,
        auction_->parent_ ? auction_->parent_->config_->seller
                          : absl::optional<url::Origin>(),
        (base::Time::Now() - bid_state->bidder->join_time)
            .RoundToMultiple(base::Milliseconds(100)),
        bid_state->bidder->bidding_browser_signals.Clone(),
        auction_->auction_start_time_, auction_->RequestedAdSize(),
        *bid_state->trace_id, std::move(pending_remote),
        bid_state->bid_finalizer.BindNewEndpointAndPassReceiver());

    // TODO(morlovich): This should arguably be merged into BeginGenerateBid
    // for footprint; check how testable that would be.
    if (bid_state->send_pending_trusted_signals_after_generate_bid) {
      bid_state->worklet_handle->GetBidderWorklet()
          ->SendPendingSignalsRequests();
    }

    FinishGenerateBidIfReady(bid_state);
  }

  void FinishGenerateBidIfReady(BidState* bid_state) {
    if (!auction_->config_promises_resolved_ ||
        auction_->direct_from_seller_signals_header_ad_slot_pending_) {
      return;
    }

    if (!bid_state->bid_finalizer.is_bound()) {
      // This can happen if the promise resolves while the worklet process is
      // still being launched.
      return;
    }

    SubresourceUrlBuilder* url_builder =
        auction_->SubresourceUrlBuilderIfReady();
    if (url_builder) {
      if (bid_state->handled_direct_from_seller_signals_in_begin_generate_bid) {
        // Don't provide direct-from-seller info to FinishGenerateBid below
        // since we already provided it to BeginGenerateBid.
        url_builder = nullptr;
      } else {
        bid_state->worklet_handle->AuthorizeSubresourceUrls(*url_builder);
      }
    }
    bid_state->bid_finalizer->FinishGenerateBid(
        auction_->config_->non_shared_params.auction_signals.value(),
        GetPerBuyerSignals(*auction_->config_,
                           bid_state->bidder->interest_group.owner),
        PerBuyerTimeout(owner_, *auction_->config_),
        PerBuyerCurrency(owner_, *auction_->config_),
        GetDirectFromSellerPerBuyerSignals(
            url_builder, bid_state->bidder->interest_group.owner),
        GetDirectFromSellerPerBuyerSignalsHeaderAdSlot(
            *auction_->direct_from_seller_signals_header_ad_slot(),
            bid_state->bidder->interest_group.owner),
        GetDirectFromSellerAuctionSignals(url_builder),
        GetDirectFromSellerAuctionSignalsHeaderAdSlot(
            *auction_->direct_from_seller_signals_header_ad_slot()));
    bid_state->bid_finalizer.reset();
  }

  // Invoked when OnBiddingSignalsReceived() has been called for `state`, or
  // with a negative priority when the worklet process has an error, or the
  // buyer reaches their cumulative timeout, and is still waiting on the
  // OnBiddingSignalsReceived() invocation.
  void OnBiddingSignalsReceivedInternal(
      BidState* state,
      absl::optional<double> new_priority,
      base::OnceClosure resume_generate_bid_callback) {
    DCHECK(!state->bidding_signals_received);
    DCHECK_GT(num_outstanding_bids_, 0);
    DCHECK_GT(num_outstanding_bidding_signals_received_calls_, 0);
    // `resume_generate_bid_callback` must be non-null except when invoked with
    // a negative `net_priority` on worklet error.
    DCHECK(resume_generate_bid_callback || *new_priority < 0);

    state->bidding_signals_received = true;
    --num_outstanding_bidding_signals_received_calls_;

    // If `new_priority` has a value and is negative, need to record the bidder
    // as no longer participating in the auction and cancel bid generation.
    bool bid_filtered = new_priority.has_value() && *new_priority < 0;
    UMA_HISTOGRAM_BOOLEAN("Ads.InterestGroup.Auction.BidFiltered",
                          bid_filtered);
    if (bid_filtered) {
      // Record if there are other bidders, as if there are not, the next call
      // may delete `this`.
      bool other_bidders = (num_outstanding_bids_ > 1);

      // If the result of applying the filter is negative, complete the bid
      // with OnGenerateBidCompleteInternal(), which will close the relevant
      // pipes and abort bid generation.
      OnGenerateBidCompleteInternal(
          state, /*mojo_bid=*/auction_worklet::mojom::BidderWorkletBidPtr(),
          /*mojo_kanon_bid=*/
          auction_worklet::mojom::BidderWorkletKAnonEnforcedBidPtr(),
          /*bidding_signals_data_version=*/0,
          /*has_bidding_signals_data_version=*/false,
          /*debug_loss_report_url=*/absl::nullopt,
          /*debug_win_report_url=*/absl::nullopt,
          /*set_priority=*/0,
          /*has_set_priority=*/false,
          /*update_priority_signals_overrides=*/{},
          /*pa_requests=*/{},
          /*non_kanon_pa_requests=*/{},
          /*reject_reason=*/auction_worklet::mojom::RejectReason::kNotAvailable,
          /*errors=*/{});
      // If this was the last bidder, and it was filtered out, there's nothing
      // else to do, and `this` may have already been deleted.
      if (!other_bidders) {
        return;
      }

      // If bidding_signals_prioritization is not enabled, there's also
      // nothing else to do - no other bidders were blocked on the bidder's
      // OnBiddingSignalsReceived() call.
      if (!enable_bidding_signals_prioritization_) {
        return;
      }
    } else {
      if (new_priority.has_value()) {
        state->calculated_priority = *new_priority;
      }
      // Otherwise, invoke the callback to proceed to generate a bid, if don't
      // need to prioritize / filter based on number of interest groups.
      if (!enable_bidding_signals_prioritization_) {
        std::move(resume_generate_bid_callback).Run();
        return;
      }

      state->resume_generate_bid_callback =
          std::move(resume_generate_bid_callback);
    }

    // Check if there are any outstanding OnBiddingSignalsReceived() calls. If
    // so, need to sort interest groups by priority resume pending generate bid
    // calls.
    DCHECK(enable_bidding_signals_prioritization_);
    if (num_outstanding_bidding_signals_received_calls_ > 0) {
      return;
    }

    // Remove Bid states that were filtered out due to having negative new
    // priorities, as ApplySizeLimitAndSort() assumes all bidders are still
    // potentially capable of generating bids. Do these all at once to avoid
    // repeatedly searching for bid states that had negative priority vector
    // multiplication results, each time a priority vector is received.
    for (size_t i = 0; i < bid_states_.size();) {
      // Removing a bid is guaranteed to destroy the worklet handle, though not
      // necessarily the `resume_generate_bid_callback` (in particular,
      // OnBidderWorkletGenerateBidFatalError() calls OnGenerateBidInternal() if
      // a worklet with a `resume_generate_bid_callback` already set crashes,
      // but does not clear `resume_generate_bid_callback`, since doing so
      // directly without closing the pipe first will DCHECK).
      if (!bid_states_[i]->worklet_handle) {
        // The GenerateBidClient pipe should also have been closed.
        DCHECK(!bid_states_[i]->generate_bid_client_receiver_id);
        // std::swap() instead of std::move() because self-move isn't guaranteed
        // to work.
        std::swap(bid_states_[i], bid_states_.back());
        bid_states_.pop_back();
        size_limit_ = std::min(size_limit_, bid_states_.size());
        continue;
      }
      DCHECK(bid_states_[i]->resume_generate_bid_callback);
      ++i;
    }

    // The above loop should have deleted any bid states not accounted for in
    // `num_outstanding_bids_`.
    DCHECK_EQ(static_cast<size_t>(num_outstanding_bids_), bid_states_.size());

    ApplySizeLimitAndSort();

    // Update `num_outstanding_bids_` to reflect the remaining number of pending
    // bids, after applying the size limit.
    num_outstanding_bids_ = bid_states_.size();

    // Let all generate bid calls proceed.
    for (auto& pending_state : bid_states_) {
      std::move(pending_state->resume_generate_bid_callback).Run();
    }
  }

  // Called once a bid has been generated, or has failed to be generated.
  // Releases the BidderWorklet handle and instructs the SellerWorklet to
  // start scoring the bid, if there is one.
  void OnGenerateBidCompleteInternal(
      BidState* state,
      auction_worklet::mojom::BidderWorkletBidPtr mojo_bid,
      auction_worklet::mojom::BidderWorkletKAnonEnforcedBidPtr mojo_kanon_bid,
      uint32_t bidding_signals_data_version,
      bool has_bidding_signals_data_version,
      const absl::optional<GURL>& debug_loss_report_url,
      const absl::optional<GURL>& debug_win_report_url,
      double set_priority,
      bool has_set_priority,
      base::flat_map<std::string,
                     auction_worklet::mojom::PrioritySignalsDoublePtr>
          update_priority_signals_overrides,
      PrivateAggregationRequests pa_requests,
      PrivateAggregationRequests non_kanon_pa_requests,
      auction_worklet::mojom::RejectReason reject_reason,
      const std::vector<std::string>& errors) {
    DCHECK(!state->made_bid);
    DCHECK_GT(num_outstanding_bids_, 0);

    TRACE_EVENT_NESTABLE_ASYNC_END0("fledge", "bidder_worklet_generate_bid",
                                    *state->trace_id);

    const blink::InterestGroup& interest_group = state->bidder->interest_group;
    absl::optional<uint32_t> maybe_bidding_signals_data_version;
    if (has_bidding_signals_data_version) {
      maybe_bidding_signals_data_version = bidding_signals_data_version;
    }

    if (has_set_priority) {
      auction_->interest_group_manager_->SetInterestGroupPriority(
          blink::InterestGroupKey(interest_group.owner, interest_group.name),
          set_priority);
    }

    if (!update_priority_signals_overrides.empty()) {
      // Reject infinite values. The worklet code should prevent this, but the
      // process may be compromised. This is largely preventing the owner from
      // messing up its own prioritization function, but there could be issues
      // around serializing infinite values to persist to disk as well.
      //
      // Note that the data received here has no effect on the result of the
      // auction, so just reject the data and continue with the auction to keep
      // the code simple.
      if (base::ranges::any_of(
              update_priority_signals_overrides, [](const auto& pair) {
                return pair.second && !std::isfinite(pair.second->value);
              })) {
        generate_bid_client_receiver_set_.ReportBadMessage(
            "Invalid priority signals overrides");
      } else {
        auction_->interest_group_manager_->UpdateInterestGroupPriorityOverrides(
            blink::InterestGroupKey(interest_group.owner, interest_group.name),
            std::move(update_priority_signals_overrides));
      }
    }

    // Validate `mojo_kanon_bid` coming in from the less-trusted worklet
    // process; k-anonymity itself will be checked by TryToCreateBid.
    if (mojo_kanon_bid) {
      if (auction_->kanon_mode_ ==
          auction_worklet::mojom::KAnonymityBidMode::kNone) {
        generate_bid_client_receiver_set_.ReportBadMessage(
            "Received k-anon bid data when not considering k-anon");
        mojo_kanon_bid.reset();
      } else if (mojo_bid &&
                 IsKAnon(state->kanon_keys, interest_group, mojo_bid.get())) {
        if (!mojo_kanon_bid->is_same_as_non_enforced()) {
          generate_bid_client_receiver_set_.ReportBadMessage(
              "Received different k-anon bid when unenforced bid already "
              "k-anon");
          mojo_kanon_bid = auction_worklet::mojom::
              BidderWorkletKAnonEnforcedBid::NewSameAsNonEnforced(nullptr);
        }
      }
    }

    // The mojom API declaration should ensure none of these are null.
    DCHECK(base::ranges::none_of(
        pa_requests,
        [](const auction_worklet::mojom::PrivateAggregationRequestPtr&
               request_ptr) { return request_ptr.is_null(); }));
    DCHECK(base::ranges::none_of(
        non_kanon_pa_requests,
        [](const auction_worklet::mojom::PrivateAggregationRequestPtr&
               request_ptr) { return request_ptr.is_null(); }));
    auction_->MaybeLogPrivateAggregationWebFeatures(pa_requests);
    if (!pa_requests.empty()) {
      BidState::PrivateAggregationPhaseKey agg_key = {
          interest_group.owner, PrivateAggregationPhase::kBidder,
          interest_group.aggregation_coordinator_origin};
      PrivateAggregationRequests& pa_requests_for_bidder =
          state->private_aggregation_requests[std::move(agg_key)];
      pa_requests_for_bidder.insert(pa_requests_for_bidder.end(),
                                    std::move_iterator(pa_requests.begin()),
                                    std::move_iterator(pa_requests.end()));
    }
    if (!non_kanon_pa_requests.empty()) {
      PrivateAggregationRequests& non_kanon_pa_requests_for_bidder =
          state->non_kanon_private_aggregation_requests;
      non_kanon_pa_requests_for_bidder.insert(
          non_kanon_pa_requests_for_bidder.end(),
          std::move_iterator(non_kanon_pa_requests.begin()),
          std::move_iterator(non_kanon_pa_requests.end()));
    }

    auction_->errors_.insert(auction_->errors_.end(), errors.begin(),
                             errors.end());

    // Ignore invalid bids.
    std::unique_ptr<Bid> bid;
    std::string ad_metadata;

    if (reject_reason != auction_worklet::mojom::RejectReason::kNotAvailable &&
        reject_reason !=
            auction_worklet::mojom::RejectReason::kWrongGenerateBidCurrency) {
      // Only possible reject reason from generateBid(), besides the default
      // "not available", is "wrong generate bid currency".
      mojo_bid.reset();
      mojo_kanon_bid.reset();
      state->reject_reason =
          auction_worklet::mojom::RejectReason::kNotAvailable;
      generate_bid_client_receiver_set_.ReportBadMessage(
          "Invalid bid reject_reason");
    } else {
      state->reject_reason = reject_reason;
    }

    // `mojo_bid` is null if the worklet doesn't bid, or if the bidder worklet
    // fails to load / crashes.
    if (mojo_bid) {
      // It's possible that k-anon enforced bid is the same as one with out
      // enforcement, in which case we make sure to only run ScoreBid once.
      Bid::BidRole role = Bid::BidRole::kUnenforcedKAnon;
      if (mojo_kanon_bid) {
        if (mojo_kanon_bid->is_same_as_non_enforced()) {
          role = Bid::BidRole::kBothKAnonModes;
          auction_->auction_metrics_recorder_
              ->RecordInterestGroupWithSameBidForKAnonAndNonKAnon();
        } else {
          auction_->auction_metrics_recorder_
              ->RecordInterestGroupWithSeparateBidsForKAnonAndNonKAnon();
        }
      } else {
        auction_->auction_metrics_recorder_
            ->RecordInterestGroupWithOnlyNonKAnonBid();
      }
      bid = TryToCreateBid(role, std::move(mojo_bid), *state,
                           maybe_bidding_signals_data_version,
                           debug_loss_report_url, debug_win_report_url);
      if (bid) {
        state->bidder_debug_loss_report_url = debug_loss_report_url;
      }
    } else {
      // Bidders who do not bid are allowed to get loss report.
      state->bidder_debug_loss_report_url = debug_loss_report_url;
      auction_->auction_metrics_recorder_->RecordInterestGroupWithNoBids();
    }

    std::unique_ptr<Bid> kanon_bid;
    if (mojo_kanon_bid && !mojo_kanon_bid->is_same_as_non_enforced()) {
      kanon_bid = TryToCreateBid(Bid::BidRole::kEnforcedKAnon,
                                 std::move(mojo_kanon_bid->get_bid()), *state,
                                 maybe_bidding_signals_data_version,
                                 /*debug_loss_report_url=*/absl::nullopt,
                                 /*debug_win_report_url=*/absl::nullopt);
    }

    // Release the worklet. If it wins the auction, it will be requested again
    // to invoke its ReportWin() method.
    CloseBidStatePipes(*state);

    if (!bid && !kanon_bid) {
      if (state->trace_id.has_value()) {
        // Might not have started it if we timed out before worklet received.
        state->EndTracing();
      }
    } else {
      state->bidder_debug_win_report_url = debug_win_report_url;
      state->made_bid = true;
      if (bid) {
        auction_->ScoreBidIfReady(std::move(bid));
      }
      if (kanon_bid) {
        state->BeginTracingKAnonScoring();
        auction_->ScoreBidIfReady(std::move(kanon_bid));
      }
    }

    --num_outstanding_bids_;
    if (num_outstanding_bids_ == 0) {
      DCHECK_EQ(num_outstanding_bidding_signals_received_calls_, 0);
      // Pipes should already be closed at this point, but the
      // `cumulative_buyer_timeout_timer_` needs to be stopped if it's running,
      // and it's safest to keep all logic to stop everything `this` may be
      // doing in one place.
      ClosePipes();

      auction_->OnScoringDependencyDone();
    }
  }

  void MaybeStartCumulativeTimeoutTimer() {
    // This should only be called when there are outstanding bids.
    DCHECK_GT(num_outstanding_bids_, 0);

    // Do nothing if still waiting on the seller to provide more of the
    // AuctionConfig, or directFromSellerSignalsHeaderAdSlot is still
    // parsing and finding a matching ad slot response, or waiting on a process
    // to be assigned (which would mean that this may be waiting behind other
    // buyers).
    if (!auction_->config_promises_resolved_ ||
        auction_->direct_from_seller_signals_header_ad_slot_pending_ ||
        !bidder_process_received_) {
      return;
    }

    DCHECK(!cumulative_buyer_timeout_timer_.IsRunning());

    // Get cumulative buyer timeout. Note that this must be done after the
    // `config_promises_resolved_` check above.
    absl::optional<base::TimeDelta> cumulative_buyer_timeout =
        PerBuyerCumulativeTimeout(owner_, *auction_->config_);

    // Nothing to do if there's no cumulative timeout.
    if (!cumulative_buyer_timeout) {
      return;
    }

    cumulative_buyer_timeout_timer_.Start(
        FROM_HERE, *cumulative_buyer_timeout,
        base::BindOnce(&BuyerHelper::OnTimeout, base::Unretained(this)));
  }

  // Called when the `cumulative_buyer_timeout_timer_` expires.
  void OnTimeout() {
    // If there are no outstanding bids, then the timer should not still be
    // running.
    DCHECK_GT(num_outstanding_bids_, 0);

    // Assemble a list of interest groups that haven't bid yet - have to do
    // this, since calling OnGenerateBidCompleteInternal() on the last
    // incomplete bid may delete `this`, if it ends the auction.
    std::list<BidState*> pending_bids;
    for (auto& bid_state : bid_states_) {
      if (!bid_state->worklet_handle) {
        continue;
      }
      // Put the IGs that have received signals first, since cancelling the last
      // bid that has not received signals could cause a bid that has received
      // signals to start running Javascript.
      if (bid_state->bidding_signals_received) {
        pending_bids.push_front(bid_state.get());
      } else {
        pending_bids.push_back(bid_state.get());
      }
    }

    auction_->auction_metrics_recorder_
        ->RecordBidsAbortedByBuyerCumulativeTimeout(pending_bids.size());
    for (auto* pending_bid : pending_bids) {
      // We specifically include timeouts in this metric.
      auction_->auction_metrics_recorder_->RecordBidForOneInterestGroupLatency(
          base::TimeTicks::Now() - start_generating_bids_time_);

      // Fail bids individually, with errors. This does potentially do extra
      // work over just failing the entire auction directly, but ensures there's
      // a single failure path, reducing the chance of future breakages.
      OnFatalError(
          pending_bid, /*errors=*/{base::StrCat(
              {pending_bid->bidder->interest_group.bidding_url->spec(),
               " perBuyerCumulativeTimeout exceeded during bid generation."})});
    }
  }

  // Validates that `mojo_bid` is valid and, if it is, creates a Bid
  // corresponding to it, consuming it. Returns nullptr and calls
  // ReportBadMessage() if it's not valid. Does not mutate `bid_state`, but
  // the returned Bid has a non-const pointer to it.
  std::unique_ptr<InterestGroupAuction::Bid> TryToCreateBid(
      InterestGroupAuction::Bid::BidRole bid_role,
      auction_worklet::mojom::BidderWorkletBidPtr mojo_bid,
      BidState& bid_state,
      const absl::optional<uint32_t>& bidding_signals_data_version,
      const absl::optional<GURL>& debug_loss_report_url,
      const absl::optional<GURL>& debug_win_report_url) {
    // We record the bid duration even if the bid is invalid to avoid bias.
    auction_->auction_metrics_recorder_->RecordGenerateSingleBidLatency(
        mojo_bid->bid_duration);

    if (!IsValidBid(mojo_bid->bid)) {
      generate_bid_client_receiver_set_.ReportBadMessage("Invalid bid value");
      return nullptr;
    }

    if (mojo_bid->bid_duration.is_negative()) {
      generate_bid_client_receiver_set_.ReportBadMessage(
          "Invalid bid duration");
      return nullptr;
    }

    if (!blink::VerifyAdCurrencyCode(
            PerBuyerCurrency(owner_, *auction_->config_),
            mojo_bid->bid_currency)) {
      generate_bid_client_receiver_set_.ReportBadMessage(
          "Invalid bid currency");
      return nullptr;
    }

    const blink::InterestGroup& interest_group =
        bid_state.bidder->interest_group;
    const blink::InterestGroup::Ad* matching_ad = FindMatchingAd(
        *interest_group.ads, bid_state.kanon_keys, interest_group, bid_role,
        /*is_component_ad=*/false, mojo_bid->ad_descriptor);
    if (!matching_ad) {
      generate_bid_client_receiver_set_.ReportBadMessage(
          "Bid render ad must have a valid URL and size (if specified)");
      return nullptr;
    }
    // If the matching ad does not have size specified, the bid to be created
    // should not have size specified to fall back to old behavior.
    blink::AdDescriptor ad_descriptor(
        mojo_bid->ad_descriptor.url,
        matching_ad->size_group ? mojo_bid->ad_descriptor.size : absl::nullopt);

    // Validate `ad_component` URLs, if present.
    std::vector<blink::AdDescriptor> ad_component_descriptors;
    if (mojo_bid->ad_component_descriptors) {
      // Only InterestGroups with ad components should return bids with ad
      // components.
      if (!interest_group.ad_components) {
        generate_bid_client_receiver_set_.ReportBadMessage(
            "Unexpected non-null ad component list");
        return nullptr;
      }

      if (mojo_bid->ad_component_descriptors->size() >
          blink::kMaxAdAuctionAdComponents) {
        generate_bid_client_receiver_set_.ReportBadMessage(
            "Too many ad component URLs");
        return nullptr;
      }

      // Validate each ad component URL is valid and appears in the interest
      // group's `ad_components` field.
      for (const blink::AdDescriptor& ad_component_descriptor :
           *mojo_bid->ad_component_descriptors) {
        const blink::InterestGroup::Ad* matching_ad_component = FindMatchingAd(
            *interest_group.ad_components, bid_state.kanon_keys, interest_group,
            bid_role, /*is_component_ad=*/true, ad_component_descriptor);
        if (!matching_ad_component) {
          generate_bid_client_receiver_set_.ReportBadMessage(
              "Bid ad component must have a valid URL and size (if specified)");
          return nullptr;
        }
        // If the matching ad does not have size specified, the bid to be
        // created should not have size specified to fall back to old behavior.
        ad_component_descriptors.emplace_back(ad_component_descriptor.url,
                                              matching_ad_component->size_group
                                                  ? ad_component_descriptor.size
                                                  : absl::nullopt);
      }
    }

    // Validate `debug_loss_report_url` and `debug_win_report_url`, if present.
    if (debug_loss_report_url.has_value() &&
        !IsUrlValid(debug_loss_report_url.value())) {
      generate_bid_client_receiver_set_.ReportBadMessage(
          "Invalid bidder debugging loss report URL");
      return nullptr;
    }
    if (debug_win_report_url.has_value() &&
        !IsUrlValid(debug_win_report_url.value())) {
      generate_bid_client_receiver_set_.ReportBadMessage(
          "Invalid bidder debugging win report URL");
      return nullptr;
    }

    return std::make_unique<Bid>(
        bid_role, std::move(mojo_bid->ad), mojo_bid->bid,
        std::move(mojo_bid->bid_currency), mojo_bid->ad_cost,
        std::move(ad_descriptor), std::move(ad_component_descriptors),
        std::move(mojo_bid->modeling_signals), mojo_bid->bid_duration,
        bidding_signals_data_version, matching_ad, &bid_state, auction_);
  }

  // Close all Mojo pipes associated with `state`.
  void CloseBidStatePipes(BidState& state) {
    state.worklet_handle.reset();
    if (state.generate_bid_client_receiver_id) {
      generate_bid_client_receiver_set_.Remove(
          *state.generate_bid_client_receiver_id);
      state.generate_bid_client_receiver_id.reset();
      state.bid_finalizer.reset();
    }
  }

  size_t size_limit_;

  const raw_ptr<InterestGroupAuction> auction_;

  const url::Origin owner_;

  // State of loaded interest groups owned by `owner_`. Use unique_ptrs so that
  // pointers aren't invalidated by sorting / deleting BidStates.
  std::vector<std::unique_ptr<BidState>> bid_states_;

  // Per-BidState receivers. These can never be null. Uses unique_ptrs so that
  // existing pointers aren't invalidated by sorting / deleting BidStates.
  mojo::AssociatedReceiverSet<auction_worklet::mojom::GenerateBidClient,
                              BidState*>
      generate_bid_client_receiver_set_;

  // Set to true once a single bidder worklet has been received (and thus, since
  // all bidder worklets managed by a BuyerHelper use the same process, `this`
  // is no longer blocked waiting on other bidders to complete).
  bool bidder_process_received_ = false;

  // Timer for applying the perBidderCumulativeTimeout, if one is applicable.
  // Starts once `bidder_process_received_`,
  // `auction_->config_promises_resolved_` are true, and
  // `auction_->direct_from_seller_signals_header_ad_slot_pending_` is false,
  // if `cumulative_buyer_timeout_` is not nullopt.
  base::OneShotTimer cumulative_buyer_timeout_timer_;

  int num_outstanding_bidding_signals_received_calls_ = 0;
  int num_outstanding_bids_ = 0;

  // Records the time at which StartGeneratingBids was called for UKM.
  base::TimeTicks start_generating_bids_time_;

  // True if any interest group owned by `owner_` participating in this auction
  // has `use_biddings_signals_prioritization` set to true. When this is true,
  // all GenerateBid() calls will be deferred until OnBiddingSignalsReceived()
  // has been invoked for all bidders (or they've failed to generate bids due to
  // errors).
  //
  // TODO(mmenke): Could only set this to true if the number of bidders exceeds
  // the per-buyer limit as well, and only the `priority_vector` as a filter for
  // buyers with `use_biddings_signals_prioritization` set to true, as a small
  // performance optimization.
  bool enable_bidding_signals_prioritization_ = false;

  base::WeakPtrFactory<BuyerHelper> weak_ptr_factory_{this};
};

InterestGroupAuction::InterestGroupAuction(
    auction_worklet::mojom::KAnonymityBidMode kanon_mode,
    const blink::AuctionConfig* config,
    const InterestGroupAuction* parent,
    AuctionWorkletManager* auction_worklet_manager,
    AuctionNonceManager* auction_nonce_manager,
    InterestGroupManagerImpl* interest_group_manager,
    AuctionMetricsRecorder* auction_metrics_recorder,
    AdAuctionPageData* ad_auction_page_data,
    base::Time auction_start_time,
    IsInterestGroupApiAllowedCallback is_interest_group_api_allowed_callback,
    base::RepeatingCallback<
        void(const PrivateAggregationRequests& private_aggregation_requests)>
        maybe_log_private_aggregation_web_features_callback)
    : trace_id_(base::trace_event::GetNextGlobalTraceId()),
      kanon_mode_(kanon_mode),
      auction_worklet_manager_(auction_worklet_manager),
      auction_nonce_manager_(auction_nonce_manager),
      interest_group_manager_(interest_group_manager),
      auction_metrics_recorder_(auction_metrics_recorder),
      config_(config),
      config_promises_resolved_(config_->NumPromises() == 0),
      parent_(parent),
      negative_targeter_(std::make_unique<AdAuctionNegativeTargeter>()),
      auction_start_time_(auction_start_time),
      creation_time_(base::TimeTicks::Now()),
      is_interest_group_api_allowed_callback_(
          std::move(is_interest_group_api_allowed_callback)),
      maybe_log_private_aggregation_web_features_callback_(
          std::move(maybe_log_private_aggregation_web_features_callback)),
      data_decoder_(ad_auction_page_data->GetDecoderFor(config->seller)) {
  DCHECK(is_interest_group_api_allowed_callback_);
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("fledge", "auction", *trace_id_,
                                    "decision_logic_url",
                                    config_->decision_logic_url);

  uint32_t child_pos = 0;
  for (const auto& component_auction_config :
       config->non_shared_params.component_auctions) {
    // Nested component auctions are not supported.
    DCHECK(!parent_);
    component_auctions_.emplace(
        child_pos, std::make_unique<InterestGroupAuction>(
                       kanon_mode_, &component_auction_config, /*parent=*/this,
                       auction_worklet_manager, auction_nonce_manager,
                       interest_group_manager, auction_metrics_recorder_,
                       ad_auction_page_data, auction_start_time_,
                       is_interest_group_api_allowed_callback_,
                       maybe_log_private_aggregation_web_features_callback_));
    ++child_pos;
  }

  if (!parent_) {
    auction_metrics_recorder_->SetKAnonymityBidMode(kanon_mode);
    auction_metrics_recorder_->SetNumConfigPromises(config_->NumPromises());
  }
}

InterestGroupAuction::~InterestGroupAuction() {
  if (trace_id_.has_value()) {
    TRACE_EVENT_NESTABLE_ASYNC_END0("fledge", "auction", *trace_id_);
  }

  if (!final_auction_result_) {
    final_auction_result_ = AuctionResult::kAborted;
  }

  std::string uma_prefix = "Ads.InterestGroup.Auction.";
  if (is_server_auction_) {
    uma_prefix = "Ads.InterestGroup.ServerAuction.";
  }

  // TODO(mmenke): Record histograms for component auctions.
  if (!parent_) {
    base::UmaHistogramEnumeration(uma_prefix + "Result",
                                  *final_auction_result_);

    if (HasNonKAnonWinner()) {
      base::UmaHistogramBoolean(uma_prefix + "NonKAnonWinnerIsKAnon",
                                NonKAnonWinnerIsKAnon());
    }

    // Only record time of full auctions and aborts.
    base::TimeTicks now = base::TimeTicks::Now();
    switch (*final_auction_result_) {
      case AuctionResult::kAborted:
        base::UmaHistogramMediumTimes(uma_prefix + "AbortTime",
                                      now - creation_time_);
        break;
      case AuctionResult::kNoBids:
      case AuctionResult::kAllBidsRejected:
        base::UmaHistogramMediumTimes(uma_prefix + "CompletedWithoutWinnerTime",
                                      now - creation_time_);
        if (is_server_auction_) {
          base::UmaHistogramMediumTimes(
              "Ads.InterestGroup.ServerAuction.EndToEndTimeNoWinner",
              now - get_ad_auction_data_start_time_);
        }
        break;
      case AuctionResult::kSuccess:
        base::UmaHistogramMediumTimes(uma_prefix + "AuctionWithWinnerTime",
                                      now - creation_time_);
        if (is_server_auction_) {
          base::UmaHistogramMediumTimes(
              "Ads.InterestGroup.ServerAuction.EndToEndTime",
              now - get_ad_auction_data_start_time_);
        }
        break;
      default:
        break;
    }

    // Last UKM we record for this auction. This finalizes and records the
    // AdsInterestGroup_AuctionLatency entry. Any further interactions with
    // auction_metrics_recorder_ will likely cause a CHECK-fail.
    auction_metrics_recorder_->OnAuctionEnd(*final_auction_result_);
  }
}

void InterestGroupAuction::StartLoadInterestGroupsPhase(
    AuctionPhaseCompletionCallback load_interest_groups_phase_callback) {
  DCHECK(load_interest_groups_phase_callback);
  DCHECK(buyer_helpers_.empty());
  DCHECK(!load_interest_groups_phase_callback_);
  DCHECK(!bidding_and_scoring_phase_callback_);
  DCHECK(!final_auction_result_);
  DCHECK_EQ(num_pending_loads_, 0u);

  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("fledge", "load_groups_phase", *trace_id_);

  load_interest_groups_phase_callback_ =
      std::move(load_interest_groups_phase_callback);

  // If the seller can't participate in the auction, fail the auction.
  if (!is_interest_group_api_allowed_callback_.Run(
          ContentBrowserClient::InterestGroupApiOperation::kSell,
          config_->seller)) {
    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE,
        base::BindOnce(
            &InterestGroupAuction::OnStartLoadInterestGroupsPhaseComplete,
            weak_ptr_factory_.GetWeakPtr(), AuctionResult::kSellerRejected));
    return;
  }

  if (config_->non_shared_params.auction_nonce) {
    if (!auction_nonce_manager_->ClaimAuctionNonceIfAvailable(
            static_cast<AuctionNonce>(
                *config_->non_shared_params.auction_nonce))) {
      base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
          FROM_HERE,
          base::BindOnce(
              &InterestGroupAuction::OnStartLoadInterestGroupsPhaseComplete,
              weak_ptr_factory_.GetWeakPtr(),
              AuctionResult::kInvalidAuctionNonce));
      return;
    }
  }

  for (auto component_auction = component_auctions_.begin();
       component_auction != component_auctions_.end(); ++component_auction) {
    component_auction->second->StartLoadInterestGroupsPhase(
        base::BindOnce(&InterestGroupAuction::OnComponentInterestGroupsRead,
                       weak_ptr_factory_.GetWeakPtr(), component_auction));
    ++num_pending_loads_;
  }

  if (config_->non_shared_params.interest_group_buyers) {
    for (const auto& buyer :
         *config_->non_shared_params.interest_group_buyers) {
      if (!is_interest_group_api_allowed_callback_.Run(
              ContentBrowserClient::InterestGroupApiOperation::kBuy, buyer)) {
        continue;
      }
      interest_group_manager_->GetInterestGroupsForOwner(
          buyer, base::BindOnce(&InterestGroupAuction::OnInterestGroupRead,
                                weak_ptr_factory_.GetWeakPtr()));
      ++num_pending_loads_;
    }
  }

  if (num_pending_loads_ == 0) {
    // There is nothing to load.  We move on to the bidding and scoring phase
    // anyway, since it may need to wait for config promises to be resolved
    // (and checked) and also potentially deal with additional_bids.
    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE,
        base::BindOnce(
            &InterestGroupAuction::OnStartLoadInterestGroupsPhaseComplete,
            weak_ptr_factory_.GetWeakPtr(), AuctionResult::kSuccess));
  }
}

void InterestGroupAuction::StartBiddingAndScoringPhase(
    base::OnceClosure on_seller_receiver_callback,
    AuctionPhaseCompletionCallback bidding_and_scoring_phase_callback) {
  DCHECK(bidding_and_scoring_phase_callback);
  DCHECK(!on_seller_receiver_callback_);
  DCHECK(!load_interest_groups_phase_callback_);
  DCHECK(!bidding_and_scoring_phase_callback_);
  DCHECK(!final_auction_result_);
  DCHECK(!non_kanon_enforced_auction_leader_.top_bid);
  DCHECK(!kanon_enforced_auction_leader_.top_bid);
  DCHECK_EQ(pending_component_seller_worklet_requests_, 0u);
  DCHECK_EQ(bidding_and_scoring_phase_state_, PhaseState::kBefore);

  bidding_and_scoring_phase_state_ = PhaseState::kDuring;

  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("fledge", "bidding_and_scoring_phase",
                                    *trace_id_);

  on_seller_receiver_callback_ = std::move(on_seller_receiver_callback);
  bidding_and_scoring_phase_callback_ =
      std::move(bidding_and_scoring_phase_callback);

  bidding_and_scoring_phase_start_time_ = base::TimeTicks::Now();

  CHECK_EQ(num_scoring_dependencies_, 0);
  num_scoring_dependencies_ =
      buyer_helpers_.size() + component_auctions_.size();

  // Also wait for config to resolve.
  if (!config_promises_resolved_) {
    ++num_scoring_dependencies_;
  }

  // Also wait for directFromSellerSignalsHeaderAdSlot to finish JSON parsing.
  if (direct_from_seller_signals_header_ad_slot_pending_) {
    ++num_scoring_dependencies_;
  }

  DecodeAdditionalBidsIfReady();

  // Need to start loading worklets before any bids can be generated or scored.
  if (component_auctions_.empty()) {
    // If there are no component auctions, request the seller worklet if we may
    // need it. (The case for component auctions is handled below, there the
    // seller worklet will be requested once all component auctions have
    // received their own seller worklets).
    if (!buyer_helpers_.empty() || MayHaveAdditionalBids()) {
      RequestSellerWorklet();
    }
  } else {
    // Since component auctions may invoke OnComponentSellerWorkletReceived()
    // synchronously, it's important to set this to the total number of
    // component auctions before invoking StartBiddingAndScoringPhase() on any
    // component auction.
    pending_component_seller_worklet_requests_ = component_auctions_.size();
    for (auto& component_auction_info : component_auctions_) {
      InterestGroupAuction* component_auction =
          component_auction_info.second.get();
      component_auction->StartBiddingAndScoringPhase(
          base::BindOnce(
              &InterestGroupAuction::OnComponentSellerWorkletReceived,
              base::Unretained(this)),
          base::BindOnce(&InterestGroupAuction::OnComponentAuctionComplete,
                         base::Unretained(this), component_auction));
    }
  }

  for (const auto& buyer_helper : buyer_helpers_) {
    buyer_helper->StartGeneratingBids();
  }

  // It's possible that we actually have nothing to do here at this point ---
  // neither bids from interest groups, nor configuration promises to wait for.
  MaybeCompleteBiddingAndScoringPhase();
}

void InterestGroupAuction::StartFromServerResponse(
    mojo_base::BigBuffer response,
    AdAuctionPageData* ad_auction_page_data,
    AuctionPhaseCompletionCallback bidding_and_scoring_phase_callback) {
  bidding_and_scoring_phase_callback_ =
      std::move(bidding_and_scoring_phase_callback);
  is_server_auction_ = true;

  // Check that response was witnessed by seller origin.
  std::array<uint8_t, crypto::kSHA256Length> hash =
      crypto::SHA256Hash(response.byte_span());
  if (!ad_auction_page_data->WitnessedAuctionResultForOrigin(
          config_->seller,
          std::string(reinterpret_cast<char*>(hash.data()), hash.size()))) {
    // If it wasn't witnessed then we don't know that it came from the server.
    OnBiddingAndScoringComplete(
        AuctionResult::kInvalidServerResponse,
        {base::StrCat(
            {"runAdAuction(): Server response was not witnessed from ",
             config_->seller.Serialize()})});
    return;
  }

  AdAuctionRequestContext* request_context =
      ad_auction_page_data->GetContextForAdAuctionRequest(
          config_->server_response->request_id);
  if (!request_context) {
    // The corresponding context for the requested blob couldn't be found.
    OnBiddingAndScoringComplete(
        AuctionResult::kInvalidServerResponse,
        {base::StrCat(
            {"runAdAuction(): No corresponding request with ID: ",
             config_->server_response->request_id.AsLowercaseString()})});
    return;
  }

  // The auction must be for the same seller that requested the blob.
  if (request_context->seller != config_->seller) {
    OnBiddingAndScoringComplete(
        AuctionResult::kInvalidServerResponse,
        {"runAdAuction(): Seller in response doesn't match request"});
    return;
  }
  get_ad_auction_data_start_time_ = request_context->start_time;

  auto maybe_response =
      quiche::ObliviousHttpResponse::CreateClientObliviousResponse(
          std::string(reinterpret_cast<char*>(response.data()),
                      response.size()),
          request_context->context,
          kBiddingAndAuctionEncryptionResponseMediaType.Get());
  if (!maybe_response.ok()) {
    // We couldn't decrypt the response.
    OnBiddingAndScoringComplete(
        AuctionResult::kInvalidServerResponse,
        {"runAdAuction(): Could not decrypt server response"});
    return;
  }
  const std::string& plaintext_response = maybe_response->GetPlaintextData();
  absl::optional<base::span<const uint8_t>> compressed_response =
      ExtractCompressedBiddingAndAuctionResponse(
          base::as_bytes(base::make_span(plaintext_response)));
  if (!compressed_response) {
    OnBiddingAndScoringComplete(
        AuctionResult::kInvalidServerResponse,
        {"runAdAuction(): Could not parse response framing"});
    return;
  }
  data_decoder_->GzipUncompress(
      std::move(compressed_response).value(),
      base::BindOnce(
          &InterestGroupAuction::OnDecompressedServerResponse,
          // This use of unretained is safe since the request_context is owned
          // by a PageUserData and is only deleted when the page is destroyed.
          // This auction is owned by the page through a DocumentService, so it
          // will be destroyed before the decoder.
          weak_ptr_factory_.GetWeakPtr(), base::Unretained(request_context)));
}

std::unique_ptr<InterestGroupAuctionReporter>
InterestGroupAuction::CreateReporter(
    BrowserContext* browser_context,
    PrivateAggregationManager* private_aggregation_manager,
    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
    std::unique_ptr<blink::AuctionConfig> auction_config,
    const url::Origin& main_frame_origin,
    const url::Origin& frame_origin,
    network::mojom::ClientSecurityStatePtr client_security_state,
    blink::InterestGroupSet interest_groups_that_bid) {
  DCHECK(!load_interest_groups_phase_callback_);
  DCHECK(!bidding_and_scoring_phase_callback_);
  DCHECK_EQ(*final_auction_result_, AuctionResult::kSuccess);
  DCHECK(non_kanon_enforced_auction_leader_.top_bid);

  // This should only be called on top-level auctions.
  DCHECK(!parent_);

  uint64_t trace_id = *trace_id_;
  trace_id_.reset();

  const LeaderInfo& leader = leader_info();
  InterestGroupAuction::ScoredBid* winner = leader.top_bid.get();
  InterestGroupAuctionReporter::WinningBidInfo winning_bid_info(
      winner->bid->bid_state->bidder);
  winning_bid_info.render_url = winner->bid->ad_descriptor.url;
  winning_bid_info.ad_components = winner->bid->GetAdComponentUrls();
  winning_bid_info.allowed_reporting_origins =
      winner->bid->bid_ad->allowed_reporting_origins;
  // Need the bid from the bidder itself. If the bid was from a component
  // auction, then `top_bid_->bid` will be the bid from the component auction,
  // which the component seller worklet may have modified, and thus the wrong
  // bid. As a result, have to get the top bid from the component auction in
  // that case. `top_bid_->bid->auction->top_bid()` is the same as `top_bid_` if
  // the bid was from the top-level auction, and the original top bid from the
  // component auction, otherwise, so will always be the bid returned by the
  // winning bidder's generateBid() method.
  const InterestGroupAuction::Bid* bidder_bid =
      winner->bid->auction->top_bid()->bid.get();
  winning_bid_info.bid = bidder_bid->bid;
  // We redact the bid currency to just be the concrete currency from the
  // config; passing in the currency from actual bid would permit leakage of
  // information, if only via its absence.
  winning_bid_info.bid_currency = PerBuyerCurrency(
      bidder_bid->interest_group->owner, *bidder_bid->auction->config_);

  winning_bid_info.provided_as_additional_bid =
      bidder_bid->bid_state->additional_bid_buyer.has_value();
  winning_bid_info.ad_cost = bidder_bid->ad_cost;
  winning_bid_info.modeling_signals = bidder_bid->modeling_signals;
  winning_bid_info.bid_duration = winner->bid->bid_duration;
  winning_bid_info.bidding_signals_data_version =
      winner->bid->bidding_signals_data_version;
  base::Value::Dict ad_metadata;
  ad_metadata.Set("renderURL", winner->bid->ad_descriptor.url.spec());
  if (winner->bid->bid_ad->metadata) {
    ad_metadata.Set("metadata", winner->bid->bid_ad->metadata.value());
  }
  if (winner->bid->bid_ad->ad_render_id) {
    ad_metadata.Set("adRenderId", winner->bid->bid_ad->ad_render_id.value());
  }
  JSONStringValueSerializer serializer(&winning_bid_info.ad_metadata);
  serializer.Serialize(base::Value(std::move(ad_metadata)));

  InterestGroupAuctionReporter::SellerWinningBidInfo
      top_level_seller_winning_bid_info;
  top_level_seller_winning_bid_info.auction_config = config_;
  DCHECK(subresource_url_builder_);  // Must have been created by scoring.
  CHECK(direct_from_seller_signals_header_ad_slot_);  // Should never be null.
  top_level_seller_winning_bid_info.subresource_url_builder =
      std::move(subresource_url_builder_);
  top_level_seller_winning_bid_info.direct_from_seller_signals_header_ad_slot =
      std::move(direct_from_seller_signals_header_ad_slot_);
  top_level_seller_winning_bid_info.bid = winner->bid->bid;

  if (winner->bid->auction == this) {
    // Bid came directly from bidder, not a component auction.
    top_level_seller_winning_bid_info.bid_currency =
        winning_bid_info.bid_currency;
  } else {
    // Bid comes from component auction, so we redact the config expectation of
    // the bid of component auction in top-level auction.
    InterestGroupAuction* component_auction = winner->bid->auction;
    top_level_seller_winning_bid_info.bid_currency =
        component_auction->config_->non_shared_params.seller_currency;
    if (!top_level_seller_winning_bid_info.bid_currency) {
      top_level_seller_winning_bid_info.bid_currency =
          PerBuyerCurrency(component_auction->config_->seller, *config_);
    }
  }

  top_level_seller_winning_bid_info.bid_in_seller_currency =
      winner->bid_in_seller_currency.value_or(0.0);
  top_level_seller_winning_bid_info.score = winner->score;
  top_level_seller_winning_bid_info.highest_scoring_other_bid =
      leader.highest_scoring_other_bid;
  top_level_seller_winning_bid_info
      .highest_scoring_other_bid_in_seller_currency =
      leader.highest_scoring_other_bid_in_seller_currency;
  top_level_seller_winning_bid_info.highest_scoring_other_bid_owner =
      leader.highest_scoring_other_bid_owner;
  top_level_seller_winning_bid_info.scoring_signals_data_version =
      leader.top_bid->scoring_signals_data_version;
  top_level_seller_winning_bid_info.trace_id = trace_id;

  // Populate the SellerWinningBidInfo for the component auction that the
  // winning bid came from, if any. This largely duplicates the above block.
  //
  // TODO(mmenke): Share code with the above block. This currently isn't
  // possible because InterestGroupAuctionReporter depends on
  // InterestGroupAuction, so it can return an auction completion status, so no
  // InterestGroupAuction methods can take or return an
  // InterestGroupAuctionReporter::SellerWinningBidInfo. Once that dependency is
  // removed, it should be possible to make a helper method to construct both
  // SellerWinningBidInfos.
  absl::optional<InterestGroupAuctionReporter::SellerWinningBidInfo>
      component_seller_winning_bid_info;
  if (winner->bid->auction != this) {
    InterestGroupAuction* component_auction = winner->bid->auction;
    component_seller_winning_bid_info.emplace();
    component_seller_winning_bid_info->auction_config =
        component_auction->config_;
    DCHECK(component_auction->subresource_url_builder_);
    // Should never be null.
    CHECK(component_auction->direct_from_seller_signals_header_ad_slot_);
    component_seller_winning_bid_info->subresource_url_builder =
        std::move(component_auction->subresource_url_builder_);
    component_seller_winning_bid_info
        ->direct_from_seller_signals_header_ad_slot = std::move(
        component_auction->direct_from_seller_signals_header_ad_slot_);
    const LeaderInfo& component_leader = component_auction->leader_info();
    component_seller_winning_bid_info->bid = component_leader.top_bid->bid->bid;
    // The bidder in this auction was the actual bidder, so the currency comes
    // from it, too.
    component_seller_winning_bid_info->bid_currency =
        winning_bid_info.bid_currency;
    component_seller_winning_bid_info->bid_in_seller_currency =
        component_leader.top_bid->bid_in_seller_currency.value_or(0.0);
    component_seller_winning_bid_info->score = component_leader.top_bid->score;
    component_seller_winning_bid_info->highest_scoring_other_bid =
        component_leader.highest_scoring_other_bid;
    component_seller_winning_bid_info
        ->highest_scoring_other_bid_in_seller_currency =
        component_leader.highest_scoring_other_bid_in_seller_currency;
    component_seller_winning_bid_info->highest_scoring_other_bid_owner =
        component_leader.highest_scoring_other_bid_owner;
    component_seller_winning_bid_info->scoring_signals_data_version =
        component_leader.top_bid->scoring_signals_data_version;
    component_seller_winning_bid_info->trace_id = *component_auction->trace_id_;
    component_seller_winning_bid_info->component_auction_modified_bid_params =
        component_leader.top_bid->component_auction_modified_bid_params
            ->Clone();
  }

  std::vector<GURL> debug_win_report_urls;
  std::vector<GURL> debug_loss_report_urls;
  TakeDebugReportUrlsAndFillInPrivateAggregationRequests(
      debug_win_report_urls, debug_loss_report_urls);

  bool bid_is_kanon;
  switch (kanon_mode_) {
    case auction_worklet::mojom::KAnonymityBidMode::kSimulate:
      // Check if the winner was k-anon, since we use the non-kanonymous winner
      // in simulate mode.
      bid_is_kanon = NonKAnonWinnerIsKAnon();
      break;
    case auction_worklet::mojom::KAnonymityBidMode::kEnforce:
      // We always have a winner when we get here.
      bid_is_kanon = true;
      break;
    case auction_worklet::mojom::KAnonymityBidMode::kNone:
      // Set to false due to enforcement is completely off.
      bid_is_kanon = false;
      break;
  }

  auto result = std::make_unique<InterestGroupAuctionReporter>(
      interest_group_manager_, auction_worklet_manager_, browser_context,
      private_aggregation_manager,
      maybe_log_private_aggregation_web_features_callback_,
      std::move(auction_config), main_frame_origin, frame_origin,
      std::move(client_security_state), std::move(url_loader_factory),
      kanon_mode_, bid_is_kanon, std::move(winning_bid_info),
      std::move(top_level_seller_winning_bid_info),
      std::move(component_seller_winning_bid_info),
      std::move(interest_groups_that_bid), std::move(debug_win_report_urls),
      std::move(debug_loss_report_urls), GetKAnonKeysToJoin(),
      TakeReservedPrivateAggregationRequests(),
      TakeNonReservedPrivateAggregationRequests());

  // Avoid dangling pointers for things transferred to the reporter.
  winner->bid->interest_group = nullptr;
  winner->bid->bid_ad = nullptr;
  config_ = nullptr;
  for (const auto& kv : component_auctions_) {
    kv.second->config_ = nullptr;
  }

  return result;
}

void InterestGroupAuction::NotifyConfigPromisesResolved() {
  DCHECK(!config_promises_resolved_);
  DCHECK_EQ(0, config_->NumPromises());
  config_promises_resolved_ = true;

  // If we haven't started the bidding and scoring phase, we will just handle
  // this information at its start; setting `config_promises_resolved_` is
  // enough both for us and the BuyerHelper. If we are after the phase, that
  // means that promises resolved after we failed out of it, so we should ignore
  // them.
  if (bidding_and_scoring_phase_state_ != PhaseState::kDuring) {
    return;
  }

  auction_metrics_recorder_->OnConfigPromisesResolved();

  for (const auto& buyer_helper : buyer_helpers_) {
    buyer_helper->NotifyConfigPromisesResolved();
  }

  base::TimeTicks now = base::TimeTicks::Now();
  for (auto& unscored_bid : unscored_bids_) {
    unscored_bid->wait_promises =
        now - unscored_bid->trace_wait_seller_deps_start;

    if (!component_auctions_.empty()) {
      auction_metrics_recorder_
          ->RecordTopLevelBidQueuedWaitingForConfigPromises(
              unscored_bid->wait_promises);
    } else {
      auction_metrics_recorder_->RecordBidQueuedWaitingForConfigPromises(
          unscored_bid->wait_promises);
    }
  }

  DecodeAdditionalBidsIfReady();

  // Config resolution is done.
  OnScoringDependencyDone();

  ScoreQueuedBidsIfReady();
}

void InterestGroupAuction::NotifyComponentConfigPromisesResolved(uint32_t pos) {
  DCHECK(!parent_);  // Should not be called on a component.
  auto it = component_auctions_.find(pos);

  if (it == component_auctions_.end()) {
    // It's OK if the component auction isn't found; that means it got dropped
    // at database loading stage.
    return;
  }

  it->second->NotifyConfigPromisesResolved();
}

void InterestGroupAuction::NotifyAdditionalBidsConfig(
    AdAuctionPageData* auction_page_data) {
  // An auction with additional bids can't have child auctions.
  DCHECK_EQ(config_->non_shared_params.component_auctions.size(), 0u);

  // Enforced by mojo traits and checks on ResolvedAdditionalBids().
  CHECK(config_->non_shared_params.auction_nonce.has_value());
  CHECK(config_->non_shared_params.interest_group_buyers.has_value());

  if (!auction_page_data) {
    return;
  }

  interest_group_buyers_ = base::flat_set<url::Origin>(
      config_->non_shared_params.interest_group_buyers->begin(),
      config_->non_shared_params.interest_group_buyers->end());

  encoded_signed_additional_bids_ =
      auction_page_data->TakeAuctionAdditionalBidsForOriginAndNonce(
          config_->seller,
          config_->non_shared_params.auction_nonce->AsLowercaseString());
}

void InterestGroupAuction::NotifyComponentAdditionalBidsConfig(
    uint32_t pos,
    AdAuctionPageData* auction_page_data) {
  DCHECK(!parent_);  // Should not be called on a component.
  // And should have component auctions configured if we got thus far
  // (though none may have ended up passing the permissions check).
  DCHECK_GT(config_->non_shared_params.component_auctions.size(), 0u);

  auto it = component_auctions_.find(pos);
  if (it == component_auctions_.end()) {
    // Empty component auctions shouldn't be dropped, but component
    // auctions may still be dropped if they fail permissions checks.
    return;
  }

  it->second->NotifyAdditionalBidsConfig(auction_page_data);
}

void InterestGroupAuction::NotifyDirectFromSellerSignalsHeaderAdSlotConfig(
    AdAuctionPageData* auction_page_data,
    const absl::optional<std::string>&
        direct_from_seller_signals_header_ad_slot) {
  CHECK(!direct_from_seller_signals_header_ad_slot_pending_);
  if (!direct_from_seller_signals_header_ad_slot ||
      bidding_and_scoring_phase_state_ == PhaseState::kAfter) {
    return;
  }
  if (bidding_and_scoring_phase_state_ == PhaseState::kDuring) {
    ++num_scoring_dependencies_;
  }
  direct_from_seller_signals_header_ad_slot_pending_ = true;
  HeaderDirectFromSellerSignals::ParseAndFind(
      base::BindRepeating(&InterestGroupAuction::GetDataDecoder,
                          weak_ptr_factory_.GetWeakPtr()),
      auction_page_data->GetAuctionSignalsForOrigin(config_->seller),
      *direct_from_seller_signals_header_ad_slot,
      base::BindOnce(
          &InterestGroupAuction::OnDirectFromSellerSignalHeaderAdSlotResolved,
          weak_ptr_factory_.GetWeakPtr()));
}

void InterestGroupAuction::
    NotifyComponentDirectFromSellerSignalsHeaderAdSlotConfig(
        uint32_t pos,
        AdAuctionPageData* auction_page_data,
        const absl::optional<std::string>&
            direct_from_seller_signals_header_ad_slot) {
  CHECK(!parent_);  // Should not be called on a component.
  auto it = component_auctions_.find(pos);

  if (it == component_auctions_.end()) {
    // Empty component auctions shouldn't be dropped, but component
    // auctions may still be dropped if they fail permissions checks.
    return;
  }

  it->second->NotifyDirectFromSellerSignalsHeaderAdSlotConfig(
      auction_page_data, std::move(direct_from_seller_signals_header_ad_slot));
}

void InterestGroupAuction::ClosePipes() {
  weak_ptr_factory_.InvalidateWeakPtrs();

  score_ad_receivers_.Clear();

  for (auto& buyer_helper : buyer_helpers_) {
    buyer_helper->ClosePipes();
  }
  seller_worklet_handle_.reset();

  // There shouldn't be any pipes here for additional bids (though reporter
  // may create some).
  for (const auto& bid_state : bid_states_for_additional_bids_) {
    DCHECK(!bid_state->worklet_handle);
    DCHECK(!bid_state->bid_finalizer);
  }

  // Close pipes for component auctions as well.
  for (auto& component_auction_info : component_auctions_) {
    component_auction_info.second->ClosePipes();
  }
}

size_t InterestGroupAuction::NumPotentialBidders() const {
  size_t num_interest_groups = 0;
  for (const auto& buyer_helper : buyer_helpers_) {
    num_interest_groups += buyer_helper->num_potential_bidders();
  }
  for (const auto& component_auction_info : component_auctions_) {
    num_interest_groups += component_auction_info.second->NumPotentialBidders();
  }
  return num_interest_groups;
}

void InterestGroupAuction::GetInterestGroupsThatBidAndReportBidCounts(
    blink::InterestGroupSet& interest_groups) const {
  if (!all_bids_scored_) {
    return;
  }

  if (saved_response_) {
    interest_groups.insert(saved_response_->bidding_groups.begin(),
                           saved_response_->bidding_groups.end());
    for (const auto& ig_bid : interest_groups) {
      interest_group_manager_->NotifyInterestGroupAccessed(
          InterestGroupManagerImpl::InterestGroupObserver::
              InterestGroupObserver::kBid,
          ig_bid.owner, ig_bid.name);
    }
    return;
  }

  for (auto& buyer_helper : buyer_helpers_) {
    buyer_helper->GetInterestGroupsThatBidAndReportBidCounts(interest_groups);
  }

  // Notify devtools of additional bids. These don't go into `interest_groups`,
  // that's only things in the database.
  for (const auto& bid_state : bid_states_for_additional_bids_) {
    CHECK(bid_state->made_bid);
    interest_group_manager_->NotifyInterestGroupAccessed(
        InterestGroupManagerImpl::InterestGroupObserver::InterestGroupObserver::
            kAdditionalBid,
        bid_state->bidder->interest_group.owner,
        bid_state->bidder->interest_group.name);
  }

  // Retrieve data from component auctions as well.
  for (const auto& component_auction_info : component_auctions_) {
    component_auction_info.second->GetInterestGroupsThatBidAndReportBidCounts(
        interest_groups);
  }
}

absl::optional<blink::AdSize> InterestGroupAuction::RequestedAdSize() const {
  return config_->non_shared_params.requested_size;
}

base::StringPiece GetRejectReasonString(
    const auction_worklet::mojom::RejectReason reject_reason) {
  base::StringPiece reject_reason_str;
  switch (reject_reason) {
    case auction_worklet::mojom::RejectReason::kNotAvailable:
      reject_reason_str = "not-available";
      break;
    case auction_worklet::mojom::RejectReason::kInvalidBid:
      reject_reason_str = "invalid-bid";
      break;
    case auction_worklet::mojom::RejectReason::kBidBelowAuctionFloor:
      reject_reason_str = "bid-below-auction-floor";
      break;
    case auction_worklet::mojom::RejectReason::kPendingApprovalByExchange:
      reject_reason_str = "pending-approval-by-exchange";
      break;
    case auction_worklet::mojom::RejectReason::kDisapprovedByExchange:
      reject_reason_str = "disapproved-by-exchange";
      break;
    case auction_worklet::mojom::RejectReason::kBlockedByPublisher:
      reject_reason_str = "blocked-by-publisher";
      break;
    case auction_worklet::mojom::RejectReason::kLanguageExclusions:
      reject_reason_str = "language-exclusions";
      break;
    case auction_worklet::mojom::RejectReason::kCategoryExclusions:
      reject_reason_str = "category-exclusions";
      break;
    case auction_worklet::mojom::RejectReason::kBelowKAnonThreshold:
      reject_reason_str = "below-kanon-threshold";
      break;
    case auction_worklet::mojom::RejectReason::kWrongGenerateBidCurrency:
      reject_reason_str = "wrong-generate-bid-currency";
      break;
    case auction_worklet::mojom::RejectReason::kWrongScoreAdCurrency:
      reject_reason_str = "wrong-score-ad-currency";
      break;
  }
  return reject_reason_str;
}

GURL InterestGroupAuction::FillPostAuctionSignals(
    const GURL& url,
    const PostAuctionSignals& signals,
    const absl::optional<PostAuctionSignals>& top_level_signals,
    const absl::optional<auction_worklet::mojom::RejectReason> reject_reason) {
  // TODO(qingxinwu): Round `winning_bid` and `highest_scoring_other_bid` to two
  // most-significant digits. Maybe same to corresponding browser signals of
  // reportWin()/reportResult().
  if (!url.has_query()) {
    return url;
  }

  std::string query_string = url.query();
  base::ReplaceSubstringsAfterOffset(&query_string, 0, "${winningBid}",
                                     base::NumberToString(signals.winning_bid));
  base::ReplaceSubstringsAfterOffset(
      &query_string, 0, "${winningBidCurrency}",
      blink::PrintableAdCurrency(signals.winning_bid_currency));

  base::ReplaceSubstringsAfterOffset(
      &query_string, 0, "${madeWinningBid}",
      signals.made_winning_bid ? "true" : "false");
  base::ReplaceSubstringsAfterOffset(
      &query_string, 0, "${highestScoringOtherBid}",
      base::NumberToString(signals.highest_scoring_other_bid));
  base::ReplaceSubstringsAfterOffset(
      &query_string, 0, "${highestScoringOtherBidCurrency}",
      blink::PrintableAdCurrency(signals.highest_scoring_other_bid_currency));
  base::ReplaceSubstringsAfterOffset(
      &query_string, 0, "${madeHighestScoringOtherBid}",
      signals.made_highest_scoring_other_bid ? "true" : "false");

  // For component auction sellers only, which get post auction signals from
  // both their own component auctions and top-level auction.
  // For now, we're assuming top-level auctions to be first-price auction only
  // (not second-price auction) and it does not need highest_scoring_other_bid.
  if (top_level_signals.has_value()) {
    base::ReplaceSubstringsAfterOffset(
        &query_string, 0, "${topLevelWinningBid}",
        base::NumberToString(top_level_signals->winning_bid));
    base::ReplaceSubstringsAfterOffset(
        &query_string, 0, "${topLevelWinningBidCurrency}",
        blink::PrintableAdCurrency(top_level_signals->winning_bid_currency));
    base::ReplaceSubstringsAfterOffset(
        &query_string, 0, "${topLevelMadeWinningBid}",
        top_level_signals->made_winning_bid ? "true" : "false");
  }

  if (reject_reason.has_value()) {
    base::ReplaceSubstringsAfterOffset(
        &query_string, 0, "${rejectReason}",
        GetRejectReasonString(reject_reason.value()));
  }

  GURL::Replacements replacements;
  replacements.SetQueryStr(query_string);
  return url.ReplaceComponents(replacements);
}

bool InterestGroupAuction::ReportPaBuyersValueIfAllowed(
    const blink::InterestGroup& interest_group,
    blink::SellerCapabilities capability,
    blink::AuctionConfig::NonSharedParams::BuyerReportType buyer_report_type,
    int value) {
  if (!CanReportPaBuyersValue(interest_group, capability, config_->seller)) {
    return false;
  }

  absl::optional<absl::uint128> bucket_base =
      BucketBaseForReportPaBuyers(*config_, interest_group.owner);
  if (!bucket_base) {
    return false;
  }

  absl::optional<
      blink::AuctionConfig::NonSharedParams::AuctionReportBuyersConfig>
      report_buyers_config =
          ReportBuyersConfigForPaBuyers(buyer_report_type, *config_);
  if (!report_buyers_config) {
    return false;
  }

  // TODO(caraitto): Consider adding renderer and Mojo validation to ensure that
  // bucket sums can't be out of range, and scales can't be negative, infinite,
  // or NaN.
  InterestGroupAuctionReporter::PrivateAggregationKey agg_key = {
      config_->seller, config_->aggregation_coordinator_origin};
  PrivateAggregationRequests& destination_vector =
      private_aggregation_requests_reserved_[std::move(agg_key)];
  destination_vector.push_back(
      auction_worklet::mojom::PrivateAggregationRequest::New(
          auction_worklet::mojom::AggregatableReportContribution::
              NewHistogramContribution(
                  blink::mojom::AggregatableReportHistogramContribution::New(
                      *bucket_base + report_buyers_config->bucket,
                      base::saturated_cast<int32_t>(
                          std::max(0.0, value * report_buyers_config->scale)))),
          // TODO(caraitto): Consider allowing these to be set.
          blink::mojom::AggregationServiceMode::kDefault,
          blink::mojom::DebugModeDetails::New()));
  return true;
}

bool InterestGroupAuction::HasNonKAnonWinner() const {
  if (!final_auction_result_) {
    return false;
  }

  switch (*final_auction_result_) {
    // Bidding and scoring phase completed with no fatal error. We either
    // succeeded or only failed because we did not have a winner. If the only
    // reason we didn't have a winner was k-anonymity enforcement, there may
    // still be a non-k-anon winner.
    case AuctionResult::kSuccess:
    case AuctionResult::kNoBids:
    case AuctionResult::kAllBidsRejected:
      return top_non_kanon_enforced_bid() != nullptr;
    case AuctionResult::kAborted:
    case AuctionResult::kBadMojoMessage:
    case AuctionResult::kNoInterestGroups:
    case AuctionResult::kSellerWorkletLoadFailed:
    case AuctionResult::kSellerWorkletCrashed:
    case AuctionResult::kSellerRejected:
    case AuctionResult::kComponentLostAuction:
    case AuctionResult::kInvalidServerResponse:
    case AuctionResult::kInvalidAuctionNonce:
      return false;
  }
}

bool InterestGroupAuction::NonKAnonWinnerIsKAnon() const {
  return top_non_kanon_enforced_bid() &&
         top_non_kanon_enforced_bid()
                 ->bid->auction->top_non_kanon_enforced_bid()
                 ->bid->bid_role == Bid::BidRole::kBothKAnonModes;
}

bool InterestGroupAuction::HasInterestGroups() const {
  if (!buyer_helpers_.empty()) {
    return true;
  }
  for (const auto& kv : component_auctions_) {
    if (!kv.second->buyer_helpers_.empty()) {
      return true;
    }
  }
  return false;
}

SubresourceUrlBuilder* InterestGroupAuction::SubresourceUrlBuilderIfReady() {
  if (!subresource_url_builder_ &&
      !config_->direct_from_seller_signals.is_promise()) {
    subresource_url_builder_ = std::make_unique<SubresourceUrlBuilder>(
        config_->direct_from_seller_signals.value());
  }

  return subresource_url_builder_.get();
}

void InterestGroupAuction::
    TakeDebugReportUrlsAndFillInPrivateAggregationRequests(
        std::vector<GURL>& debug_win_report_urls,
        std::vector<GURL>& debug_loss_report_urls) {
  if (!all_bids_scored_) {
    return;
  }

  // Set `winner` to the BidState in this auction associated with the winning
  // bid of the top-level auction, if there is one.
  //
  // In a component auction, the highest bid may have lost the top-level
  // auction, and we want to report that as a loss. In this case, AuctionResult
  // will be kComponentLostAuction.
  //
  // Also for the top-level auction in the case a component auctions bid won,
  // the highest bid's BidState and its reporting URLs are stored with the
  // component auction, so the component auction will be the one to populate
  // `debug_win_report_urls`.
  BidState* winner = nullptr;
  const LeaderInfo& leader = leader_info();
  if (final_auction_result_ == AuctionResult::kSuccess &&
      leader.top_bid->bid->auction == this) {
    winner = leader.top_bid->bid->bid_state;
  }

  BidState* non_kanon_winner = nullptr;
  if (kanon_mode_ == auction_worklet::mojom::KAnonymityBidMode::kEnforce &&
      HasNonKAnonWinner() && !NonKAnonWinnerIsKAnon()) {
    non_kanon_winner = top_non_kanon_enforced_bid()->bid->bid_state;
  }

  // `signals` includes post auction signals from current auction.
  PostAuctionSignals signals;

  // `top_level_signals` includes post auction signals from top-level auction.
  // Will only will be used in debug report URLs of top-level seller and
  // component sellers.
  // For now, we're assuming top-level auctions to be first-price auction only
  // (not second-price auction) and it does not need highest_scoring_other_bid.
  absl::optional<PostAuctionSignals> top_level_signals;
  if (parent_) {
    top_level_signals.emplace();
  }

  if (!leader.top_bid) {
    DCHECK_EQ(leader.highest_scoring_other_bid, 0);
    DCHECK(!leader.highest_scoring_other_bid_owner.has_value());
  }

  std::map<InterestGroupAuctionReporter::PrivateAggregationKey,
           PrivateAggregationRequests>
      private_aggregation_requests_reserved;
  std::map<std::string, PrivateAggregationRequests>
      private_aggregation_requests_non_reserved;

  for (const auto& buyer_helper : buyer_helpers_) {
    const url::Origin& owner = buyer_helper->owner();
    ComputePostAuctionSignals(owner, signals, top_level_signals);
    buyer_helper->TakeDebugReportUrls(winner, signals, top_level_signals,
                                      debug_win_report_urls,
                                      debug_loss_report_urls);

    buyer_helper->TakePrivateAggregationRequests(
        winner, non_kanon_winner, signals, top_level_signals,
        private_aggregation_requests_reserved,
        private_aggregation_requests_non_reserved);
  }

  for (std::unique_ptr<BidState>& bid_state : bid_states_for_additional_bids_) {
    const url::Origin& owner = bid_state->additional_bid_buyer.value();
    ComputePostAuctionSignals(owner, signals, top_level_signals);
    TakePrivateAggregationRequestsForBidState(
        bid_state, /*is_component_auction=*/parent_ != nullptr, winner,
        non_kanon_winner, signals, top_level_signals,
        private_aggregation_requests_reserved,
        private_aggregation_requests_non_reserved);
    TakeDebugReportUrlsForBidState(bid_state, winner, signals,
                                   top_level_signals, debug_win_report_urls,
                                   debug_loss_report_urls);
  }

  for (auto& [key, requests] : private_aggregation_requests_reserved) {
    PrivateAggregationRequests& destination_vector =
        private_aggregation_requests_reserved_[key];
    destination_vector.insert(destination_vector.end(),
                              std::move_iterator(requests.begin()),
                              std::move_iterator(requests.end()));
  }
  for (auto& [event_type, requests] :
       private_aggregation_requests_non_reserved) {
    PrivateAggregationRequests& destination_vector =
        private_aggregation_requests_non_reserved_[event_type];
    destination_vector.insert(destination_vector.end(),
                              std::move_iterator(requests.begin()),
                              std::move_iterator(requests.end()));
  }

  // Retrieve data from component auctions as well.
  for (auto& component_auction_info : component_auctions_) {
    component_auction_info.second
        ->TakeDebugReportUrlsAndFillInPrivateAggregationRequests(
            debug_win_report_urls, debug_loss_report_urls);
  }
}

std::map<InterestGroupAuctionReporter::PrivateAggregationKey,
         InterestGroupAuction::PrivateAggregationRequests>
InterestGroupAuction::TakeReservedPrivateAggregationRequests() {
  for (auto& component_auction_info : component_auctions_) {
    std::map<InterestGroupAuctionReporter::PrivateAggregationKey,
             PrivateAggregationRequests>
        requests_map = component_auction_info.second
                           ->TakeReservedPrivateAggregationRequests();
    for (auto& [agg_key, requests] : requests_map) {
      DCHECK(!requests.empty());
      PrivateAggregationRequests& destination_vector =
          private_aggregation_requests_reserved_[agg_key];
      destination_vector.insert(destination_vector.end(),
                                std::move_iterator(requests.begin()),
                                std::move_iterator(requests.end()));
    }
  }
  return std::move(private_aggregation_requests_reserved_);
}

std::map<std::string, InterestGroupAuction::PrivateAggregationRequests>
InterestGroupAuction::TakeNonReservedPrivateAggregationRequests() {
  for (auto& component_auction_info : component_auctions_) {
    std::map<std::string, PrivateAggregationRequests> requests_map =
        component_auction_info.second
            ->TakeNonReservedPrivateAggregationRequests();
    for (auto& [event_type, requests] : requests_map) {
      DCHECK(!requests.empty());
      PrivateAggregationRequests& destination_vector =
          private_aggregation_requests_non_reserved_[event_type];
      destination_vector.insert(destination_vector.end(),
                                std::move_iterator(requests.begin()),
                                std::move_iterator(requests.end()));
    }
  }
  return std::move(private_aggregation_requests_non_reserved_);
}

std::vector<std::string> InterestGroupAuction::TakeErrors() {
  for (auto& component_auction_info : component_auctions_) {
    std::vector<std::string> errors =
        component_auction_info.second->TakeErrors();
    errors_.insert(errors_.begin(), errors.begin(), errors.end());
  }
  return std::move(errors_);
}

void InterestGroupAuction::TakePostAuctionUpdateOwners(
    std::vector<url::Origin>& owners) {
  for (const url::Origin& owner : post_auction_update_owners_) {
    owners.emplace_back(std::move(owner));
  }

  for (auto& component_auction_info : component_auctions_) {
    component_auction_info.second->TakePostAuctionUpdateOwners(owners);
  }
}

bool InterestGroupAuction::ReportInterestGroupCount(
    const blink::InterestGroup& interest_group,
    size_t count) {
  return ReportPaBuyersValueIfAllowed(
      interest_group, blink::SellerCapabilities::kInterestGroupCounts,
      blink::AuctionConfig::NonSharedParams::BuyerReportType::
          kInterestGroupCount,
      count);
}

bool InterestGroupAuction::ReportBidCount(
    const blink::InterestGroup& interest_group,
    size_t count) {
  return ReportPaBuyersValueIfAllowed(
      interest_group, blink::SellerCapabilities::kInterestGroupCounts,
      blink::AuctionConfig::NonSharedParams::BuyerReportType::kBidCount, count);
}

void InterestGroupAuction::ReportTrustedSignalsFetchLatency(
    const blink::InterestGroup& interest_group,
    base::TimeDelta trusted_signals_fetch_latency) {
  ReportPaBuyersValueIfAllowed(interest_group,
                               blink::SellerCapabilities::kLatencyStats,
                               blink::AuctionConfig::NonSharedParams::
                                   BuyerReportType::kTotalSignalsFetchLatency,
                               trusted_signals_fetch_latency.InMilliseconds());
}

void InterestGroupAuction::ReportBiddingLatency(
    const blink::InterestGroup& interest_group,
    base::TimeDelta bidding_latency) {
  ReportPaBuyersValueIfAllowed(interest_group,
                               blink::SellerCapabilities::kLatencyStats,
                               blink::AuctionConfig::NonSharedParams::
                                   BuyerReportType::kTotalGenerateBidLatency,
                               bidding_latency.InMilliseconds());
}

base::flat_set<std::string> InterestGroupAuction::GetKAnonKeysToJoin() const {
  if (!HasNonKAnonWinner()) {
    return {};
  }

  // If the k-anon winner is the same as the non-k-anon winner then just include
  // it once.
  std::vector<const ScoredBid*> bids_to_include = {
      top_non_kanon_enforced_bid()};
  if (!NonKAnonWinnerIsKAnon()) {
    bids_to_include.push_back(top_kanon_enforced_bid());
  }

  // Add all the KAnon keys for the winning k-anon and non-k-anon bids.
  std::vector<std::string> k_anon_keys_to_join;
  for (const ScoredBid* scored_bid : bids_to_include) {
    if (!scored_bid) {
      continue;
    }
    if (scored_bid->bid->bid_state->additional_bid_buyer.has_value()) {
      continue;
    }
    DCHECK(scored_bid->bid);
    const blink::InterestGroup& interest_group =
        *scored_bid->bid->interest_group;
    k_anon_keys_to_join.push_back(blink::KAnonKeyForAdBid(
        interest_group, scored_bid->bid->bid_ad->render_url));
    k_anon_keys_to_join.push_back(blink::KAnonKeyForAdNameReporting(
        interest_group, *scored_bid->bid->bid_ad));
    for (const blink::AdDescriptor& ad_component_descriptor :
         scored_bid->bid->ad_component_descriptors) {
      k_anon_keys_to_join.push_back(
          blink::KAnonKeyForAdComponentBid(ad_component_descriptor));
    }
  }
  return base::flat_set<std::string>(std::move(k_anon_keys_to_join));
}

void InterestGroupAuction::MaybeLogPrivateAggregationWebFeatures(
    const std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr>&
        private_aggregation_requests) {
  DCHECK(maybe_log_private_aggregation_web_features_callback_);
  maybe_log_private_aggregation_web_features_callback_.Run(
      private_aggregation_requests);
}

const InterestGroupAuction::LeaderInfo& InterestGroupAuction::leader_info()
    const {
  if (kanon_mode_ == auction_worklet::mojom::KAnonymityBidMode::kEnforce) {
    return kanon_enforced_auction_leader_;
  } else {
    return non_kanon_enforced_auction_leader_;
  }
}

InterestGroupAuction::ScoredBid*
InterestGroupAuction::top_kanon_enforced_bid() {
  return kanon_enforced_auction_leader_.top_bid.get();
}
const InterestGroupAuction::ScoredBid*
InterestGroupAuction::top_kanon_enforced_bid() const {
  return kanon_enforced_auction_leader_.top_bid.get();
}

InterestGroupAuction::ScoredBid*
InterestGroupAuction::top_non_kanon_enforced_bid() {
  return non_kanon_enforced_auction_leader_.top_bid.get();
}

const InterestGroupAuction::ScoredBid*
InterestGroupAuction::top_non_kanon_enforced_bid() const {
  return non_kanon_enforced_auction_leader_.top_bid.get();
}

void InterestGroupAuction::ComputePostAuctionSignals(
    const url::Origin& bid_owner,
    PostAuctionSignals& signals_out,
    absl::optional<PostAuctionSignals>& top_level_signals_out) {
  DCHECK(!parent_ || top_level_signals_out.has_value());
  const LeaderInfo& leader = leader_info();
  if (leader.top_bid) {
    PostAuctionSignals::FillWinningBidInfo(
        bid_owner, leader.top_bid->bid->interest_group->owner,
        leader.top_bid->bid->bid, leader.top_bid->bid_in_seller_currency,
        config_->non_shared_params.seller_currency,
        signals_out.made_winning_bid, signals_out.winning_bid,
        signals_out.winning_bid_currency);
  }

  PostAuctionSignals::FillRelevantHighestScoringOtherBidInfo(
      bid_owner, leader.highest_scoring_other_bid_owner,
      leader.highest_scoring_other_bid,
      leader.highest_scoring_other_bid_in_seller_currency,
      config_->non_shared_params.seller_currency,
      signals_out.made_highest_scoring_other_bid,
      signals_out.highest_scoring_other_bid,
      signals_out.highest_scoring_other_bid_currency);

  if (parent_ && parent_->top_bid()) {
    PostAuctionSignals::FillWinningBidInfo(
        bid_owner, parent_->top_bid()->bid->interest_group->owner,
        parent_->top_bid()->bid->bid,
        parent_->top_bid()->bid_in_seller_currency,
        parent_->config_->non_shared_params.seller_currency,
        top_level_signals_out->made_winning_bid,
        top_level_signals_out->winning_bid,
        top_level_signals_out->winning_bid_currency);
  }
}

absl::optional<uint16_t> InterestGroupAuction::GetBuyerExperimentId(
    const blink::AuctionConfig& config,
    const url::Origin& buyer) {
  auto it = config.per_buyer_experiment_group_ids.find(buyer);
  if (it != config.per_buyer_experiment_group_ids.end()) {
    return it->second;
  }
  return config.all_buyer_experiment_group_id;
}

absl::optional<std::string> InterestGroupAuction::GetPerBuyerSignals(
    const blink::AuctionConfig& config,
    const url::Origin& buyer) {
  const auto& auction_config_per_buyer_signals =
      config.non_shared_params.per_buyer_signals;
  DCHECK(!auction_config_per_buyer_signals.is_promise());
  if (auction_config_per_buyer_signals.value().has_value()) {
    auto it = auction_config_per_buyer_signals.value()->find(buyer);
    if (it != auction_config_per_buyer_signals.value()->end()) {
      return it->second;
    }
  }
  return absl::nullopt;
}

absl::optional<GURL> InterestGroupAuction::GetDirectFromSellerAuctionSignals(
    const SubresourceUrlBuilder* subresource_url_builder) {
  if (subresource_url_builder && subresource_url_builder->auction_signals()) {
    return subresource_url_builder->auction_signals()->subresource_url;
  }
  return absl::nullopt;
}

absl::optional<std::string>
InterestGroupAuction::GetDirectFromSellerAuctionSignalsHeaderAdSlot(
    const HeaderDirectFromSellerSignals& signals) {
  return signals.auction_signals();
}

absl::optional<GURL> InterestGroupAuction::GetDirectFromSellerPerBuyerSignals(
    const SubresourceUrlBuilder* subresource_url_builder,
    const url::Origin& owner) {
  if (!subresource_url_builder) {
    return absl::nullopt;
  }

  auto it = subresource_url_builder->per_buyer_signals().find(owner);
  if (it == subresource_url_builder->per_buyer_signals().end()) {
    return absl::nullopt;
  }
  return it->second.subresource_url;
}

absl::optional<std::string>
InterestGroupAuction::GetDirectFromSellerPerBuyerSignalsHeaderAdSlot(
    const HeaderDirectFromSellerSignals& signals,
    const url::Origin& owner) {
  auto it = signals.per_buyer_signals().find(owner);
  if (it == signals.per_buyer_signals().end()) {
    return absl::nullopt;
  }
  return it->second;
}

absl::optional<GURL> InterestGroupAuction::GetDirectFromSellerSellerSignals(
    const SubresourceUrlBuilder* subresource_url_builder) {
  if (subresource_url_builder && subresource_url_builder->seller_signals()) {
    return subresource_url_builder->seller_signals()->subresource_url;
  }
  return absl::nullopt;
}

absl::optional<std::string>
InterestGroupAuction::GetDirectFromSellerSellerSignalsHeaderAdSlot(
    const HeaderDirectFromSellerSignals& signals) {
  return signals.seller_signals();
}

InterestGroupAuction::LeaderInfo::LeaderInfo() = default;
InterestGroupAuction::LeaderInfo::~LeaderInfo() = default;

void InterestGroupAuction::OnInterestGroupRead(
    scoped_refptr<StorageInterestGroups> read_interest_groups) {
  ++num_owners_loaded_;
  if (read_interest_groups->size() == 0) {
    OnOneLoadCompleted();
    return;
  }
  std::vector<SingleStorageInterestGroup> interest_groups =
      read_interest_groups->GetInterestGroups();
  for (const SingleStorageInterestGroup& group : interest_groups) {
    if (ReportInterestGroupCount(group->interest_group,
                                 read_interest_groups->size())) {
      break;
    }
  }

  post_auction_update_owners_.emplace_back(
      interest_groups[0]->interest_group.owner);
  for (const SingleStorageInterestGroup& bidder : interest_groups) {
    // Report freshness metrics.
    if (bidder->interest_group.update_url.has_value()) {
      UMA_HISTOGRAM_CUSTOM_COUNTS(
          "Ads.InterestGroup.Auction.GroupFreshness.WithDailyUpdates",
          (base::Time::Now() - bidder->last_updated).InMinutes(),
          kGroupFreshnessMin.InMinutes(), kGroupFreshnessMax.InMinutes(),
          kGroupFreshnessBuckets);
    } else {
      UMA_HISTOGRAM_CUSTOM_COUNTS(
          "Ads.InterestGroup.Auction.GroupFreshness.NoDailyUpdates",
          (base::Time::Now() - bidder->last_updated).InMinutes(),
          kGroupFreshnessMin.InMinutes(), kGroupFreshnessMax.InMinutes(),
          kGroupFreshnessBuckets);
    }
  }

  // Extract negative targeting info, if something may care.
  // This needs to happen before dropping IGs w/o scripts and ads, since
  // negative targeting IGs may lack those.
  if (MayHaveAdditionalBids()) {
    for (const SingleStorageInterestGroup& group : interest_groups) {
      if (group->interest_group.additional_bid_key.has_value()) {
        negative_targeter_->AddInterestGroupInfo(
            group->interest_group.owner, group->interest_group.name,
            group->joining_origin, *group->interest_group.additional_bid_key);
      }
    }
  }

  // Ignore interest groups with no bidding script or no ads.
  base::EraseIf(interest_groups, [](const SingleStorageInterestGroup& bidder) {
    return !bidder->interest_group.bidding_url || !bidder->interest_group.ads ||
           bidder->interest_group.ads->empty();
  });

  // Ignore interest groups that don't provide the requested seller
  // capabilities.
  base::EraseIf(interest_groups,
                [this](const SingleStorageInterestGroup& bidder) {
                  return !GroupSatisfiesAllCapabilities(
                      bidder->interest_group,
                      config_->non_shared_params.required_seller_capabilities,
                      config_->seller);
                });

  // If there are no interest groups left, nothing else to do.
  if (interest_groups.empty()) {
    OnOneLoadCompleted();
    return;
  }

  ++num_owners_with_interest_groups_;
  auction_metrics_recorder_->ReportBuyer(
      interest_groups[0]->interest_group.owner);
  auto buyer_helper =
      std::make_unique<BuyerHelper>(this, std::move(interest_groups));

  // BuyerHelper may filter out additional interest groups on construction.
  if (buyer_helper->has_potential_bidder()) {
    buyer_helpers_.emplace_back(std::move(buyer_helper));
  } else {
    // `buyer_helper` has a raw pointer to `this`, so if it's not added to
    // buyer_helpers_, delete it now to avoid a dangling pointer, since
    // OnOneLoadCompleted() could result in deleting `this`.
    buyer_helper.reset();
  }

  OnOneLoadCompleted();
}

void InterestGroupAuction::OnComponentInterestGroupsRead(
    AuctionMap::iterator component_auction,
    bool success) {
  num_owners_loaded_ += component_auction->second->num_owners_loaded_;
  num_owners_with_interest_groups_ +=
      component_auction->second->num_owners_with_interest_groups_;

  // Erase component auctions that failed their interest group loading phase,
  // so they won't be invoked in the generate bid phase. This is not a problem
  // in the reporting phase, as the top-level auction knows which component
  // auction, if any, won.
  if (!success) {
    component_auctions_.erase(component_auction);
  }
  OnOneLoadCompleted();
}

void InterestGroupAuction::OnOneLoadCompleted() {
  DCHECK_GT(num_pending_loads_, 0u);
  --num_pending_loads_;

  // Wait for more buyers to be loaded, if there are still some pending.
  if (num_pending_loads_ > 0) {
    return;
  }

  // Record histograms about the interest groups participating in the auction.
  // TODO(mmenke): Record histograms for component auctions.
  if (!parent_) {
    // Only record histograms if there were interest groups that could
    // theoretically participate in the auction.
    if (num_owners_loaded_ > 0) {
      size_t num_interest_groups = NumPotentialBidders();
      size_t num_sellers_with_bidders = 0;
      for (const auto& [unused, component] : component_auctions_) {
        if (!component->buyer_helpers_.empty()) {
          ++num_sellers_with_bidders;
        }
      }

      // If the top-level seller either has interest groups itself, or any of
      // the component auctions do, then the top-level seller also has bidders.
      if (num_interest_groups > 0) {
        ++num_sellers_with_bidders;
      }

      auction_metrics_recorder_->SetNumInterestGroups(num_interest_groups);
      auction_metrics_recorder_->SetNumOwnersWithInterestGroups(
          num_owners_with_interest_groups_);
      auction_metrics_recorder_->SetNumSellersWithBidders(
          num_sellers_with_bidders);
    }
  }

  if (MayHaveAdditionalBids()) {
    auction_metrics_recorder_->RecordNegativeInterestGroups(
        negative_targeter_->GetNumNegativeInterestGroups());
  }

  // We generally proceed even if there is seemingly nothing to do since we
  // still may need to wait for promises to resolve and deal with
  // `additional_bids`.
  AuctionResult result = AuctionResult::kSuccess;

  // If the config had components, but none survived the loading phase,
  // they must all have failed permissions checks, so there is no reason
  // to proceed.
  if (!config_->non_shared_params.component_auctions.empty() &&
      component_auctions_.empty()) {
    result = AuctionResult::kNoInterestGroups;
  }

  OnStartLoadInterestGroupsPhaseComplete(result);
}

void InterestGroupAuction::OnStartLoadInterestGroupsPhaseComplete(
    AuctionResult auction_result) {
  DCHECK(load_interest_groups_phase_callback_);
  DCHECK(!final_auction_result_);

  if (!parent_) {
    auction_metrics_recorder_->OnLoadInterestGroupPhaseComplete();
  }
  TRACE_EVENT_NESTABLE_ASYNC_END0("fledge", "load_groups_phase", *trace_id_);

  if (!HasInterestGroups()) {
    UMA_HISTOGRAM_TIMES("Ads.InterestGroup.Auction.LoadNoGroupsTime",
                        base::TimeTicks::Now() - creation_time_);
  } else {
    UMA_HISTOGRAM_TIMES("Ads.InterestGroup.Auction.LoadGroupsTime",
                        base::TimeTicks::Now() - creation_time_);
  }

  // `final_auction_result_` should only be set to kSuccess when the entire
  // auction is complete.
  //
  // TODO(https://crbug.com/1394777): We should probably add new states for
  // whether the result was used, reports sent, etc, so either the
  // InterestGroupAuction or the InterestGroupAuctionReporter logs a single
  // result. Alternatively, we could add a separate histogram just for the
  // reporter stuff, which should have exactly as many entries as the historam
  // `final_auction_result_` is logged to.
  bool success = auction_result == AuctionResult::kSuccess;
  if (!success) {
    final_auction_result_ = auction_result;
  }
  std::move(load_interest_groups_phase_callback_).Run(success);
}

void InterestGroupAuction::OnComponentSellerWorkletReceived() {
  DCHECK_GT(pending_component_seller_worklet_requests_, 0u);
  --pending_component_seller_worklet_requests_;
  if (pending_component_seller_worklet_requests_ == 0) {
    RequestSellerWorklet();
  }
}

void InterestGroupAuction::RequestSellerWorklet() {
  DCHECK_EQ(bidding_and_scoring_phase_state_, PhaseState::kDuring);
  TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("fledge", "request_seller_worklet",
                                    *trace_id_);
  auction_worklet_manager_->RequestSellerWorklet(
      *config_->decision_logic_url, config_->trusted_scoring_signals_url,
      config_->seller_experiment_group_id,
      base::BindOnce(&InterestGroupAuction::OnSellerWorkletReceived,
                     base::Unretained(this)),
      base::BindOnce(&InterestGroupAuction::OnSellerWorkletFatalError,
                     base::Unretained(this)),
      seller_worklet_handle_);
}

void InterestGroupAuction::OnSellerWorkletReceived() {
  DCHECK(!seller_worklet_received_);
  DCHECK_EQ(bidding_and_scoring_phase_state_, PhaseState::kDuring);

  TRACE_EVENT_NESTABLE_ASYNC_END0("fledge", "request_seller_worklet",
                                  *trace_id_);

  if (on_seller_receiver_callback_) {
    std::move(on_seller_receiver_callback_).Run();
  }

  seller_worklet_received_ = true;

  base::TimeTicks now = base::TimeTicks::Now();
  for (auto& unscored_bid : unscored_bids_) {
    unscored_bid->wait_worklet =
        now - unscored_bid->trace_wait_seller_deps_start;

    if (!component_auctions_.empty()) {
      auction_metrics_recorder_->RecordTopLevelBidQueuedWaitingForSellerWorklet(
          unscored_bid->wait_worklet);
    } else {
      auction_metrics_recorder_->RecordBidQueuedWaitingForSellerWorklet(
          unscored_bid->wait_worklet);
    }
  }

  ScoreQueuedBidsIfReady();
}

void InterestGroupAuction::ScoreQueuedBidsIfReady() {
  DCHECK_EQ(bidding_and_scoring_phase_state_, PhaseState::kDuring);
  if (!ReadyToScoreBids() || unscored_bids_.empty()) {
    return;
  }

  auto unscored_bids = std::move(unscored_bids_);
  for (auto& unscored_bid : unscored_bids) {
    TRACE_EVENT_NESTABLE_ASYNC_END1(
        "fledge", "wait_for_seller_deps", unscored_bid->TraceId(), "data",
        [&](perfetto::TracedValue trace_context) {
          auto dict = std::move(trace_context).WriteDictionary();
          if (!unscored_bid->wait_worklet.is_zero()) {
            dict.Add("wait_worklet_ms",
                     unscored_bid->wait_worklet.InMillisecondsF());
          }
          if (!unscored_bid->wait_promises.is_zero()) {
            dict.Add("wait_promises_ms",
                     unscored_bid->wait_promises.InMillisecondsF());
          }
        });
    ScoreBidIfReady(std::move(unscored_bid));
  }

  // If no further bids are outstanding, now is the time to send a coalesced
  // request for all the trusted seller signals (if some still are pending,
  // OnScoringDependencyDone() will take care of it).
  if (num_scoring_dependencies_ == 0) {
    seller_worklet_handle_->GetSellerWorklet()->SendPendingSignalsRequests();
  }

  // No more unscored bids should be added, once the seller worklet has been
  // received.
  DCHECK(unscored_bids_.empty());
}

void InterestGroupAuction::HandleAdditionalBidError(AdditionalBidResult result,
                                                    std::string error) {
  auction_metrics_recorder_->RecordAdditionalBidResult(result);
  errors_.push_back(std::move(error));
  OnScoringDependencyDone();
}

void InterestGroupAuction::DecodeAdditionalBidsIfReady() {
  DCHECK_EQ(bidding_and_scoring_phase_state_, PhaseState::kDuring);
  if (encoded_signed_additional_bids_.empty()) {
    return;
  }
  decode_additional_bids_start_time_ = base::TimeTicks::Now();

  num_scoring_dependencies_ += encoded_signed_additional_bids_.size();
  for (const auto& encoded_signed_bid : encoded_signed_additional_bids_) {
    std::string signed_additional_bid_data;
    if (!base::Base64Decode(encoded_signed_bid, &signed_additional_bid_data,
                            base::Base64DecodePolicy::kForgiving)) {
      HandleAdditionalBidError(
          AdditionalBidResult::kRejectedDueToInvalidBase64,
          "Unable to base64-decode a signed additional bid.");
      continue;
    }
    data_decoder_->ParseJson(
        signed_additional_bid_data,
        base::BindOnce(&InterestGroupAuction::HandleDecodedSignedAdditionalBid,
                       weak_ptr_factory_.GetWeakPtr()));
  }
  encoded_signed_additional_bids_.clear();
}

void InterestGroupAuction::HandleDecodedSignedAdditionalBid(
    data_decoder::DataDecoder::ValueOrError result) {
  DCHECK_EQ(bidding_and_scoring_phase_state_, PhaseState::kDuring);
  if (!result.has_value()) {
    HandleAdditionalBidError(
        AdditionalBidResult::kRejectedDueToSignedBidJsonParseError,
        "Unable to parse signed additional bid as JSON: " + result.error());
    return;
  }

  auto maybe_signed_additional_bid =
      DecodeSignedAdditionalBid(std::move(result).value());
  if (!maybe_signed_additional_bid.has_value()) {
    HandleAdditionalBidError(
        AdditionalBidResult::kRejectedDueToSignedBidDecodeError,
        "Unable to decode signed additional bid: " +
            maybe_signed_additional_bid.error());
    return;
  }

  auto valid_signatures = maybe_signed_additional_bid->VerifySignatures();

  data_decoder_->ParseJson(
      maybe_signed_additional_bid->additional_bid_json,
      base::BindOnce(&InterestGroupAuction::HandleDecodedAdditionalBid,
                     weak_ptr_factory_.GetWeakPtr(),
                     std::move(maybe_signed_additional_bid->signatures),
                     std::move(valid_signatures)));
}

void InterestGroupAuction::HandleDecodedAdditionalBid(
    const std::vector<SignedAdditionalBidSignature>& signatures,
    const std::vector<size_t>& valid_signatures,
    data_decoder::DataDecoder::ValueOrError result) {
  DCHECK_EQ(bidding_and_scoring_phase_state_, PhaseState::kDuring);
  if (!result.has_value()) {
    HandleAdditionalBidError(
        AdditionalBidResult::kRejectedDueToJsonParseError,
        "Unable to parse additional bid as JSON: " + result.error());
    return;
  }

  base::expected<AdditionalBidDecodeResult, std::string> maybe_bid =
      DecodeAdditionalBid(
          this, result.value(),
          config_->non_shared_params.auction_nonce.value(),
          interest_group_buyers_, config_->seller,
          parent_
              ? base::optional_ref<const url::Origin>(parent_->config_->seller)
              : base::optional_ref<const url::Origin>(absl::nullopt));
  if (!maybe_bid.has_value()) {
    HandleAdditionalBidError(AdditionalBidResult::kRejectedDueToDecodeError,
                             std::move(maybe_bid).error());
    return;
  }

  if (!is_interest_group_api_allowed_callback_.Run(
          ContentBrowserClient::InterestGroupApiOperation::kBuy,
          maybe_bid->bid_state->bidder->interest_group.owner)) {
    HandleAdditionalBidError(
        AdditionalBidResult::kRejectedDueToBuyerNotAllowed,
        "Rejecting an additionalBid due to operation not allowed for buyer.");
    return;
  }

  if (!blink::VerifyAdCurrencyCode(
          PerBuyerCurrency(*maybe_bid->bid_state->additional_bid_buyer,
                           *config_),
          maybe_bid->bid->bid_currency)) {
    HandleAdditionalBidError(
        AdditionalBidResult::kRejectedDueToCurrencyMismatch,
        "Rejecting an additionalBid due to currency mismatch.");
    return;
  }

  if (negative_targeter_->ShouldDropDueToNegativeTargeting(
          *maybe_bid->bid_state->additional_bid_buyer,
          maybe_bid->negative_target_joining_origin,
          maybe_bid->negative_target_interest_group_names, signatures,
          valid_signatures, config_->seller, *auction_metrics_recorder_,
          errors_)) {
    // We do *not* call HandleAdditionalBidError at this point because an
    // additional bid being negative targeted is not an error scenario, so we
    // don't want to record anything to the errors_.
    auction_metrics_recorder_->RecordAdditionalBidResult(
        AdditionalBidResult::kNegativeTargeted);
    auction_metrics_recorder_->RecordAdditionalBidDecodeLatency(
        base::TimeTicks::Now() - decode_additional_bids_start_time_);
    OnScoringDependencyDone();
    return;
  }

  auction_metrics_recorder_->RecordAdditionalBidResult(
      AdditionalBidResult::kSentForScoring);
  auction_metrics_recorder_->RecordAdditionalBidDecodeLatency(
      base::TimeTicks::Now() - decode_additional_bids_start_time_);
  bid_states_for_additional_bids_.push_back(std::move(maybe_bid->bid_state));
  ScoreBidIfReady(std::move(maybe_bid->bid));
  OnScoringDependencyDone();
}

void InterestGroupAuction::OnSellerWorkletFatalError(
    AuctionWorkletManager::FatalErrorType fatal_error_type,
    const std::vector<std::string>& errors) {
  DCHECK_EQ(bidding_and_scoring_phase_state_, PhaseState::kDuring);
  AuctionResult result;
  switch (fatal_error_type) {
    case AuctionWorkletManager::FatalErrorType::kScriptLoadFailed:
      result = AuctionResult::kSellerWorkletLoadFailed;
      break;
    case AuctionWorkletManager::FatalErrorType::kWorkletCrash:
      result = AuctionResult::kSellerWorkletCrashed;
      break;
  }

  OnBiddingAndScoringComplete(result, errors);
}

void InterestGroupAuction::OnComponentAuctionComplete(
    InterestGroupAuction* component_auction,
    bool success) {
  DCHECK_EQ(bidding_and_scoring_phase_state_, PhaseState::kDuring);
  if (!component_auction->buyer_helpers_.empty() ||
      !component_auction->bid_states_for_additional_bids_.empty()) {
    auction_metrics_recorder_->RecordComponentAuctionLatency(
        base::TimeTicks::Now() - bidding_and_scoring_phase_start_time_);
  }

  // TODO(morlovich): Can try to consolidate these as kBothKAnonModes when
  // possible.
  ScoredBid* non_kanon_enforced_bid =
      component_auction->top_non_kanon_enforced_bid();
  if (non_kanon_enforced_bid) {
    // There is no need to potentially turn this into an k-anon enforced bid
    // since that already happened when running the component auction.
    ScoreBidIfReady(CreateBidFromComponentAuctionWinner(
        non_kanon_enforced_bid, Bid::BidRole::kUnenforcedKAnon));
  }

  ScoredBid* kanon_bid = component_auction->top_kanon_enforced_bid();
  if (kanon_bid) {
    ScoreBidIfReady(CreateBidFromComponentAuctionWinner(
        kanon_bid, Bid::BidRole::kEnforcedKAnon));
  }

  OnScoringDependencyDone();
}

// static
std::unique_ptr<InterestGroupAuction::Bid>
InterestGroupAuction::CreateBidFromComponentAuctionWinner(
    const ScoredBid* scored_bid,
    Bid::BidRole bid_role) {
  // Create a copy of component Auction's bid, replacing values as necessary.
  const Bid* component_bid = scored_bid->bid.get();
  const auto* modified_bid_params =
      scored_bid->component_auction_modified_bid_params.get();
  DCHECK(modified_bid_params);

  // Create a new event for the bid, since the component auction's event for
  // it ended after the component auction scored the bid.
  if (bid_role == Bid::BidRole::kEnforcedKAnon) {
    if (!component_bid->bid_state->trace_id_for_kanon_scoring.has_value()) {
      component_bid->bid_state->BeginTracingKAnonScoring();
    }
  } else {
    if (!component_bid->bid_state->trace_id.has_value()) {
      component_bid->bid_state->BeginTracing();
    }
  }

  return std::make_unique<Bid>(
      bid_role, modified_bid_params->ad,
      modified_bid_params->has_bid ? modified_bid_params->bid
                                   : component_bid->bid,
      modified_bid_params->has_bid ? modified_bid_params->bid_currency
                                   : component_bid->bid_currency,
      component_bid->ad_cost, component_bid->ad_descriptor,
      component_bid->ad_component_descriptors, component_bid->modeling_signals,
      component_bid->bid_duration, component_bid->bidding_signals_data_version,
      component_bid->bid_ad, component_bid->bid_state, component_bid->auction);
}

void InterestGroupAuction::OnScoringDependencyDone() {
  DCHECK_EQ(bidding_and_scoring_phase_state_, PhaseState::kDuring);
  --num_scoring_dependencies_;

  // If we issued the final set of bids to a seller worklet, tell it to send any
  // pending scoring signals request to complete the auction more quickly.
  if (num_scoring_dependencies_ == 0 && ReadyToScoreBids()) {
    seller_worklet_handle_->GetSellerWorklet()->SendPendingSignalsRequests();
  }

  MaybeCompleteBiddingAndScoringPhase();
}

void InterestGroupAuction::ScoreBidIfReady(std::unique_ptr<Bid> bid) {
  DCHECK_EQ(bidding_and_scoring_phase_state_, PhaseState::kDuring);
  DCHECK(bid);
  DCHECK(bid->bid_state->made_bid);

  any_bid_made_ = true;

  // If seller worklet hasn't been received yet, or configuration is still
  // waiting on some promises, wait till everything is ready.
  // TODO(morlovich): Tracing doesn't reflect config wait here.
  uint64_t bid_trace_id = bid->TraceId();
  if (!ReadyToScoreBids()) {
    bid->trace_wait_seller_deps_start = base::TimeTicks::Now();
    TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("fledge", "wait_for_seller_deps",
                                      bid_trace_id);
    unscored_bids_.emplace_back(std::move(bid));
    return;
  }

  TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("fledge", ScoreAdTraceEventName(*bid),
                                    bid_trace_id, "decision_logic_url",
                                    config_->decision_logic_url);
  bid->seller_worklet_score_ad_start = base::TimeTicks::Now();

  ++bids_being_scored_;
  Bid* bid_raw = bid.get();

  mojo::PendingRemote<auction_worklet::mojom::ScoreAdClient> score_ad_remote;
  score_ad_receivers_.Add(
      this, score_ad_remote.InitWithNewPipeAndPassReceiver(), std::move(bid));
  DCHECK_EQ(0, config_->NumPromises());
  SubresourceUrlBuilder* url_builder = SubresourceUrlBuilderIfReady();
  DCHECK(url_builder);  // Should be ready by now.
  seller_worklet_handle_->AuthorizeSubresourceUrls(*url_builder);
  seller_worklet_handle_->GetSellerWorklet()->ScoreAd(
      bid_raw->ad_metadata, bid_raw->bid, bid_raw->bid_currency,
      config_->non_shared_params, GetDirectFromSellerSellerSignals(url_builder),
      GetDirectFromSellerSellerSignalsHeaderAdSlot(
          *direct_from_seller_signals_header_ad_slot_),
      GetDirectFromSellerAuctionSignals(url_builder),
      GetDirectFromSellerAuctionSignalsHeaderAdSlot(
          *direct_from_seller_signals_header_ad_slot_),
      GetOtherSellerParam(*bid_raw),
      parent_ ? PerBuyerCurrency(config_->seller, *parent_->config_)
              : absl::nullopt,
      bid_raw->interest_group->owner, bid_raw->ad_descriptor.url,
      bid_raw->GetAdComponentUrls(), bid_raw->bid_duration.InMilliseconds(),
      SellerTimeout(), bid_trace_id, std::move(score_ad_remote));
}

bool InterestGroupAuction::ValidateScoreBidCompleteResult(
    double score,
    auction_worklet::mojom::ComponentAuctionModifiedBidParams*
        component_auction_modified_bid_params,
    absl::optional<double> bid_in_seller_currency,
    const absl::optional<GURL>& debug_loss_report_url,
    const absl::optional<GURL>& debug_win_report_url) {
  DCHECK_EQ(bidding_and_scoring_phase_state_, PhaseState::kDuring);
  // If `debug_loss_report_url` or `debug_win_report_url` is not a valid HTTPS
  // URL, the auction should fail because the worklet is compromised.
  if (debug_loss_report_url.has_value() &&
      !IsUrlValid(debug_loss_report_url.value())) {
    score_ad_receivers_.ReportBadMessage(
        "Invalid seller debugging loss report URL");
    return false;
  }
  if (debug_win_report_url.has_value() &&
      !IsUrlValid(debug_win_report_url.value())) {
    score_ad_receivers_.ReportBadMessage(
        "Invalid seller debugging win report URL");
    return false;
  }

  // Only validate `component_auction_modified_bid_params` if the bid was
  // accepted.
  if (score > 0) {
    // If they accept a bid / return a positive score, component auction
    // SellerWorklets must return a `component_auction_modified_bid_params`,
    // and top-level auctions must not.
    if ((parent_ == nullptr) !=
        (component_auction_modified_bid_params == nullptr)) {
      score_ad_receivers_.ReportBadMessage(
          "Invalid component_auction_modified_bid_params");
      return false;
    }
    // If a component seller modified the bid, the new bid must also be valid,
    // as should its currency.
    if (component_auction_modified_bid_params &&
        component_auction_modified_bid_params->has_bid) {
      if (!IsValidBid(component_auction_modified_bid_params->bid)) {
        score_ad_receivers_.ReportBadMessage(
            "Invalid component_auction_modified_bid_params bid");
        return false;
      }

      if (!blink::VerifyAdCurrencyCode(
              config_->non_shared_params.seller_currency,
              component_auction_modified_bid_params->bid_currency) ||
          !blink::VerifyAdCurrencyCode(
              PerBuyerCurrency(config_->seller, *parent_->config_),
              component_auction_modified_bid_params->bid_currency)) {
        score_ad_receivers_.ReportBadMessage(
            "Invalid component_auction_modified_bid_params bid_currency");
        return false;
      }
    }
  }
  if (bid_in_seller_currency.has_value() &&
      (!IsValidBid(*bid_in_seller_currency) ||
       !config_->non_shared_params.seller_currency.has_value())) {
    score_ad_receivers_.ReportBadMessage("Invalid bid_in_seller_currency");
    return false;
  }
  return true;
}

void InterestGroupAuction::OnScoreAdComplete(
    double score,
    auction_worklet::mojom::RejectReason reject_reason,
    auction_worklet::mojom::ComponentAuctionModifiedBidParamsPtr
        component_auction_modified_bid_params,
    absl::optional<double> bid_in_seller_currency,
    absl::optional<uint32_t> scoring_signals_data_version,
    const absl::optional<GURL>& debug_loss_report_url,
    const absl::optional<GURL>& debug_win_report_url,
    PrivateAggregationRequests pa_requests,
    base::TimeDelta scoring_latency,
    auction_worklet::mojom::ScoreAdDependencyLatenciesPtr
        score_ad_dependency_latencies,
    const std::vector<std::string>& errors) {
  DCHECK_EQ(bidding_and_scoring_phase_state_, PhaseState::kDuring);
  DCHECK_GT(bids_being_scored_, 0);

  if (!ValidateScoreBidCompleteResult(
          score, component_auction_modified_bid_params.get(),
          bid_in_seller_currency, debug_loss_report_url,
          debug_win_report_url)) {
    OnBiddingAndScoringComplete(AuctionResult::kBadMojoMessage);
    return;
  }

  std::unique_ptr<Bid> bid = std::move(score_ad_receivers_.current_context());
  score_ad_receivers_.Remove(score_ad_receivers_.current_receiver());

  auction_metrics_recorder_->RecordScoreAdFlowLatency(
      base::TimeTicks::Now() - bid->seller_worklet_score_ad_start);
  auction_metrics_recorder_->RecordScoreAdLatency(scoring_latency);
  auction_metrics_recorder_->RecordScoreAdDependencyLatencies(
      *score_ad_dependency_latencies);

  TRACE_EVENT_NESTABLE_ASYNC_END0("fledge", ScoreAdTraceEventName(*bid),
                                  bid->TraceId());
  if (bid->bid_role == Bid::BidRole::kEnforcedKAnon) {
    bid->bid_state->EndTracingKAnonScoring();
  } else {
    bid->bid_state->EndTracing();
  }
  bid->bid_state->pa_timings(seller_phase()).script_run_time = scoring_latency;
  bid->bid_state->pa_timings(seller_phase()).signals_fetch_time =
      score_ad_dependency_latencies->trusted_scoring_signals_latency.value_or(
          base::TimeDelta());

  --bids_being_scored_;

  // Reporting and the like should be done only for things that go into the
  // run that produces the result of runAdAuction().
  if (IsBidRoleUsedForWinner(kanon_mode_, bid->bid_role)) {
    // The mojom API declaration should ensure none of these are null.
    DCHECK(base::ranges::none_of(
        pa_requests,
        [](const auction_worklet::mojom::PrivateAggregationRequestPtr&
               request_ptr) { return request_ptr.is_null(); }));
    MaybeLogPrivateAggregationWebFeatures(pa_requests);
    if (!pa_requests.empty()) {
      DCHECK(config_);
      BidState::PrivateAggregationPhaseKey agg_key = {
          config_->seller, seller_phase(),
          config_->aggregation_coordinator_origin};
      PrivateAggregationRequests& pa_requests_for_seller =
          bid->bid_state->private_aggregation_requests[std::move(agg_key)];
      for (auction_worklet::mojom::PrivateAggregationRequestPtr& request :
           pa_requests) {
        // A for-event private aggregation request with non-reserved event type
        // from scoreAd() should be ignored and not reported.
        if (request->contribution->is_for_event_contribution() &&
            !base::StartsWith(
                request->contribution->get_for_event_contribution()->event_type,
                "reserved.")) {
          continue;
        }
        pa_requests_for_seller.emplace_back(std::move(request));
      }
    }

    // Use separate fields for component and top-level seller reports, so both
    // can send debug reports.
    if (bid->auction == this) {
      bid->bid_state->seller_debug_loss_report_url =
          std::move(debug_loss_report_url);
      bid->bid_state->seller_debug_win_report_url =
          std::move(debug_win_report_url);
      // Ignores reject reason if score > 0.
      // TODO(qingxinwu): Set bid_state->reject_reason to nullopt instead of
      // kNotAvailable when score > 0.
      if (score <= 0) {
        bid->bid_state->reject_reason = reject_reason;
      }
    } else {
      bid->bid_state->top_level_seller_debug_loss_report_url =
          std::move(debug_loss_report_url);
      bid->bid_state->top_level_seller_debug_win_report_url =
          std::move(debug_win_report_url);
    }
  }

  // Debug output to developers should include all of errors.
  errors_.insert(errors_.end(), errors.begin(), errors.end());

  // A score <= 0 means the seller rejected the bid.
  if (score > 0) {
    switch (bid->bid_role) {
      case Bid::BidRole::kUnenforcedKAnon:
        UpdateAuctionLeaders(std::move(bid), score,
                             std::move(component_auction_modified_bid_params),
                             bid_in_seller_currency,
                             scoring_signals_data_version,
                             non_kanon_enforced_auction_leader_);
        break;
      case Bid::BidRole::kEnforcedKAnon:
        UpdateAuctionLeaders(std::move(bid), score,
                             std::move(component_auction_modified_bid_params),
                             bid_in_seller_currency,
                             scoring_signals_data_version,
                             kanon_enforced_auction_leader_);
        break;
      case Bid::BidRole::kBothKAnonModes: {
        auto bid_copy = std::make_unique<Bid>(*bid);
        auto modified_bid_params_copy =
            component_auction_modified_bid_params
                ? component_auction_modified_bid_params->Clone()
                : auction_worklet::mojom::
                      ComponentAuctionModifiedBidParamsPtr();
        UpdateAuctionLeaders(std::move(bid), score,
                             std::move(component_auction_modified_bid_params),
                             bid_in_seller_currency,
                             scoring_signals_data_version,
                             non_kanon_enforced_auction_leader_);
        UpdateAuctionLeaders(
            std::move(bid_copy), score, std::move(modified_bid_params_copy),
            bid_in_seller_currency, scoring_signals_data_version,
            kanon_enforced_auction_leader_);
      }
    }
  }

  // Need to delete `bid` because OnBiddingAndScoringComplete() may delete
  // this, which leaves danging pointers on the stack. While this is safe to
  // do (nothing has access to `bid` to dereference them), it makes the
  // dangling pointer tooling sad.
  bid.reset();
  MaybeCompleteBiddingAndScoringPhase();
}

void InterestGroupAuction::UpdateAuctionLeaders(
    std::unique_ptr<Bid> bid,
    double score,
    auction_worklet::mojom::ComponentAuctionModifiedBidParamsPtr
        component_auction_modified_bid_params,
    absl::optional<double> bid_in_seller_currency,
    absl::optional<uint32_t> scoring_signals_data_version,
    LeaderInfo& leader_info) {
  DCHECK_EQ(bidding_and_scoring_phase_state_,
            is_server_auction_ ? PhaseState::kBefore : PhaseState::kDuring);
  bool is_top_bid = false;
  const url::Origin& owner = bid->interest_group->owner;

  if (!leader_info.top_bid || score > leader_info.top_bid->score) {
    // If there's no previous top bidder, or the bidder has the highest score,
    // need to replace the previous top bidder.
    is_top_bid = true;
    if (leader_info.top_bid) {
      OnNewHighestScoringOtherBid(
          leader_info.top_bid->score, leader_info.top_bid->bid->bid,
          leader_info.top_bid->bid_in_seller_currency,
          &leader_info.top_bid->bid->interest_group->owner, leader_info);
    }
    leader_info.num_top_bids = 1;
    leader_info.at_most_one_top_bid_owner = true;
  } else if (score == leader_info.top_bid->score) {
    // If there's a tie, replace the top-bidder with 1-in-`num_top_bids_`
    // chance. This is the select random value from a stream with fixed
    // storage problem.
    ++leader_info.num_top_bids;
    if (1 == base::RandInt(1, leader_info.num_top_bids)) {
      is_top_bid = true;
    }
    if (owner != leader_info.top_bid->bid->interest_group->owner) {
      leader_info.at_most_one_top_bid_owner = false;
    }
    // If the top bid is being replaced, need to add the old top bid as a second
    // highest bid. Otherwise, need to add the current bid as a second highest
    // bid.
    double new_highest_scoring_other_bid =
        is_top_bid ? leader_info.top_bid->bid->bid : bid->bid;
    absl::optional<double> new_highest_scoring_other_bid_in_seller_currency =
        is_top_bid ? leader_info.top_bid->bid_in_seller_currency
                   : bid_in_seller_currency;
    OnNewHighestScoringOtherBid(
        score, new_highest_scoring_other_bid,
        new_highest_scoring_other_bid_in_seller_currency,
        leader_info.at_most_one_top_bid_owner ? &bid->interest_group->owner
                                              : nullptr,
        leader_info);
  } else if (score >= leader_info.second_highest_score) {
    // Also use this bid (the most recent one) as highest scoring other bid if
    // there's a tie for second highest score.
    OnNewHighestScoringOtherBid(score, bid->bid, bid_in_seller_currency, &owner,
                                leader_info);
  }

  if (is_top_bid) {
    leader_info.top_bid = std::make_unique<ScoredBid>(
        score, std::move(scoring_signals_data_version), std::move(bid),
        std::move(bid_in_seller_currency),
        std::move(component_auction_modified_bid_params));
  }
}

void InterestGroupAuction::OnNewHighestScoringOtherBid(
    double score,
    double bid_value,
    absl::optional<double> bid_in_seller_currency,
    const url::Origin* owner,
    LeaderInfo& leader_info) {
  DCHECK_EQ(bidding_and_scoring_phase_state_,
            is_server_auction_ ? PhaseState::kBefore : PhaseState::kDuring);

  // Current (the most recent) bid becomes highest scoring other bid.
  if (score > leader_info.second_highest_score) {
    leader_info.highest_scoring_other_bid = bid_value;
    leader_info.highest_scoring_other_bid_in_seller_currency =
        bid_in_seller_currency;
    leader_info.num_second_highest_bids = 1;
    // Owner may be false if this is one of the bids tied for first place.
    if (!owner) {
      leader_info.highest_scoring_other_bid_owner.reset();
    } else {
      leader_info.highest_scoring_other_bid_owner = *owner;
    }
    leader_info.second_highest_score = score;
    return;
  }

  DCHECK_EQ(score, leader_info.second_highest_score);
  if (!owner || *owner != leader_info.highest_scoring_other_bid_owner) {
    leader_info.highest_scoring_other_bid_owner.reset();
  }
  ++leader_info.num_second_highest_bids;
  // In case of a tie, randomly pick one. This is the select random value from a
  // stream with fixed storage problem.
  if (1 == base::RandInt(1, leader_info.num_second_highest_bids)) {
    leader_info.highest_scoring_other_bid = bid_value;
    leader_info.highest_scoring_other_bid_in_seller_currency =
        bid_in_seller_currency;
  }
}

absl::optional<base::TimeDelta> InterestGroupAuction::SellerTimeout() {
  if (config_->non_shared_params.seller_timeout.has_value()) {
    return std::min(config_->non_shared_params.seller_timeout.value(),
                    kMaxPerBuyerTimeout);
  }
  return absl::nullopt;
}

void InterestGroupAuction::MaybeCompleteBiddingAndScoringPhase() {
  DCHECK_EQ(bidding_and_scoring_phase_state_, PhaseState::kDuring);
  if (!IsBiddingAndScoringPhaseComplete()) {
    return;
  }

  all_bids_scored_ = true;

  AuctionResult result = AuctionResult::kSuccess;

  // If there's no winning bid, fail with kAllBidsRejected if there were any
  // bids. Otherwise, fail with kNoBids or kNoInterestGroups.
  if (!top_bid()) {
    if (any_bid_made_) {
      result = AuctionResult::kAllBidsRejected;
    } else {
      result = HasInterestGroups() ? AuctionResult::kNoBids
                                   : AuctionResult::kNoInterestGroups;
    }
  }

  // This needs to be asynchronous since it can happens inside
  // StartBiddingAndScoringPhase if there is actually nothing to do, and we
  // don't want to delete the auction while we're in process of starting it.
  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
      FROM_HERE,
      base::BindOnce(&InterestGroupAuction::OnBiddingAndScoringComplete,
                     weak_ptr_factory_.GetWeakPtr(), result,
                     std::vector<std::string>()));
}

void InterestGroupAuction::OnBiddingAndScoringComplete(
    AuctionResult auction_result,
    const std::vector<std::string>& errors) {
  DCHECK(bidding_and_scoring_phase_callback_);
  DCHECK(!final_auction_result_);
  DCHECK_EQ(bidding_and_scoring_phase_state_,
            is_server_auction_ ? PhaseState::kBefore : PhaseState::kDuring);
  bidding_and_scoring_phase_state_ = PhaseState::kAfter;

  TRACE_EVENT_NESTABLE_ASYNC_END0("fledge", "bidding_and_scoring_phase",
                                  *trace_id_);

  errors_.insert(errors_.end(), errors.begin(), errors.end());

  // If this is a component auction, have to unload the seller worklet handle to
  // avoid deadlock. Otherwise, loading the top-level seller worklet may be
  // blocked by component seller worklets taking up all the quota.
  if (parent_) {
    seller_worklet_handle_.reset();
  }

  // If the seller loaded callback hasn't been invoked yet, call it now. This is
  // needed in the case the phase ended without receiving the seller worklet
  // (e.g., in the case no bidder worklet bids).
  if (on_seller_receiver_callback_) {
    std::move(on_seller_receiver_callback_).Run();
  }

  bool success = auction_result == AuctionResult::kSuccess;
  if (!success) {
    // Close all pipes, to prevent any pending callbacks from being invoked if
    // this phase is being completed due to a fatal error, like the seller
    // worklet failing to load.
    ClosePipes();

    // `final_auction_result_` should only be set to kSuccess when the entire
    // auction is complete.
    final_auction_result_ = auction_result;
  } else {
    // If this is the top-level auction, mark it as a success (and the winning
    // component auction as well, if there is one). Component auction status
    // depend on whether or not they won the top-level auction, so if this is a
    // component auction, leave status as-is.
    if (!parent_) {
      final_auction_result_ = AuctionResult::kSuccess;
      // If there's a winning bid, set its auction result as well. If the
      // winning bid came from a component auction, this will set that component
      // auction's result as well. This is needed for auction result accessors.
      //
      // TODO(https://crbug.com/1394777): This is currently needed to correctly
      // retrieve reporting information from the nested auction. Is there a
      // cleaner way to do this?
      if (top_bid()) {
        top_bid()->bid->auction->final_auction_result_ =
            AuctionResult::kSuccess;
      }
    }
  }

  // If this is a top-level auction with component auction, update final state
  // of all successfully completed component auctions with bids that did not win
  // to reflect a loss.
  for (auto& component_auction_info : component_auctions_) {
    InterestGroupAuction* component_auction =
        component_auction_info.second.get();
    // Leave the state of the winning component auction alone, if the winning
    // bid is from a component auction.
    ScoredBid* winner = top_bid();
    if (winner && winner->bid->auction == component_auction) {
      continue;
    }
    if (component_auction->final_auction_result_) {
      continue;
    }
    component_auction->final_auction_result_ =
        AuctionResult::kComponentLostAuction;
  }

  std::move(bidding_and_scoring_phase_callback_).Run(success);
}

auction_worklet::mojom::ComponentAuctionOtherSellerPtr
InterestGroupAuction::GetOtherSellerParam(const Bid& bid) const {
  auction_worklet::mojom::ComponentAuctionOtherSellerPtr
      browser_signals_other_seller;
  if (parent_) {
    // This is a component seller scoring a bid from its own auction.
    // Need to provide the top-level seller origin.
    browser_signals_other_seller =
        auction_worklet::mojom::ComponentAuctionOtherSeller::NewTopLevelSeller(
            parent_->config_->seller);
  } else if (bid.auction != this) {
    // This is a top-level seller scoring a bid from a component auction.
    // Need to provide the component seller origin.
    browser_signals_other_seller =
        auction_worklet::mojom::ComponentAuctionOtherSeller::NewComponentSeller(
            bid.auction->config_->seller);
  }
  return browser_signals_other_seller;
}

AuctionWorkletManager::WorkletKey InterestGroupAuction::BidderWorkletKey(
    BidState& bid_state) {
  DCHECK(!bid_state.worklet_handle);
  DCHECK(!bid_state.additional_bid_buyer);

  const blink::InterestGroup& interest_group = bid_state.bidder->interest_group;

  absl::optional<uint16_t> experiment_group_id =
      GetBuyerExperimentId(*config_, interest_group.owner);

  return AuctionWorkletManager::BidderWorkletKey(
      interest_group.bidding_url.value_or(GURL()),
      interest_group.bidding_wasm_helper_url,
      interest_group.trusted_bidding_signals_url,
      /*needs_cors_for_additional_bid=*/false, experiment_group_id);
}

void InterestGroupAuction::OnDecompressedServerResponse(
    AdAuctionRequestContext* request_context,
    base::expected<mojo_base::BigBuffer, std::string> result) {
  if (!result.has_value()) {
    // We couldn't unzip the response.
    OnBiddingAndScoringComplete(
        AuctionResult::kInvalidServerResponse,
        {"runAdAuction(): Could not decompress server response"});
    return;
  }
  base::span<const uint8_t> result_span = result.value().byte_span();
  data_decoder_->ParseCbor(
      result_span,
      base::BindOnce(
          &InterestGroupAuction::OnParsedServerResponse,
          weak_ptr_factory_.GetWeakPtr(),
          // This use of unretained is safe since the request_context is owned
          // by a PageUserData and is only deleted when the page is destroyed.
          // This auction is owned by the page through a DocumentService, so it
          // will be destroyed before the decoder.
          base::Unretained(request_context)));

  // `result` falls out of scope, deallocating the buffer with the decompressed
  // response. This is okay because `DataDecoder::ParseCbor` made a copy before
  // it returned (via implicit construction of mojo_base::BigBuffer).
}

void InterestGroupAuction::OnParsedServerResponse(
    AdAuctionRequestContext* request_context,
    data_decoder::DataDecoder::ValueOrError result) {
  if (!result.has_value()) {
    // We couldn't parse the CBOR of the response.
    OnBiddingAndScoringComplete(
        AuctionResult::kInvalidServerResponse,
        {"runAdAuction(): Could not parse server response"});
    return;
  }
  absl::optional<BiddingAndAuctionResponse> response =
      BiddingAndAuctionResponse::TryParse(std::move(result).value(),
                                          request_context->group_names);
  if (!response) {
    // We couldn't recognize the structure of the response.
    OnBiddingAndScoringComplete(
        AuctionResult::kInvalidServerResponse,
        {"runAdAuction(): Could not parse server response"});
    return;
  }
  std::vector<std::string> errors;
  if (response->error) {
    errors.push_back(base::StrCat({"runAdAuction(): ", *response->error}));
  }
  if (response->is_chaff) {
    // This is a place-holder response because there was no winner.
    OnBiddingAndScoringComplete(AuctionResult::kNoBids, errors);
    return;
  }
  if (response->bid && !IsValidBid(*response->bid)) {
    errors.push_back(base::StrCat({"runAdAuction(): Invalid bid value ",
                                   base::NumberToString(*response->bid)}));
    OnBiddingAndScoringComplete(AuctionResult::kNoBids, errors);
    return;
  }
  any_bid_made_ = !response->bidding_groups.empty();

  blink::InterestGroupKey winning_group(response->interest_group_owner,
                                        response->interest_group_name);
  // Winning group must be a bidder.
  if (!base::Contains(response->bidding_groups, winning_group)) {
    errors.push_back("runAdAuction(): Winning group must be a bidder");
    OnBiddingAndScoringComplete(AuctionResult::kInvalidServerResponse, errors);
    return;
  }

  interest_group_manager_->GetInterestGroup(
      winning_group, base::BindOnce(&InterestGroupAuction::OnLoadedWinningGroup,
                                    weak_ptr_factory_.GetWeakPtr(),
                                    std::move(response).value()));
}

void InterestGroupAuction::OnLoadedWinningGroup(
    BiddingAndAuctionResponse response,
    absl::optional<StorageInterestGroup> maybe_group) {
  if (!maybe_group) {
    OnBiddingAndScoringComplete(
        AuctionResult::kInvalidServerResponse,
        {"runAdAuction(): Could not load winning interest group"});
    return;
  }
  std::vector<blink::AdDescriptor> ad_components;
  base::ranges::transform(
      response.ad_components, std::back_inserter(ad_components),
      [](const GURL& url) { return blink::AdDescriptor(url); });

  if (!maybe_group->interest_group.bidding_url) {
    // Groups must have a bidding logic URL to bid.
    OnBiddingAndScoringComplete(
        AuctionResult::kInvalidServerResponse,
        {"runAdAuction(): Winning group doesn't have a bidding URL"});
    return;
  }
  all_bids_scored_ = true;

  std::vector<SingleStorageInterestGroup> groups;
  groups.emplace_back(std::move(*maybe_group));
  auto buyer_helper = std::make_unique<BuyerHelper>(this, std::move(groups));
  std::unique_ptr<Bid> bid = buyer_helper->TryToCreateBidFromServerResponse(
      Bid::BidRole::kUnenforcedKAnon,  // TODO(behamilton): Fix this.
      response.bid.value_or(0.00001),
      /*ad_descriptor=*/
      blink::AdDescriptor(response.ad_render_url),
      /*ad_component_descriptors=*/std::move(ad_components));
  buyer_helpers_.emplace_back(std::move(buyer_helper));

  if (!bid) {
    OnBiddingAndScoringComplete(
        AuctionResult::kInvalidServerResponse,
        {"runAdAuction(): Couldn't reconstruct winning bid"});
    return;
  }

  SubresourceUrlBuilderIfReady();  // This is required for some reason.

  UpdateAuctionLeaders(
      std::move(bid), response.score.value_or(0.00001),
      // TODO(1457241): Use correct modified bid params for multi-level auction.
      /*component_auction_modified_bid_params=*/
      nullptr,
      /*bid_in_seller_currency=*/absl::nullopt,
      /*scoring_signals_data_version=*/absl::nullopt,
      // TODO(behamilton): Properly support k-anonymity here
      non_kanon_enforced_auction_leader_);

  saved_response_ = std::move(response);

  OnBiddingAndScoringComplete(AuctionResult::kSuccess);
}

void InterestGroupAuction::OnDirectFromSellerSignalHeaderAdSlotResolved(
    std::unique_ptr<HeaderDirectFromSellerSignals> signals,
    std::vector<std::string> errors) {
  DCHECK_NE(bidding_and_scoring_phase_state_, PhaseState::kAfter);
  CHECK(direct_from_seller_signals_header_ad_slot_pending_);
  CHECK(direct_from_seller_signals_header_ad_slot_);
  direct_from_seller_signals_header_ad_slot_ = std::move(signals);
  errors_.insert(errors_.end(), errors.begin(), errors.end());

  direct_from_seller_signals_header_ad_slot_pending_ = false;

  if (bidding_and_scoring_phase_state_ == PhaseState::kDuring) {
    for (const auto& buyer_helper : buyer_helpers_) {
      buyer_helper->NotifyConfigDependencyResolved();
    }
    OnScoringDependencyDone();
    ScoreQueuedBidsIfReady();
  }
}

// static
data_decoder::DataDecoder* InterestGroupAuction::GetDataDecoder(
    base::WeakPtr<InterestGroupAuction> instance) {
  if (!instance) {
    return nullptr;
  }
  return instance->data_decoder_.get();
}

}  // namespace content
