1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171

content / services / auction_worklet / trusted_kvv2_signals.h [blame]

// Copyright 2024 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_SERVICES_AUCTION_WORKLET_TRUSTED_KVV2_SIGNALS_H_
#define CONTENT_SERVICES_AUCTION_WORKLET_TRUSTED_KVV2_SIGNALS_H_

#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <vector>

#include "base/functional/callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/types/expected.h"
#include "content/common/content_export.h"
#include "content/services/auction_worklet/auction_v8_helper.h"
#include "content/services/auction_worklet/public/mojom/auction_network_events_handler.mojom.h"
#include "content/services/auction_worklet/trusted_signals.h"
#include "content/services/auction_worklet/trusted_signals_kvv2_helper.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/http/http_response_headers.h"
#include "net/third_party/quiche/src/quiche/oblivious_http/buffers/oblivious_http_request.h"
#include "net/third_party/quiche/src/quiche/oblivious_http/oblivious_http_client.h"
#include "services/network/public/mojom/url_loader_factory.mojom-forward.h"
#include "url/gurl.h"
#include "url/origin.h"
#include "v8/include/v8-forward.h"

namespace auction_worklet {

class AuctionDownloader;

// Like the TrustedSignals class, but for version 2 of the Key-Value server API
// for bidding/scoring signals. It fetches and parses the hosted CBOR data
// needed by worklets. There are separate methods for fetching bidding and
// scoring signals. A single `TrustedKVv2Signals` object can only be used to
// fetch either bidding signals or scoring signals, even if a single URL is used
// for both types of signals.
class CONTENT_EXPORT TrustedKVv2Signals {
 public:
  using LoadKVv2SignalsCallback = base::OnceCallback<void(
      std::optional<TrustedSignalsKVv2ResponseParser::TrustedSignalsResultMap>
          result_map,
      std::optional<std::string> error_msg)>;

  explicit TrustedKVv2Signals(const TrustedKVv2Signals&) = delete;
  TrustedKVv2Signals& operator=(const TrustedKVv2Signals&) = delete;
  ~TrustedKVv2Signals();

  // Construct a TrustedKVv2Signals for fetching bidding signals, and start
  // 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.
  //
  // There are no lifetime constraints of `url_loader_factory`.
  static std::unique_ptr<TrustedKVv2Signals> LoadKVv2BiddingSignals(
      network::mojom::URLLoaderFactory* url_loader_factory,
      mojo::PendingRemote<auction_worklet::mojom::AuctionNetworkEventsHandler>
          auction_network_events_handler,
      std::set<std::string> interest_group_names,
      std::set<std::string> bidding_signals_keys,
      const GURL& trusted_bidding_signals_url,
      std::unique_ptr<TrustedBiddingSignalsKVv2RequestHelperBuilder>
          request_helper_builder,
      scoped_refptr<AuctionV8Helper> v8_helper,
      LoadKVv2SignalsCallback load_kvv2_signals_callback);

  // Just like LoadKVv2BiddingSignals() above, but for fetching seller signals.
  static std::unique_ptr<TrustedKVv2Signals> LoadKVv2ScoringSignals(
      network::mojom::URLLoaderFactory* url_loader_factory,
      mojo::PendingRemote<auction_worklet::mojom::AuctionNetworkEventsHandler>
          auction_network_events_handler,
      std::set<std::string> render_urls,
      std::set<std::string> ad_component_render_urls,
      const GURL& trusted_scoring_signals_url,
      std::unique_ptr<TrustedScoringSignalsKVv2RequestHelperBuilder>
          request_helper_builder,
      scoped_refptr<AuctionV8Helper> v8_helper,
      LoadKVv2SignalsCallback load_kvv2_signals_callback);

 private:
  // The `context` is generated during the encryption process in the request
  // builder and is saved for decrypting the response body.
  TrustedKVv2Signals(
      std::optional<std::set<std::string>> interest_group_names,
      std::optional<std::set<std::string>> bidding_signals_keys,
      std::optional<std::set<std::string>> render_urls,
      std::optional<std::set<std::string>> ad_component_render_urls,
      const GURL& trusted_signals_url,
      quiche::ObliviousHttpRequest::Context context,
      mojo::PendingRemote<auction_worklet::mojom::AuctionNetworkEventsHandler>
          auction_network_events_handler,
      scoped_refptr<AuctionV8Helper> v8_helper,
      LoadKVv2SignalsCallback load_kvv2_signals_callback);

  // Start downloading `url`, which should be the bidding or scoring signals
  // URL, using the POST method..
  void StartKVv2Download(network::mojom::URLLoaderFactory* url_loader_factory,
                         const GURL& full_signals_url,
                         std::string post_body);

  void OnKVv2DownloadComplete(std::unique_ptr<std::string> body,
                              scoped_refptr<net::HttpResponseHeaders> headers,
                              std::optional<std::string> error_msg);

  // Parse the response body on the V8 thread, and extract values associated
  // with the requested keys.
  static void HandleKVv2DownloadResultOnV8Thread(
      scoped_refptr<AuctionV8Helper> v8_helper,
      const GURL& signals_url,
      std::optional<std::set<std::string>> interest_group_names,
      std::optional<std::set<std::string>> bidding_signals_keys,
      std::optional<std::set<std::string>> render_urls,
      std::optional<std::set<std::string>> ad_component_render_urls,
      std::unique_ptr<std::string> body,
      scoped_refptr<net::HttpResponseHeaders> headers,
      quiche::ObliviousHttpRequest::Context context,
      std::optional<std::string> error_msg,
      scoped_refptr<base::SequencedTaskRunner> user_thread_task_runner,
      base::WeakPtr<TrustedKVv2Signals> weak_instance,
      base::TimeDelta download_time);

  // Called from V8 thread.
  static void PostKVv2CallbackToUserThread(
      scoped_refptr<base::SequencedTaskRunner> user_thread_task_runner,
      base::WeakPtr<TrustedKVv2Signals> weak_instance,
      std::optional<TrustedSignalsKVv2ResponseParser::TrustedSignalsResultMap>
          result_map,
      std::optional<std::string> error_msg);

  // Called on user thread.
  void DeliverKVv2CallbackOnUserThread(
      std::optional<TrustedSignalsKVv2ResponseParser::TrustedSignalsResultMap>
          result_map,
      std::optional<std::string> error_msg);

  // Keys being fetched. For bidding signals, only `bidding_signals_keys_` and
  // `interest_group_names_` are 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.
  std::optional<std::set<std::string>> interest_group_names_;
  std::optional<std::set<std::string>> bidding_signals_keys_;
  std::optional<std::set<std::string>> render_urls_;
  std::optional<std::set<std::string>> ad_component_render_urls_;

  const GURL trusted_signals_url_;
  const scoped_refptr<AuctionV8Helper> v8_helper_;

  LoadKVv2SignalsCallback load_kvv2_signals_callback_;
  std::unique_ptr<AuctionDownloader> auction_downloader_;
  // Used only for metrics; time when download started.
  base::TimeTicks download_start_time_;
  // Save the encryption context for decryption purpose.
  quiche::ObliviousHttpRequest::Context context_;

  mojo::PendingRemote<auction_worklet::mojom::AuctionNetworkEventsHandler>
      auction_network_events_handler_;

  base::WeakPtrFactory<TrustedKVv2Signals> weak_ptr_factory{this};
};

}  // namespace auction_worklet

#endif  // CONTENT_SERVICES_AUCTION_WORKLET_TRUSTED_KVV2_SIGNALS_H_