blob: 12a5cf4a6c513bfc3acaa34f96b9fc29e1a695d0 [file] [log] [blame]
// Copyright 2021 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_SERVICES_AUCTION_WORKLET_TRUSTED_SIGNALS_H_
#define CONTENT_SERVICES_AUCTION_WORKLET_TRUSTED_SIGNALS_H_
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "v8/include/v8-forward.h"
namespace auction_worklet {
class AuctionDownloader;
class AuctionV8Helper;
// Represents the trusted bidding/scoring signals that are part of the FLEDGE
// bidding system (https://github.com/WICG/turtledove/blob/main/FLEDGE.md).
// Fetches and parses the hosted JSON data files needed by worklets. There are
// separate methods for fetching bidding and scoring signals. A single
// TrustedSignals object can only be used to fetch bidding signals or scoring
// signals, even if a single URL is used for both types of signals.
//
// TODO(mmenke): This class currently does 4 copies when loading the data (To V8
// string, use V8's JSON parser, split data into V8 JSON subcomponent strings,
// convert to C++ strings), and 2 copies of each substring to use the data (To
// V8 per-key JSON string, use V8's JSON parser). Keeping the data stored as V8
// JSON subcomponents would remove 2 copies, without too much complexity. Could
// even implement V8 deep-copy logic, to remove two more copies (counting the
// clone operation as a copy).
class TrustedSignals {
public:
// Contains the values returned by the server.
//
// This can be created and destroyed on any thread, but GetSignals() can only
// be used on the V8 thread.
class Result : public base::RefCountedThreadSafe<Result> {
public:
// Constructor for bidding signals.
Result(std::map<std::string, std::string> bidder_json_data,
absl::optional<uint32_t> data_version);
// Constructor for scoring signals.
Result(std::map<std::string, std::string> render_url_json_data,
std::map<std::string, std::string> ad_component_json_data,
absl::optional<uint32_t> data_version);
explicit Result(const Result&) = delete;
Result& operator=(const Result&) = delete;
// Retrieves the trusted bidding signals associated with the passed in keys,
// in the format expected by a worklet's generateBid() method. `this` must
// have been generated by fetching bidding signals. `v8_helper`'s Isolate
// must be active (in particular, this must be on the v8 thread), and
// `context` must be the active context. `bidding_signals_keys` must be
// subsets of the keys provided when creating the TrustedSignals object.
// Always returns a non-empty value.
v8::Local<v8::Object> GetBiddingSignals(
AuctionV8Helper* v8_helper,
v8::Local<v8::Context> context,
const std::vector<std::string>& bidding_signals_keys) const;
// Retrieves the trusted scoring signals associated with the passed in urls,
// in the format expected by a worklet's scoreAd() method. `this` must have
// been generated by fetching scoring signals. `v8_helper`'s Isolate must be
// active (in particular, this must be on the v8 thread), and `context` must
// be the active context. `render_url` and `ad_component_render_urls` must
// be subsets of the corresponding sets of GURLs provided when creating the
// TrustedSignals object. Always returns a non-empty value.
v8::Local<v8::Object> GetScoringSignals(
AuctionV8Helper* v8_helper,
v8::Local<v8::Context> context,
const GURL& render_url,
const std::vector<std::string>& ad_component_render_urls) const;
absl::optional<uint32_t> GetDataVersion() const { return data_version_; }
private:
friend class base::RefCountedThreadSafe<Result>;
~Result();
// Map of keys to the associated JSON data for trusted bidding signals.
const absl::optional<std::map<std::string, std::string>> bidder_json_data_;
// Map of keys to the associated JSON data for trusted scoring signals.
const absl::optional<std::map<std::string, std::string>>
render_url_json_data_;
const absl::optional<std::map<std::string, std::string>>
ad_component_json_data_;
// Data version associated with the trusted signals.
const absl::optional<uint32_t> data_version_;
};
using LoadSignalsCallback =
base::OnceCallback<void(scoped_refptr<Result> result,
absl::optional<std::string> error_msg)>;
explicit TrustedSignals(const TrustedSignals&) = delete;
TrustedSignals& operator=(const TrustedSignals&) = delete;
~TrustedSignals();
// Constructs a TrustedSignals for fetching bidding signals, and starts the
// fetch. `trusted_bidding_signals_url` must be the base URL (no query params
// added). Callback will be invoked asynchronously once the data has been
// fetched or an error has occurred. De-duplicates keys when assembling the
// full URL for the fetch. Fails if the URL already has a query param (or has
// a location or embedded credentials) or if the response is not JSON. If some
// or all of the render URLs are missing, still succeeds, and GetSignals()
// will populate them with nulls.
//
// There are no lifetime constraints of `url_loader_factory`.
static std::unique_ptr<TrustedSignals> LoadBiddingSignals(
network::mojom::URLLoaderFactory* url_loader_factory,
std::set<std::string> bidding_signals_keys,
const std::string& hostname,
const GURL& trusted_bidding_signals_url,
scoped_refptr<AuctionV8Helper> v8_helper,
LoadSignalsCallback load_signals_callback);
// Just like LoadBiddingSignals() above, but for fetching seller signals.
static std::unique_ptr<TrustedSignals> LoadScoringSignals(
network::mojom::URLLoaderFactory* url_loader_factory,
std::set<std::string> render_urls,
std::set<std::string> ad_component_render_urls,
const std::string& hostname,
const GURL& trusted_scoring_signals_url,
scoped_refptr<AuctionV8Helper> v8_helper,
LoadSignalsCallback load_signals_callback);
private:
TrustedSignals(absl::optional<std::set<std::string>> bidding_signals_keys,
absl::optional<std::set<std::string>> render_urls,
absl::optional<std::set<std::string>> ad_component_render_urls,
const GURL& trusted_signals_url,
scoped_refptr<AuctionV8Helper> v8_helper,
LoadSignalsCallback load_signals_callback);
// Starts downloading `url`, which should be the bidding or scoring signals
// URL with the query parameter correctly set.
void StartDownload(network::mojom::URLLoaderFactory* url_loader_factory,
const GURL& full_signals_url);
void OnDownloadComplete(std::unique_ptr<std::string> body,
scoped_refptr<net::HttpResponseHeaders> headers,
absl::optional<std::string> error_msg);
// Parses the response body on the V8 thread, and extracts values associated
// with the requested keys.
static void HandleDownloadResultOnV8Thread(
scoped_refptr<AuctionV8Helper> v8_helper,
const GURL& signals_url,
absl::optional<std::set<std::string>> bidding_signals_keys,
absl::optional<std::set<std::string>> render_urls,
absl::optional<std::set<std::string>> ad_component_render_urls,
std::unique_ptr<std::string> body,
scoped_refptr<net::HttpResponseHeaders> headers,
absl::optional<std::string> error_msg,
scoped_refptr<base::SequencedTaskRunner> user_thread_task_runner,
base::WeakPtr<TrustedSignals> weak_instance);
// Called from V8 thread.
static void PostCallbackToUserThread(
scoped_refptr<base::SequencedTaskRunner> user_thread_task_runner,
base::WeakPtr<TrustedSignals> weak_instance,
scoped_refptr<Result> result,
absl::optional<std::string> error_msg);
// Called on user thread.
void DeliverCallbackOnUserThread(scoped_refptr<Result>,
absl::optional<std::string> error_msg);
// Keys being fetched. For bidding signals, only `bidding_signals_keys_` is
// non-null. For scoring signals, only `render_urls_` and
// `ad_component_render_urls_` are non-null. These are cleared and ownership
// is passed to the V8 thread once the download completes, as they're no
// longer on the main thread after that point.
absl::optional<std::set<std::string>> bidding_signals_keys_;
absl::optional<std::set<std::string>> render_urls_;
absl::optional<std::set<std::string>> ad_component_render_urls_;
const GURL trusted_signals_url_; // original, for error messages.
const scoped_refptr<AuctionV8Helper> v8_helper_;
LoadSignalsCallback load_signals_callback_;
std::unique_ptr<AuctionDownloader> auction_downloader_;
base::WeakPtrFactory<TrustedSignals> weak_ptr_factory{this};
};
} // namespace auction_worklet
#endif // CONTENT_SERVICES_AUCTION_WORKLET_TRUSTED_SIGNALS_H_