blob: 8ec4a449e958018676b39b845afad39392348c30 [file] [log] [blame]
juliatuttle586843332017-03-27 16:22:371// Copyright 2017 The Chromium Authors. All rights reserved.
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 NET_REPORTING_REPORTING_CACHE_H_
6#define NET_REPORTING_REPORTING_CACHE_H_
7
juliatuttle586843332017-03-27 16:22:378#include <memory>
Lily Chenad5dd0802020-03-10 21:58:099#include <set>
Lily Chenefb6fcf2019-04-19 04:17:5410#include <string>
juliatuttle586843332017-03-27 16:22:3711#include <vector>
12
Hans Wennborga65658a2020-04-21 08:09:4613#include "base/callback.h"
Ian Clelland4c336472021-08-23 22:20:0014#include "base/containers/flat_set.h"
juliatuttle586843332017-03-27 16:22:3715#include "base/macros.h"
juliatuttle586843332017-03-27 16:22:3716#include "base/time/time.h"
Ian Clellande07e64b2021-08-23 16:29:4317#include "base/unguessable_token.h"
juliatuttle586843332017-03-27 16:22:3718#include "base/values.h"
19#include "net/base/net_export.h"
Lily Chenfc92ff42019-05-06 22:59:1020#include "net/reporting/reporting_endpoint.h"
Lily Chenefb6fcf2019-04-19 04:17:5421#include "net/reporting/reporting_header_parser.h"
juliatuttle667c0bb2017-07-06 15:17:1322#include "net/reporting/reporting_report.h"
Ian Clellande07e64b2021-08-23 16:29:4323#include "third_party/abseil-cpp/absl/types/optional.h"
juliatuttle586843332017-03-27 16:22:3724#include "url/gurl.h"
25#include "url/origin.h"
26
27namespace net {
28
Lily Chen731a95c2019-05-06 22:27:2229class ReportingContext;
30
juliatuttle586843332017-03-27 16:22:3731// The cache holds undelivered reports and clients (per-origin endpoint
32// configurations) in memory. (It is not responsible for persisting them.)
33//
Lily Chenefb6fcf2019-04-19 04:17:5434// Each Reporting "endpoint" represents a report collector at some specified
35// URL. Endpoints are organized into named "endpoint groups", each of which
36// additionally specifes some properties such as expiration time.
37// A "client" represents the entire endpoint configuration set by an origin via
38// a Report-To header, which consists of multiple endpoint groups, each of which
39// consists of multiple endpoints. An endpoint group is keyed by its name. An
40// endpoint is unkeyed except by the client and group structure tree above it.
41//
42// The cache implementation corresponds roughly to the "Reporting cache"
43// described in the spec, except that endpoints and clients are stored in a more
44// structurally-convenient way, and endpoint failures/retry-after are tracked in
45// ReportingEndpointManager.
juliatuttle72a9ba62017-03-28 17:28:5246//
47// The cache implementation has the notion of "pending" reports. These are
48// reports that are part of an active delivery attempt, so they won't be
49// actually deallocated. Any attempt to remove a pending report wil mark it
50// "doomed", which will cause it to be deallocated once it is no longer pending.
juliatuttle586843332017-03-27 16:22:3751class NET_EXPORT ReportingCache {
52 public:
Lily Chenc5652312019-03-20 21:58:3053 class PersistentReportingStore;
54
Sam Burnett1446f0dd2019-07-16 04:19:3055 static std::unique_ptr<ReportingCache> Create(ReportingContext* context);
juliatuttle586843332017-03-27 16:22:3756
juliatuttle0c436c8c2017-06-05 16:57:0457 virtual ~ReportingCache();
juliatuttle586843332017-03-27 16:22:3758
59 // Adds a report to the cache.
60 //
Ian Clellande07e64b2021-08-23 16:29:4361 // |reporting_source| and |network_isolation_key| will be used when the
62 // report is delivered, to determine which endpoints are eligible to receive
63 // this report, and which other reports this report can be batched with.
64 //
65 // All other parameters correspond to the desired values for the relevant
66 // fields in ReportingReport.
67 virtual void AddReport(
68 const absl::optional<base::UnguessableToken>& reporting_source,
69 const NetworkIsolationKey& network_isolation_key,
70 const GURL& url,
71 const std::string& user_agent,
72 const std::string& group_name,
73 const std::string& type,
74 std::unique_ptr<const base::Value> body,
75 int depth,
76 base::TimeTicks queued,
77 int attempts) = 0;
juliatuttle586843332017-03-27 16:22:3778
79 // Gets all reports in the cache. The returned pointers are valid as long as
80 // either no calls to |RemoveReports| have happened or the reports' |pending|
81 // flag has been set to true using |SetReportsPending|. Does not return
82 // doomed reports (pending reports for which removal has been requested).
83 //
84 // (Clears any existing data in |*reports_out|.)
juliatuttle0c436c8c2017-06-05 16:57:0485 virtual void GetReports(
86 std::vector<const ReportingReport*>* reports_out) const = 0;
juliatuttle586843332017-03-27 16:22:3787
Douglas Creager0b937ec2018-04-13 13:53:0988 // Gets all reports in the cache, including pending and doomed reports, as a
89 // base::Value.
90 virtual base::Value GetReportsAsValue() const = 0;
91
Lily Chend9ab4e52020-01-03 22:04:4492 // Gets all reports in the cache that aren't pending or doomed (i.e. that are
93 // eligible for delivery), and marks returned reports as pending in
94 // preparation for a delivery attempt. The returned pointers are valid as long
95 // as the reports are still pending.
96 virtual std::vector<const ReportingReport*> GetReportsToDeliver() = 0;
juliatuttle586843332017-03-27 16:22:3797
Ian Clelland4c336472021-08-23 22:20:0098 // Gets all reports in the cache which are eligible for delivery, which were
99 // queued for a single `reporting_source`, and marks returned reports as
100 // pending in preparation for a delivery attempt. The returned pointers are
101 // valid as long as the reports are still pending. This method is used when a
102 // reporting source is being destroyed, to trigger delivery of any remaining
103 // outstanding reports.
104 virtual std::vector<const ReportingReport*> GetReportsToDeliverForSource(
105 const base::UnguessableToken& reporting_source) = 0;
106
juliatuttle586843332017-03-27 16:22:37107 // Unmarks a set of reports as pending. |reports| must be previously marked as
108 // pending.
juliatuttle0c436c8c2017-06-05 16:57:04109 virtual void ClearReportsPending(
110 const std::vector<const ReportingReport*>& reports) = 0;
juliatuttle586843332017-03-27 16:22:37111
112 // Increments |attempts| on a set of reports.
juliatuttle0c436c8c2017-06-05 16:57:04113 virtual void IncrementReportsAttempts(
114 const std::vector<const ReportingReport*>& reports) = 0;
juliatuttle586843332017-03-27 16:22:37115
Lily Chenefb6fcf2019-04-19 04:17:54116 // Records that we attempted (and possibly succeeded at) delivering
117 // |reports_delivered| reports to the specified endpoint.
Lily Chenad5dd0802020-03-10 21:58:09118 virtual void IncrementEndpointDeliveries(
119 const ReportingEndpointGroupKey& group_key,
120 const GURL& url,
121 int reports_delivered,
122 bool successful) = 0;
Douglas Creager1f0b5022018-04-10 18:19:13123
Ian Clelland4c336472021-08-23 22:20:00124 // Marks a `reporting_source` as expired, when the source (document or
125 // worker) has beed destroyed. The endpoint configuration for the source will
126 // be removed by the garbage collector once all outstanding reports have been
127 // delivered or expired.
128 virtual void SetExpiredSource(
129 const base::UnguessableToken& reporting_source) = 0;
130
131 // Gets the current set of expired reporting sources.
132 virtual const base::flat_set<base::UnguessableToken>& GetExpiredSources()
133 const = 0;
134
juliatuttle586843332017-03-27 16:22:37135 // Removes a set of reports. Any reports that are pending will not be removed
136 // immediately, but rather marked doomed and removed once they are no longer
137 // pending.
Yutaka Hirano1515aed2021-07-09 07:38:43138 virtual void RemoveReports(
139 const std::vector<const ReportingReport*>& reports) = 0;
juliatuttle586843332017-03-27 16:22:37140
141 // Removes all reports. Like |RemoveReports()|, pending reports are doomed
142 // until no longer pending.
Yutaka Hirano1515aed2021-07-09 07:38:43143 virtual void RemoveAllReports() = 0;
juliatuttle586843332017-03-27 16:22:37144
juliatuttle586843332017-03-27 16:22:37145 // Gets the count of reports in the cache, *including* doomed reports.
146 //
147 // Needed to ensure that doomed reports are eventually deleted, since no
148 // method provides a view of *every* report in the cache, just non-doomed
149 // ones.
juliatuttle0c436c8c2017-06-05 16:57:04150 virtual size_t GetFullReportCountForTesting() const = 0;
juliatuttle586843332017-03-27 16:22:37151
Ian Clelland4c336472021-08-23 22:20:00152 // Gets the count of reports in the cache with a specific `status`.
153 virtual size_t GetReportCountWithStatusForTesting(
154 ReportingReport::Status status) const = 0;
155
juliatuttle0c436c8c2017-06-05 16:57:04156 virtual bool IsReportPendingForTesting(
157 const ReportingReport* report) const = 0;
juliatuttle586843332017-03-27 16:22:37158
juliatuttle0c436c8c2017-06-05 16:57:04159 virtual bool IsReportDoomedForTesting(
160 const ReportingReport* report) const = 0;
Lily Chenefb6fcf2019-04-19 04:17:54161
162 // Adds a new client to the cache for |origin|, or updates the existing one
163 // to match the new header. All values are assumed to be valid as they have
164 // passed through the ReportingHeaderParser.
165 virtual void OnParsedHeader(
Lily Chenf0dd74b2020-04-07 00:25:58166 const NetworkIsolationKey& network_isolation_key,
Lily Chenefb6fcf2019-04-19 04:17:54167 const url::Origin& origin,
168 std::vector<ReportingEndpointGroup> parsed_header) = 0;
169
Ian Clellanda52d5472021-08-23 18:33:53170 // Adds named endpoints for |reporting_source| to the cache, based on the
171 // received Reporting-Endpoints header.
172 // |reporting_source| is the token identifying the document or worker with
173 // which this header was received, and may not be empty.
174 // |origin| is the origin of the document or worker represented by
175 // |reporting_source|, and |network_isolation_key| is the appropriate NIK for
176 // that source. These two parameters are currently needed because the new
177 // Reporting API currently shares the cache, delivery agent and
178 // ReportingEndpoint struct with the old API.
179 virtual void OnParsedReportingEndpointsHeader(
180 const base::UnguessableToken& reporting_source,
181 std::vector<ReportingEndpoint> parsed_header) = 0;
182
Lily Chenefb6fcf2019-04-19 04:17:54183 // Gets all the origins of clients in the cache.
Lily Chenad5dd0802020-03-10 21:58:09184 virtual std::set<url::Origin> GetAllOrigins() const = 0;
Lily Chenefb6fcf2019-04-19 04:17:54185
Lily Chenad5dd0802020-03-10 21:58:09186 // Remove client for the given (NIK, origin) pair, if it exists in the cache.
187 // All endpoint groups and endpoints for that client are also removed.
188 virtual void RemoveClient(const NetworkIsolationKey& network_isolation_key,
189 const url::Origin& origin) = 0;
190
191 // Remove all clients for the given |origin|, if any exists in the cache.
Lily Chenefb6fcf2019-04-19 04:17:54192 // All endpoint groups and endpoints for |origin| are also removed.
Lily Chenad5dd0802020-03-10 21:58:09193 virtual void RemoveClientsForOrigin(const url::Origin& origin) = 0;
Lily Chenefb6fcf2019-04-19 04:17:54194
195 // Remove all clients, groups, and endpoints from the cache.
196 virtual void RemoveAllClients() = 0;
197
Lily Chenad5dd0802020-03-10 21:58:09198 // Remove the endpoint group matching |group_key|, and remove
199 // all endpoints for that group. May cause the client it was associated with
200 // to be deleted if it becomes empty.
201 virtual void RemoveEndpointGroup(
202 const ReportingEndpointGroupKey& group_key) = 0;
Lily Chenefb6fcf2019-04-19 04:17:54203
204 // Remove all endpoints for with |url|, regardless of origin or group. Used
205 // when a delivery returns 410 Gone. May cause deletion of groups/clients if
206 // they become empty.
207 virtual void RemoveEndpointsForUrl(const GURL& url) = 0;
208
Ian Clelland4c336472021-08-23 22:20:00209 // Remove `reporting_source` from the cache, including any configured
210 // endpoints. There should be no non-doomed reports in the cache for
211 // `reporting_source` when this is called.
212 virtual void RemoveSourceAndEndpoints(
213 const base::UnguessableToken& reporting_source) = 0;
214
Sam Burnett00099fc12019-07-24 23:26:15215 // Insert endpoints and endpoint groups that have been loaded from the store.
216 //
217 // You must only call this method if context.store() was non-null when you
218 // constructed the cache and persist_clients_across_restarts in your
219 // ReportingPolicy is true.
220 virtual void AddClientsLoadedFromStore(
221 std::vector<ReportingEndpoint> loaded_endpoints,
222 std::vector<CachedReportingEndpointGroup> loaded_endpoint_groups) = 0;
223
Lily Chenefb6fcf2019-04-19 04:17:54224 // Gets endpoints that apply to a delivery for |origin| and |group|.
225 //
226 // First checks for |group| in a client exactly matching |origin|.
227 // If none exists, then checks for |group| in clients for superdomains
228 // of |origin| which have include_subdomains enabled, returning only the
229 // endpoints for the most specific applicable parent origin of |origin|. If
230 // there are multiple origins with that group within the most specific
231 // applicable superdomain, gets endpoints for that group from only one of
232 // them. The group must not be expired.
233 //
234 // For example, given the origin https://foo.bar.baz.com/, the cache
235 // would prioritize returning each potential match below over the ones below
236 // it, for groups with name |group| with include_subdomains enabled:
237 // 1. https://foo.bar.baz.com/ (exact origin match)
238 // 2. https://foo.bar.baz.com:444/ (technically, a superdomain)
239 // 3. https://bar.baz.com/, https://bar.baz.com:444/, etc. (superdomain)
240 // 4. https://baz.com/, https://baz.com:444/, etc. (superdomain)
241 // If both https://bar.baz.com/ and https://bar.baz.com:444/ had a group with
242 // name |group| with include_subdomains enabled, this method would return
243 // endpoints from that group from the earliest-inserted origin.
Lily Chenfc92ff42019-05-06 22:59:10244 virtual std::vector<ReportingEndpoint> GetCandidateEndpointsForDelivery(
Lily Chenad5dd0802020-03-10 21:58:09245 const ReportingEndpointGroupKey& group_key) = 0;
Lily Chenefb6fcf2019-04-19 04:17:54246
247 // Gets the status of all clients in the cache, including expired ones, as a
248 // base::Value.
249 virtual base::Value GetClientsAsValue() const = 0;
250
251 // Gets the total number of endpoints in the cache across all origins.
252 virtual size_t GetEndpointCount() const = 0;
253
Sam Burnettf13c06b2019-07-30 15:53:49254 // Flush the contents of the cache to disk, if applicable.
255 virtual void Flush() = 0;
256
Ian Clellanda52d5472021-08-23 18:33:53257 // Returns the endpoint named |endpoint_name| for the reporting source, if it
258 // was configured with the Reporting-Endpoints header, otherwise returns an
259 // invalid ReportingEndpoint.
260 // |reporting_source| must not be empty.
261 virtual ReportingEndpoint GetV1EndpointForTesting(
262 const base::UnguessableToken& reporting_source,
263 const std::string& endpoint_name) const = 0;
264
Lily Chenad5dd0802020-03-10 21:58:09265 // Finds an endpoint for the given |group_key| and |url|, otherwise returns an
266 // invalid ReportingEndpoint.
267 virtual ReportingEndpoint GetEndpointForTesting(
268 const ReportingEndpointGroupKey& group_key,
269 const GURL& url) const = 0;
Lily Chenefb6fcf2019-04-19 04:17:54270
271 // Returns whether an endpoint group with exactly the given properties exists
272 // in the cache. If |expires| is base::Time(), it will not be checked.
273 virtual bool EndpointGroupExistsForTesting(
Lily Chenad5dd0802020-03-10 21:58:09274 const ReportingEndpointGroupKey& group_key,
Lily Chenefb6fcf2019-04-19 04:17:54275 OriginSubdomains include_subdomains,
276 base::Time expires) const = 0;
277
Lily Chenad5dd0802020-03-10 21:58:09278 // Returns whether a client for the given (NIK, Origin) exists.
279 virtual bool ClientExistsForTesting(
280 const NetworkIsolationKey& network_isolation_key,
281 const url::Origin& origin) const = 0;
282
Lily Chenefb6fcf2019-04-19 04:17:54283 // Returns number of endpoint groups.
284 virtual size_t GetEndpointGroupCountForTesting() const = 0;
285
Lily Chenad5dd0802020-03-10 21:58:09286 // Returns number of endpoint groups.
287 virtual size_t GetClientCountForTesting() const = 0;
288
Ian Clelland4c336472021-08-23 22:20:00289 // Returns number of reporting source tokens associated with endpoints.
290 virtual size_t GetReportingSourceCountForTesting() const = 0;
291
Lily Chenefb6fcf2019-04-19 04:17:54292 // Sets an endpoint with the given properties in a group with the given
293 // properties, bypassing header parsing. Note that the endpoint is not
294 // guaranteed to exist in the cache after calling this function, if endpoint
295 // eviction is triggered. Unlike the AddOrUpdate*() methods used in header
296 // parsing, this method inserts or updates a single endpoint while leaving the
Ian Clellanda52d5472021-08-23 18:33:53297 // existing configuration for that origin intact.
Lily Chenad5dd0802020-03-10 21:58:09298 virtual void SetEndpointForTesting(const ReportingEndpointGroupKey& group_key,
Lily Chenefb6fcf2019-04-19 04:17:54299 const GURL& url,
300 OriginSubdomains include_subdomains,
301 base::Time expires,
302 int priority,
303 int weight) = 0;
Ian Clellanda52d5472021-08-23 18:33:53304
305 // Sets a V1 named endpoint with the given key for |reporting_source|,
306 // bypassing header parsing. This method inserts a single endpoint while
307 // leaving the existing configuration for that source intact.
308 virtual void SetV1EndpointForTesting(
309 const ReportingEndpointGroupKey& group_key,
310 const base::UnguessableToken& reporting_source,
311 const GURL& url) = 0;
juliatuttle586843332017-03-27 16:22:37312};
313
Lily Chenc5652312019-03-20 21:58:30314// Persistent storage for Reporting reports and clients.
315class NET_EXPORT ReportingCache::PersistentReportingStore {
316 public:
Lily Chen6a00fa362019-04-26 19:22:55317 using ReportingClientsLoadedCallback =
Lily Chenfc92ff42019-05-06 22:59:10318 base::OnceCallback<void(std::vector<ReportingEndpoint>,
Lily Chen6a00fa362019-04-26 19:22:55319 std::vector<CachedReportingEndpointGroup>)>;
320
Lily Chenc5652312019-03-20 21:58:30321 PersistentReportingStore() = default;
322 virtual ~PersistentReportingStore() = default;
323
Lily Chen6a00fa362019-04-26 19:22:55324 // Initializes the store and retrieves stored endpoints and endpoint groups.
325 // Called only once at startup.
326 virtual void LoadReportingClients(
327 ReportingClientsLoadedCallback loaded_callback) = 0;
328
329 // Adds an endpoint to the store.
Lily Chenfc92ff42019-05-06 22:59:10330 virtual void AddReportingEndpoint(const ReportingEndpoint& endpoint) = 0;
Lily Chen6a00fa362019-04-26 19:22:55331 // Adds an endpoint group to the store.
332 virtual void AddReportingEndpointGroup(
333 const CachedReportingEndpointGroup& group) = 0;
334
335 // Updates the access time of an endpoint group in the store.
336 virtual void UpdateReportingEndpointGroupAccessTime(
337 const CachedReportingEndpointGroup& group) = 0;
338
339 // Updates the details of an endpoint in the store.
340 virtual void UpdateReportingEndpointDetails(
Lily Chenfc92ff42019-05-06 22:59:10341 const ReportingEndpoint& endpoint) = 0;
Lily Chen6a00fa362019-04-26 19:22:55342 // Updates the details of an endpoint group in the store.
343 virtual void UpdateReportingEndpointGroupDetails(
344 const CachedReportingEndpointGroup& group) = 0;
345
346 // Deletes an endpoint from the store.
Lily Chenfc92ff42019-05-06 22:59:10347 virtual void DeleteReportingEndpoint(const ReportingEndpoint& endpoint) = 0;
Lily Chen6a00fa362019-04-26 19:22:55348 // Deletes an endpoint group from the store.
349 virtual void DeleteReportingEndpointGroup(
350 const CachedReportingEndpointGroup& group) = 0;
351
352 // TODO(chlily): methods to load, add, and delete reports will be added.
Lily Chenc5652312019-03-20 21:58:30353
354 // Flushes the store.
355 virtual void Flush() = 0;
356
357 private:
358 DISALLOW_COPY_AND_ASSIGN(PersistentReportingStore);
359};
360
juliatuttle586843332017-03-27 16:22:37361} // namespace net
362
363#endif // NET_REPORTING_REPORTING_CACHE_H_