blob: 15402c192d0ed71b796f326654d2e9fb34a43215 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_INTEREST_GROUP_AD_AUCTION_SERVICE_IMPL_H_
#define CONTENT_BROWSER_INTEREST_GROUP_AD_AUCTION_SERVICE_IMPL_H_
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <vector>
#include "base/containers/unique_ptr_adapters.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "base/types/expected.h"
#include "base/uuid.h"
#include "content/browser/fenced_frame/fenced_frame_url_mapping.h"
#include "content/browser/interest_group/auction_nonce_manager.h"
#include "content/browser/interest_group/auction_runner.h"
#include "content/browser/interest_group/auction_worklet_manager.h"
#include "content/browser/interest_group/bidding_and_auction_serializer.h"
#include "content/browser/interest_group/dwa_auction_metrics.h"
#include "content/browser/interest_group/interest_group_auction.h"
#include "content/browser/interest_group/interest_group_auction_reporter.h"
#include "content/common/content_export.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/document_service.h"
#include "content/services/auction_worklet/public/mojom/private_aggregation_request.mojom-forward.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/mojom/client_security_state.mojom.h"
#include "services/network/public/mojom/permissions_policy/permissions_policy_feature.mojom-forward.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "third_party/blink/public/common/interest_group/auction_config.h"
#include "third_party/blink/public/mojom/interest_group/ad_auction_service.mojom.h"
#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom-forward.h"
#include "third_party/blink/public/mojom/parakeet/ad_request.mojom.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace content {
class InterestGroupManagerImpl;
class PrivateAggregationManager;
class ReconnectableURLLoaderFactory;
class RenderFrameHost;
class RenderFrameHostImpl;
struct BiddingAndAuctionServerKey;
// Implements the AdAuctionService service called by Blink code.
class CONTENT_EXPORT AdAuctionServiceImpl final
: public DocumentService<blink::mojom::AdAuctionService>,
public AuctionWorkletManager::Delegate {
public:
// Factory method for creating an instance of this interface that is
// bound to the lifetime of the frame or receiver (whichever is shorter).
static void CreateMojoService(
RenderFrameHost* render_frame_host,
mojo::PendingReceiver<blink::mojom::AdAuctionService> receiver);
// blink::mojom::AdAuctionService.
void JoinInterestGroup(const blink::InterestGroup& group,
JoinInterestGroupCallback callback) override;
void LeaveInterestGroup(const url::Origin& owner,
const std::string& name,
LeaveInterestGroupCallback callback) override;
void LeaveInterestGroupForDocument() override;
void ClearOriginJoinedInterestGroups(
const url::Origin& owner,
const std::vector<std::string>& interest_groups_to_keep,
ClearOriginJoinedInterestGroupsCallback callback) override;
void UpdateAdInterestGroups() override;
void RunAdAuction(
const blink::AuctionConfig& config,
mojo::PendingReceiver<blink::mojom::AbortableAdAuction> abort_receiver,
RunAdAuctionCallback callback) override;
void DeprecatedGetURLFromURN(
const GURL& urn_url,
bool send_reports,
DeprecatedGetURLFromURNCallback callback) override;
void DeprecatedReplaceInURN(
const GURL& urn_url,
const std::vector<blink::AuctionConfig::AdKeywordReplacement>&
replacements,
DeprecatedReplaceInURNCallback callback) override;
void GetInterestGroupAdAuctionData(
const base::flat_map<url::Origin, std::optional<url::Origin>>& sellers,
blink::mojom::AuctionDataConfigPtr config,
GetInterestGroupAdAuctionDataCallback callback) override;
void CreateAdRequest(blink::mojom::AdRequestConfigPtr config,
CreateAdRequestCallback callback) override;
void FinalizeAd(const std::string& ads_guid,
const blink::AuctionConfig& config,
FinalizeAdCallback callback) override;
scoped_refptr<network::SharedURLLoaderFactory>
GetRefCountedTrustedURLLoaderFactory();
// AuctionWorkletManager::Delegate implementation:
network::mojom::URLLoaderFactory* GetFrameURLLoaderFactory() override;
network::mojom::URLLoaderFactory* GetTrustedURLLoaderFactory() override;
void PreconnectSocket(
const GURL& url,
const net::NetworkAnonymizationKey& network_anonymization_key) override;
RenderFrameHostImpl* GetFrame() override;
scoped_refptr<SiteInstance> GetFrameSiteInstance() override;
network::mojom::ClientSecurityStatePtr GetClientSecurityState() override;
std::optional<std::string> GetCookieDeprecationLabel() override;
void GetTrustedKeyValueServerKey(
const url::Origin& scope_origin,
const std::optional<url::Origin>& coordinator,
base::OnceCallback<void(base::expected<BiddingAndAuctionServerKey,
std::string>)> callback) override;
using DocumentService::origin;
using DocumentService::render_frame_host;
private:
using ReporterList = std::list<std::unique_ptr<InterestGroupAuctionReporter>>;
class BiddingAndAuctionDataConstructionState {
public:
BiddingAndAuctionDataConstructionState();
BiddingAndAuctionDataConstructionState(
BiddingAndAuctionDataConstructionState&& other);
~BiddingAndAuctionDataConstructionState();
base::TimeTicks start_time; // time used for metrics
std::map<url::Origin, BiddingAndAuctionServerKey> keys;
std::unique_ptr<BiddingAndAuctionData> data;
base::Uuid request_id;
base::flat_map<url::Origin, std::optional<url::Origin>> sellers;
base::Time timestamp; // timestamp to include in the request.
blink::mojom::AuctionDataConfigPtr config;
std::vector<blink::mojom::AdAuctionPerSellerRequestPtr> requests;
bool has_valid_request = false;
GetInterestGroupAdAuctionDataCallback callback;
};
// `render_frame_host` must not be null, and DocumentService guarantees
// `this` will not outlive the `render_frame_host`.
AdAuctionServiceImpl(
RenderFrameHost& render_frame_host,
mojo::PendingReceiver<blink::mojom::AdAuctionService> receiver);
// `this` can only be destroyed by DocumentService.
~AdAuctionServiceImpl() override;
// Checks if a join or leave interest group is allowed to be sent from the
// current renderer. If not, returns false and invokes
// ReportBadMessageAndDeleteThis().
bool JoinOrLeaveApiAllowedFromRenderer(const url::Origin& owner,
const char* invoked_method);
// Checks if `feature` is enabled for the frame, and returns true if so, and
// false if not. Additionally, if the feature is enabled, prints a warning to
// the console if the feature would not be enabled if the default state of the
// feature across cross-origin frames were switched to disabled instead of
// enabled.
bool IsPermissionPolicyEnabledAndWarnIfNeeded(
network::mojom::PermissionsPolicyFeature feature,
const char* method);
// Returns true if `origin` is allowed to perform the specified
// `interest_group_api_operation` in this frame. Must be called on worklet /
// interest group origins before using them in any interest group API.
bool IsInterestGroupAPIAllowed(ContentBrowserClient::InterestGroupApiOperation
interest_group_api_operation,
const url::Origin& origin) const;
// Deletes `auction`.
void OnAuctionComplete(
RunAdAuctionCallback callback,
GURL urn_uuid,
AuctionRunner* auction,
bool aborted_by_script,
std::optional<blink::InterestGroupKey> winning_group_key,
std::optional<blink::AdSize> requested_ad_size,
std::optional<blink::AdDescriptor> ad_descriptor,
std::vector<blink::AdDescriptor> ad_component_descriptors,
std::vector<std::string> errors,
std::unique_ptr<InterestGroupAuctionReporter> reporter,
bool contained_server_auction,
bool contained_on_device_auction,
AuctionResult result);
void OnReporterComplete(ReporterList::iterator reporter_it);
void MaybeLogPrivateAggregationFeatures(
const std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr>&
private_aggregation_requests);
// On failing to fetch ad auction data, set `seller`'s request to an empty
// request with error `msg`.
void AddEmptyGetInterestGroupAdAuctionDataRequest(const url::Origin& seller,
const std::string& msg);
// Call the first callback in ba_data_callbacks_ & start loading the next
// following request in ba_data_callbacks_.
void RunGetInterestGroupAdAuctionDataCallback(base::Uuid request_id);
void LoadAuctionDataAndKeyForNextQueuedRequest();
void OnGotAuctionData(base::Uuid request_id, BiddingAndAuctionData data);
void OnGotOneBiddingAndAuctionServerKey(
base::Uuid request_id,
const url::Origin& seller,
base::expected<BiddingAndAuctionServerKey, std::string> maybe_key);
void OnGotAuctionDataAndKey(base::Uuid request_id,
const url::Origin& seller,
const BiddingAndAuctionServerKey& ba_key);
InterestGroupManagerImpl& GetInterestGroupManager() const;
url::Origin GetTopWindowOrigin() const;
void CreateUnderlyingTrustedURLLoaderFactory(
mojo::PendingRemote<network::mojom::URLLoaderFactory>* out_factory);
AdAuctionPageData* GetAdAuctionPageData();
// For each buyer in `config`, preconnect to its origin and bidding signals
// origin if the origins have been cached from previous interest group joins
// or auctions. This function needs to be called separately to preconnect to
// origins for `config`'s component auctions. Returns the number of buyers
// that were preconnected.
size_t PreconnectToBuyerOrigins(const blink::AuctionConfig& config);
// To avoid race conditions associated with top frame navigations (mentioned
// in document_service.h), we need to save the values of the main frame
// URL and origin in the constructor.
const url::Origin main_frame_origin_;
const GURL main_frame_url_;
mojo::Remote<network::mojom::URLLoaderFactory> frame_url_loader_factory_;
// A URLLoaderFactory connecting to the underlying factory created by
// CreateUnderlyingTrustedURLLoaderFactory(), with reconnecting support. This
// can be used for reporting requests, which might happen after the frame is
// destroyed.
scoped_refptr<ReconnectableURLLoaderFactory>
ref_counted_trusted_url_loader_factory_;
// Used to create AuctionMetricsRecorders, which store data needed to record
// UKM. This must be before `auction_worklet_manager_`, since worklet owners
// may keep references to the AuctionMetricsRecorders owned by the
// `auction_metrics_recorder_manager_`.
AuctionMetricsRecorderManager auction_metrics_recorder_manager_;
// Keeps track of metrics associated with each seller across the auction
// run.
DwaAuctionMetricsManager dwa_auction_metrics_manager_;
// This must be before `auctions_`, since auctions may own references to
// worklets it manages.
AuctionWorkletManager auction_worklet_manager_;
// Manages auction nonces issued by prior calls to CreateAuctionNonce,
// which are used by subsequent calls to RunAdAuction.
AuctionNonceManager auction_nonce_manager_;
// Use a map instead of a list so can remove entries without destroying them.
// TODO(mmenke): Switch to std::set() and use extract() once that's allowed.
std::map<AuctionRunner*, std::unique_ptr<AuctionRunner>> auctions_;
ReporterList reporters_;
// Safe to keep as it will outlive the associated `RenderFrameHost` and
// therefore `this`, being tied to the lifetime of the `StoragePartition`.
const raw_ptr<PrivateAggregationManager> private_aggregation_manager_;
// Whether a UseCounter has already been logged for usage of the Private
// Aggregation API in general, the extended Private Aggregation API and the
// Private Aggregation API's enableDebugMode(), respectively.
bool has_logged_private_aggregation_web_features_ = false;
bool has_logged_extended_private_aggregation_web_feature_ = false;
bool has_logged_private_aggregation_enable_debug_mode_web_feature_ = false;
bool has_logged_private_aggregation_filtering_id_web_feature_ = false;
bool has_logged_private_aggregation_error_reporting_web_feature_ = false;
// Track the state of GetInterestGroupAdAuctionData calls. One request will be
// handled at a time (the first in the queue). The first
// BiddingAndAuctionDataConstructionState's data and key will be edited in
// place as they are loaded.
base::queue<BiddingAndAuctionDataConstructionState> ba_data_callbacks_;
// True if a feature is currently enabled, but would be disabled if the
// default policy for the feature were switched to EnableForSelf. Lazily
// populated.
std::map<network::mojom::PermissionsPolicyFeature, bool>
should_warn_about_feature_;
base::WeakPtrFactory<AdAuctionServiceImpl> weak_ptr_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_INTEREST_GROUP_AD_AUCTION_SERVICE_IMPL_H_