[go: nahoru, domu]

blob: bf31a8d9c525415cbcdb1a276cb8c5936adade05 [file] [log] [blame]
Avi Drissman4e1b7bc2022-09-15 14:03:501// Copyright 2021 The Chromium Authors
Nan Lin8a1108a2021-07-16 22:23:212// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/aggregation_service/aggregation_service_key_fetcher.h"
6
Nan Lin48eace62021-09-23 20:13:297#include <memory>
Dan McArdle08ad6112023-11-21 20:39:478#include <optional>
Nan Lin8a1108a2021-07-16 22:23:219#include <utility>
Nan Lin48eace62021-09-23 20:13:2910#include <vector>
Nan Lin8a1108a2021-07-16 22:23:2111
Nan Lin48eace62021-09-23 20:13:2912#include "base/containers/circular_deque.h"
Avi Drissmanadac21992023-01-11 23:46:3913#include "base/functional/bind.h"
14#include "base/functional/callback.h"
Nan Lin8a1108a2021-07-16 22:23:2115#include "base/rand_util.h"
Alex Turner71512772022-06-29 19:20:2716#include "content/browser/aggregation_service/aggregation_service_storage.h"
Nan Lin89244d62021-11-12 21:38:1717#include "content/browser/aggregation_service/aggregation_service_storage_context.h"
Nan Lin8a1108a2021-07-16 22:23:2118#include "services/network/public/cpp/is_potentially_trustworthy.h"
Nan Lin4c75cd82022-02-18 23:39:3419#include "url/gurl.h"
Nan Lin8a1108a2021-07-16 22:23:2120
21namespace content {
22
23AggregationServiceKeyFetcher::AggregationServiceKeyFetcher(
Nan Lin89244d62021-11-12 21:38:1724 AggregationServiceStorageContext* storage_context,
Nan Lin48eace62021-09-23 20:13:2925 std::unique_ptr<NetworkFetcher> network_fetcher)
Nan Lin89244d62021-11-12 21:38:1726 : storage_context_(storage_context),
27 network_fetcher_(std::move(network_fetcher)) {}
Nan Lin8a1108a2021-07-16 22:23:2128
29AggregationServiceKeyFetcher::~AggregationServiceKeyFetcher() = default;
30
Nan Lin4c75cd82022-02-18 23:39:3431void AggregationServiceKeyFetcher::GetPublicKey(const GURL& url,
Nan Lin8a1108a2021-07-16 22:23:2132 FetchCallback callback) {
Nan Lin4c75cd82022-02-18 23:39:3433 DCHECK(network::IsUrlPotentiallyTrustworthy(url));
Nan Lin8a1108a2021-07-16 22:23:2134
Nan Lin4c75cd82022-02-18 23:39:3435 base::circular_deque<FetchCallback>& pending_callbacks = url_callbacks_[url];
Nan Lin48eace62021-09-23 20:13:2936 bool in_progress = !pending_callbacks.empty();
37 pending_callbacks.push_back(std::move(callback));
38
39 // If there is already a fetch request in progress, just enqueue the
40 // callback and return.
41 if (in_progress)
42 return;
43
44 // First we check if we already have keys stored.
Nan Lin4c75cd82022-02-18 23:39:3445 // TODO(crbug.com/1223488): Pass url by value and move after C++17.
Alex Turner71512772022-06-29 19:20:2746 storage_context_->GetStorage()
47 .AsyncCall(&AggregationServiceStorage::GetPublicKeys)
Nan Lin4c75cd82022-02-18 23:39:3448 .WithArgs(url)
Nan Lin8a1108a2021-07-16 22:23:2149 .Then(base::BindOnce(
50 &AggregationServiceKeyFetcher::OnPublicKeysReceivedFromStorage,
Nan Lin4c75cd82022-02-18 23:39:3451 weak_factory_.GetWeakPtr(), url));
Nan Lin8a1108a2021-07-16 22:23:2152}
53
54void AggregationServiceKeyFetcher::OnPublicKeysReceivedFromStorage(
Nan Lin4c75cd82022-02-18 23:39:3455 const GURL& url,
Nan Lin48eace62021-09-23 20:13:2956 std::vector<PublicKey> keys) {
57 if (keys.empty()) {
58 // Fetch keys from the network if not found in the storage.
Nan Lin4c75cd82022-02-18 23:39:3459 FetchPublicKeysFromNetwork(url);
Nan Lin8a1108a2021-07-16 22:23:2160 return;
61 }
62
Nan Lin4c75cd82022-02-18 23:39:3463 RunCallbacksForUrl(url, keys);
Nan Lin48eace62021-09-23 20:13:2964}
65
Nan Lin4c75cd82022-02-18 23:39:3466void AggregationServiceKeyFetcher::FetchPublicKeysFromNetwork(const GURL& url) {
Nan Lin48eace62021-09-23 20:13:2967 if (!network_fetcher_) {
68 // Return error if fetching from network is not enabled.
Nan Lin4c75cd82022-02-18 23:39:3469 RunCallbacksForUrl(url, /*keys=*/{});
Nan Lin48eace62021-09-23 20:13:2970 return;
71 }
72
73 // Unretained is safe because the network fetcher is owned by `this` and will
74 // be deleted before `this`.
75 network_fetcher_->FetchPublicKeys(
Nan Lin4c75cd82022-02-18 23:39:3476 url, base::BindOnce(
77 &AggregationServiceKeyFetcher::OnPublicKeysReceivedFromNetwork,
78 base::Unretained(this), url));
Nan Lin48eace62021-09-23 20:13:2979}
80
81void AggregationServiceKeyFetcher::OnPublicKeysReceivedFromNetwork(
Nan Lin4c75cd82022-02-18 23:39:3482 const GURL& url,
Dan McArdle08ad6112023-11-21 20:39:4783 std::optional<PublicKeyset> keyset) {
Nan Lin48eace62021-09-23 20:13:2984 if (!keyset.has_value() || keyset->expiry_time.is_null()) {
Dan McArdle08ad6112023-11-21 20:39:4785 // `keyset` will be std::nullopt if an error occurred and `expiry_time`
Nan Lin48eace62021-09-23 20:13:2986 // will be null if the freshness lifetime was zero. In these cases, we will
Nan Lin4c75cd82022-02-18 23:39:3487 // still update the keys for `url`, i,e. clear them.
Alex Turner71512772022-06-29 19:20:2788 storage_context_->GetStorage()
89 .AsyncCall(&AggregationServiceStorage::ClearPublicKeys)
Nan Lin4c75cd82022-02-18 23:39:3490 .WithArgs(url);
Nan Lin48eace62021-09-23 20:13:2991 } else {
92 // Store public keys fetched from network to storage, the old keys will be
93 // deleted from storage.
Alex Turner71512772022-06-29 19:20:2794 storage_context_->GetStorage()
95 .AsyncCall(&AggregationServiceStorage::SetPublicKeys)
Nan Lin4c75cd82022-02-18 23:39:3496 .WithArgs(url, keyset.value());
Nan Lin48eace62021-09-23 20:13:2997 }
98
Nan Lin4c75cd82022-02-18 23:39:3499 RunCallbacksForUrl(
100 url, keyset.has_value() ? keyset->keys : std::vector<PublicKey>());
Nan Lin48eace62021-09-23 20:13:29101}
102
Nan Lin4c75cd82022-02-18 23:39:34103void AggregationServiceKeyFetcher::RunCallbacksForUrl(
104 const GURL& url,
Nan Lin48eace62021-09-23 20:13:29105 const std::vector<PublicKey>& keys) {
Nan Lin4c75cd82022-02-18 23:39:34106 auto iter = url_callbacks_.find(url);
107 DCHECK(iter != url_callbacks_.end());
Nan Lin48eace62021-09-23 20:13:29108
109 base::circular_deque<FetchCallback> pending_callbacks =
110 std::move(iter->second);
111 DCHECK(!pending_callbacks.empty());
112
Nan Lin4c75cd82022-02-18 23:39:34113 url_callbacks_.erase(iter);
Nan Lin48eace62021-09-23 20:13:29114
115 if (keys.empty()) {
116 // Return error, don't refetch to avoid infinite loop.
117 for (auto& callback : pending_callbacks) {
Dan McArdle08ad6112023-11-21 20:39:47118 std::move(callback).Run(std::nullopt,
Nan Lin48eace62021-09-23 20:13:29119 PublicKeyFetchStatus::kPublicKeyFetchFailed);
120 }
121 } else {
122 for (auto& callback : pending_callbacks) {
123 // Each report should randomly select a key. This ensures that the set of
124 // reports a client sends are not a subset of the reports identified by
125 // any one key.
126 uint64_t key_index = base::RandGenerator(keys.size());
127 std::move(callback).Run(keys[key_index], PublicKeyFetchStatus::kOk);
128 }
129 }
Nan Lin8a1108a2021-07-16 22:23:21130}
131
132} // namespace content