Avi Drissman | 4e1b7bc | 2022-09-15 14:03:50 | [diff] [blame] | 1 | // Copyright 2021 The Chromium Authors |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATABLE_REPORT_ASSEMBLER_H_ |
| 6 | #define CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATABLE_REPORT_ASSEMBLER_H_ |
| 7 | |
| 8 | #include <stddef.h> |
| 9 | #include <stdint.h> |
| 10 | |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 11 | #include <memory> |
Dan McArdle | 08ad611 | 2023-11-21 20:39:47 | [diff] [blame] | 12 | #include <optional> |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 13 | #include <vector> |
| 14 | |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 15 | #include "base/containers/flat_map.h" |
Avi Drissman | adac2199 | 2023-01-11 23:46:39 | [diff] [blame] | 16 | #include "base/functional/callback.h" |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 17 | #include "content/browser/aggregation_service/aggregatable_report.h" |
| 18 | #include "content/browser/aggregation_service/aggregation_service_key_fetcher.h" |
| 19 | #include "content/browser/aggregation_service/public_key.h" |
| 20 | #include "content/common/content_export.h" |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 21 | |
Nan Lin | 66d388d | 2021-10-20 16:03:09 | [diff] [blame] | 22 | template <class T> |
| 23 | class scoped_refptr; |
| 24 | |
| 25 | namespace network { |
| 26 | class SharedURLLoaderFactory; |
| 27 | } // namespace network |
| 28 | |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 29 | namespace content { |
| 30 | |
Nan Lin | 89244d6 | 2021-11-12 21:38:17 | [diff] [blame] | 31 | class AggregationServiceStorageContext; |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 32 | class StoragePartition; |
| 33 | |
| 34 | // This class provides an interface for assembling an aggregatable report. It is |
| 35 | // therefore responsible for taking a request, identifying and requesting the |
| 36 | // appropriate public keys, and generating and returning the AggregatableReport. |
| 37 | class CONTENT_EXPORT AggregatableReportAssembler { |
| 38 | public: |
Nan Lin | d637a9c9 | 2022-02-24 02:48:02 | [diff] [blame] | 39 | // These values are persisted to logs. Entries should not be renumbered and |
| 40 | // numeric values should never be reused. |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 41 | enum class AssemblyStatus { |
Nan Lin | d637a9c9 | 2022-02-24 02:48:02 | [diff] [blame] | 42 | kOk = 0, |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 43 | |
| 44 | // The attempt to fetch a public key failed. |
Nan Lin | d637a9c9 | 2022-02-24 02:48:02 | [diff] [blame] | 45 | kPublicKeyFetchFailed = 1, |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 46 | |
| 47 | // An internal error occurred while attempting to construct the report. |
Nan Lin | d637a9c9 | 2022-02-24 02:48:02 | [diff] [blame] | 48 | kAssemblyFailed = 2, |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 49 | |
| 50 | // The limit on the number of simultenous requests has been reached. |
Nan Lin | d637a9c9 | 2022-02-24 02:48:02 | [diff] [blame] | 51 | kTooManySimultaneousRequests = 3, |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 52 | kMaxValue = kTooManySimultaneousRequests, |
| 53 | }; |
| 54 | |
| 55 | using AssemblyCallback = |
Nan Lin | 55ad2a5a | 2022-08-15 21:32:57 | [diff] [blame] | 56 | base::OnceCallback<void(AggregatableReportRequest, |
Dan McArdle | 08ad611 | 2023-11-21 20:39:47 | [diff] [blame] | 57 | std::optional<AggregatableReport>, |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 58 | AssemblyStatus)>; |
| 59 | |
| 60 | // While we shouldn't hit these limits in typical usage, we protect against |
| 61 | // the possibility of unbounded memory growth |
| 62 | static constexpr size_t kMaxSimultaneousRequests = 1000; |
| 63 | |
Nan Lin | 89244d6 | 2021-11-12 21:38:17 | [diff] [blame] | 64 | AggregatableReportAssembler(AggregationServiceStorageContext* storage_context, |
Nan Lin | 66d388d | 2021-10-20 16:03:09 | [diff] [blame] | 65 | StoragePartition* storage_partition); |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 66 | // Not copyable or movable. |
| 67 | AggregatableReportAssembler(const AggregatableReportAssembler& other) = |
| 68 | delete; |
| 69 | AggregatableReportAssembler& operator=( |
| 70 | const AggregatableReportAssembler& other) = delete; |
| 71 | virtual ~AggregatableReportAssembler(); |
| 72 | |
| 73 | static std::unique_ptr<AggregatableReportAssembler> CreateForTesting( |
| 74 | std::unique_ptr<AggregationServiceKeyFetcher> fetcher, |
| 75 | std::unique_ptr<AggregatableReport::Provider> report_provider); |
| 76 | |
Nan Lin | 66d388d | 2021-10-20 16:03:09 | [diff] [blame] | 77 | // Used by the aggregation service tool to inject a `url_loader_factory` to |
| 78 | // AggregationServiceNetworkFetcherImpl if one is provided. |
| 79 | static std::unique_ptr<AggregatableReportAssembler> CreateForTesting( |
Nan Lin | 89244d6 | 2021-11-12 21:38:17 | [diff] [blame] | 80 | AggregationServiceStorageContext* storage_context, |
Alex Turner | 8868723f | 2022-03-08 00:55:25 | [diff] [blame] | 81 | scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, |
| 82 | bool enable_debug_logging); |
Nan Lin | 66d388d | 2021-10-20 16:03:09 | [diff] [blame] | 83 | |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 84 | // Fetches the necessary public keys and uses it to construct an |
| 85 | // AggregatableReport from the information in `report_request`. See the |
| 86 | // AggregatableReport documentation for more detail on the returned report. |
Nan Lin | 89244d6 | 2021-11-12 21:38:17 | [diff] [blame] | 87 | virtual void AssembleReport(AggregatableReportRequest report_request, |
| 88 | AssemblyCallback callback); |
| 89 | |
| 90 | protected: |
| 91 | // For testing only. |
| 92 | AggregatableReportAssembler( |
| 93 | AggregationServiceStorageContext* storage_context, |
Alex Turner | 8868723f | 2022-03-08 00:55:25 | [diff] [blame] | 94 | scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, |
| 95 | bool enable_debug_logging = false); |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 96 | |
| 97 | private: |
| 98 | // Represents a request to assemble a report that has not completed. |
| 99 | struct PendingRequest { |
| 100 | PendingRequest(AggregatableReportRequest report_request, |
| 101 | AssemblyCallback callback, |
Nan Lin | 4c75cd8 | 2022-02-18 23:39:34 | [diff] [blame] | 102 | size_t num_processing_urls); |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 103 | // Move-only. |
| 104 | PendingRequest(PendingRequest&& other); |
| 105 | PendingRequest& operator=(PendingRequest&& other); |
| 106 | ~PendingRequest(); |
| 107 | |
| 108 | AggregatableReportRequest report_request; |
| 109 | AssemblyCallback callback; |
| 110 | |
| 111 | // How many key fetches for this request have returned, including errors. |
| 112 | size_t num_returned_key_fetches = 0; |
| 113 | |
| 114 | // The PublicKey returned for each key fetch request. Indices correspond to |
Nan Lin | 4c75cd8 | 2022-02-18 23:39:34 | [diff] [blame] | 115 | // the ordering of `report_request.processing_urls`. Each element is |
Dan McArdle | 08ad611 | 2023-11-21 20:39:47 | [diff] [blame] | 116 | // `std::nullopt` if that key fetch either has not yet returned or has |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 117 | // returned an error. |
Dan McArdle | 08ad611 | 2023-11-21 20:39:47 | [diff] [blame] | 118 | std::vector<std::optional<PublicKey>> processing_url_keys; |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 119 | }; |
| 120 | |
| 121 | AggregatableReportAssembler( |
| 122 | std::unique_ptr<AggregationServiceKeyFetcher> fetcher, |
| 123 | std::unique_ptr<AggregatableReport::Provider> report_provider); |
| 124 | |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 125 | // Called when a result is returned from the key fetcher. Handles throwing |
| 126 | // errors on a failed fetch, waiting for both results to return and calling |
Alex Turner | 81c5916 | 2022-03-15 21:50:12 | [diff] [blame] | 127 | // into `OnAllPublicKeysFetched()` when appropriate. `processing_url_index` is |
| 128 | // an index into the corresponding AggregatableReportRequest's |
| 129 | // `processing_urls` vector, indicating which URL this fetch is for. |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 130 | void OnPublicKeyFetched( |
| 131 | int64_t report_id, |
Nan Lin | 4c75cd8 | 2022-02-18 23:39:34 | [diff] [blame] | 132 | size_t processing_url_index, |
Dan McArdle | 08ad611 | 2023-11-21 20:39:47 | [diff] [blame] | 133 | std::optional<PublicKey> key, |
Alex Turner | 7b0c6b6 | 2021-10-05 18:34:39 | [diff] [blame] | 134 | AggregationServiceKeyFetcher::PublicKeyFetchStatus status); |
| 135 | |
| 136 | // Call when all results have been returned from the key fetcher. Handles |
| 137 | // calling into `AssembleReportUsingKeys()` when appropriate and returning |
| 138 | // any assembled report or throwing an error if assembly fails. |
| 139 | void OnAllPublicKeysFetched(int64_t report_id, |
| 140 | PendingRequest& pending_request); |
| 141 | |
| 142 | // Keyed by a token for easier lookup. |
| 143 | base::flat_map<int64_t, PendingRequest> pending_requests_; |
| 144 | |
| 145 | // Used to generate unique ids for PendingRequests. These need to be unique |
| 146 | // per Assembler for tracking pending requests. |
| 147 | int64_t unique_id_counter_ = 0; |
| 148 | |
| 149 | std::unique_ptr<AggregationServiceKeyFetcher> fetcher_; |
| 150 | std::unique_ptr<AggregatableReport::Provider> report_provider_; |
| 151 | }; |
| 152 | |
| 153 | } // namespace content |
| 154 | |
| 155 | #endif // CONTENT_BROWSER_AGGREGATION_SERVICE_AGGREGATABLE_REPORT_ASSEMBLER_H_ |