blob: d891801304e98c35d8f37bb468250cdf2d538174 [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"
juliatuttle586843332017-03-27 16:22:3714#include "base/macros.h"
15#include "base/stl_util.h"
16#include "base/time/time.h"
17#include "base/values.h"
18#include "net/base/net_export.h"
Lily Chenfc92ff42019-05-06 22:59:1019#include "net/reporting/reporting_endpoint.h"
Lily Chenefb6fcf2019-04-19 04:17:5420#include "net/reporting/reporting_header_parser.h"
juliatuttle667c0bb2017-07-06 15:17:1321#include "net/reporting/reporting_report.h"
juliatuttle586843332017-03-27 16:22:3722#include "url/gurl.h"
23#include "url/origin.h"
24
25namespace net {
26
Lily Chen731a95c2019-05-06 22:27:2227class ReportingContext;
28
juliatuttle586843332017-03-27 16:22:3729// The cache holds undelivered reports and clients (per-origin endpoint
30// configurations) in memory. (It is not responsible for persisting them.)
31//
Lily Chenefb6fcf2019-04-19 04:17:5432// Each Reporting "endpoint" represents a report collector at some specified
33// URL. Endpoints are organized into named "endpoint groups", each of which
34// additionally specifes some properties such as expiration time.
35// A "client" represents the entire endpoint configuration set by an origin via
36// a Report-To header, which consists of multiple endpoint groups, each of which
37// consists of multiple endpoints. An endpoint group is keyed by its name. An
38// endpoint is unkeyed except by the client and group structure tree above it.
39//
40// The cache implementation corresponds roughly to the "Reporting cache"
41// described in the spec, except that endpoints and clients are stored in a more
42// structurally-convenient way, and endpoint failures/retry-after are tracked in
43// ReportingEndpointManager.
juliatuttle72a9ba62017-03-28 17:28:5244//
45// The cache implementation has the notion of "pending" reports. These are
46// reports that are part of an active delivery attempt, so they won't be
47// actually deallocated. Any attempt to remove a pending report wil mark it
48// "doomed", which will cause it to be deallocated once it is no longer pending.
juliatuttle586843332017-03-27 16:22:3749class NET_EXPORT ReportingCache {
50 public:
Lily Chenc5652312019-03-20 21:58:3051 class PersistentReportingStore;
52
Sam Burnett1446f0dd2019-07-16 04:19:3053 static std::unique_ptr<ReportingCache> Create(ReportingContext* context);
juliatuttle586843332017-03-27 16:22:3754
juliatuttle0c436c8c2017-06-05 16:57:0455 virtual ~ReportingCache();
juliatuttle586843332017-03-27 16:22:3756
57 // Adds a report to the cache.
58 //
59 // All parameters correspond to the desired values for the relevant fields in
60 // ReportingReport.
Lily Chen09383462020-04-09 21:39:0661 virtual void AddReport(const NetworkIsolationKey& network_isolation_key,
62 const GURL& url,
Douglas Creagerf6cb49f72018-07-19 20:14:5363 const std::string& user_agent,
Lily Chenefb6fcf2019-04-19 04:17:5464 const std::string& group_name,
juliatuttle0c436c8c2017-06-05 16:57:0465 const std::string& type,
66 std::unique_ptr<const base::Value> body,
Julia Tuttle107e30672018-03-29 18:48:4267 int depth,
juliatuttle0c436c8c2017-06-05 16:57:0468 base::TimeTicks queued,
69 int attempts) = 0;
juliatuttle586843332017-03-27 16:22:3770
71 // Gets all reports in the cache. The returned pointers are valid as long as
72 // either no calls to |RemoveReports| have happened or the reports' |pending|
73 // flag has been set to true using |SetReportsPending|. Does not return
74 // doomed reports (pending reports for which removal has been requested).
75 //
76 // (Clears any existing data in |*reports_out|.)
juliatuttle0c436c8c2017-06-05 16:57:0477 virtual void GetReports(
78 std::vector<const ReportingReport*>* reports_out) const = 0;
juliatuttle586843332017-03-27 16:22:3779
Douglas Creager0b937ec2018-04-13 13:53:0980 // Gets all reports in the cache, including pending and doomed reports, as a
81 // base::Value.
82 virtual base::Value GetReportsAsValue() const = 0;
83
Lily Chend9ab4e52020-01-03 22:04:4484 // Gets all reports in the cache that aren't pending or doomed (i.e. that are
85 // eligible for delivery), and marks returned reports as pending in
86 // preparation for a delivery attempt. The returned pointers are valid as long
87 // as the reports are still pending.
88 virtual std::vector<const ReportingReport*> GetReportsToDeliver() = 0;
juliatuttle586843332017-03-27 16:22:3789
90 // Unmarks a set of reports as pending. |reports| must be previously marked as
91 // pending.
juliatuttle0c436c8c2017-06-05 16:57:0492 virtual void ClearReportsPending(
93 const std::vector<const ReportingReport*>& reports) = 0;
juliatuttle586843332017-03-27 16:22:3794
95 // Increments |attempts| on a set of reports.
juliatuttle0c436c8c2017-06-05 16:57:0496 virtual void IncrementReportsAttempts(
97 const std::vector<const ReportingReport*>& reports) = 0;
juliatuttle586843332017-03-27 16:22:3798
Lily Chenefb6fcf2019-04-19 04:17:5499 // Records that we attempted (and possibly succeeded at) delivering
100 // |reports_delivered| reports to the specified endpoint.
Lily Chenad5dd0802020-03-10 21:58:09101 virtual void IncrementEndpointDeliveries(
102 const ReportingEndpointGroupKey& group_key,
103 const GURL& url,
104 int reports_delivered,
105 bool successful) = 0;
Douglas Creager1f0b5022018-04-10 18:19:13106
juliatuttle586843332017-03-27 16:22:37107 // Removes a set of reports. Any reports that are pending will not be removed
108 // immediately, but rather marked doomed and removed once they are no longer
109 // pending.
juliatuttle667c0bb2017-07-06 15:17:13110 virtual void RemoveReports(const std::vector<const ReportingReport*>& reports,
111 ReportingReport::Outcome outcome) = 0;
juliatuttle586843332017-03-27 16:22:37112
113 // Removes all reports. Like |RemoveReports()|, pending reports are doomed
114 // until no longer pending.
juliatuttle667c0bb2017-07-06 15:17:13115 virtual void RemoveAllReports(ReportingReport::Outcome outcome) = 0;
juliatuttle586843332017-03-27 16:22:37116
juliatuttle586843332017-03-27 16:22:37117 // Gets the count of reports in the cache, *including* doomed reports.
118 //
119 // Needed to ensure that doomed reports are eventually deleted, since no
120 // method provides a view of *every* report in the cache, just non-doomed
121 // ones.
juliatuttle0c436c8c2017-06-05 16:57:04122 virtual size_t GetFullReportCountForTesting() const = 0;
juliatuttle586843332017-03-27 16:22:37123
juliatuttle0c436c8c2017-06-05 16:57:04124 virtual bool IsReportPendingForTesting(
125 const ReportingReport* report) const = 0;
juliatuttle586843332017-03-27 16:22:37126
juliatuttle0c436c8c2017-06-05 16:57:04127 virtual bool IsReportDoomedForTesting(
128 const ReportingReport* report) const = 0;
Lily Chenefb6fcf2019-04-19 04:17:54129
130 // Adds a new client to the cache for |origin|, or updates the existing one
131 // to match the new header. All values are assumed to be valid as they have
132 // passed through the ReportingHeaderParser.
133 virtual void OnParsedHeader(
Lily Chenf0dd74b2020-04-07 00:25:58134 const NetworkIsolationKey& network_isolation_key,
Lily Chenefb6fcf2019-04-19 04:17:54135 const url::Origin& origin,
136 std::vector<ReportingEndpointGroup> parsed_header) = 0;
137
138 // Gets all the origins of clients in the cache.
Lily Chenad5dd0802020-03-10 21:58:09139 virtual std::set<url::Origin> GetAllOrigins() const = 0;
Lily Chenefb6fcf2019-04-19 04:17:54140
Lily Chenad5dd0802020-03-10 21:58:09141 // Remove client for the given (NIK, origin) pair, if it exists in the cache.
142 // All endpoint groups and endpoints for that client are also removed.
143 virtual void RemoveClient(const NetworkIsolationKey& network_isolation_key,
144 const url::Origin& origin) = 0;
145
146 // Remove all clients for the given |origin|, if any exists in the cache.
Lily Chenefb6fcf2019-04-19 04:17:54147 // All endpoint groups and endpoints for |origin| are also removed.
Lily Chenad5dd0802020-03-10 21:58:09148 virtual void RemoveClientsForOrigin(const url::Origin& origin) = 0;
Lily Chenefb6fcf2019-04-19 04:17:54149
150 // Remove all clients, groups, and endpoints from the cache.
151 virtual void RemoveAllClients() = 0;
152
Lily Chenad5dd0802020-03-10 21:58:09153 // Remove the endpoint group matching |group_key|, and remove
154 // all endpoints for that group. May cause the client it was associated with
155 // to be deleted if it becomes empty.
156 virtual void RemoveEndpointGroup(
157 const ReportingEndpointGroupKey& group_key) = 0;
Lily Chenefb6fcf2019-04-19 04:17:54158
159 // Remove all endpoints for with |url|, regardless of origin or group. Used
160 // when a delivery returns 410 Gone. May cause deletion of groups/clients if
161 // they become empty.
162 virtual void RemoveEndpointsForUrl(const GURL& url) = 0;
163
Sam Burnett00099fc12019-07-24 23:26:15164 // Insert endpoints and endpoint groups that have been loaded from the store.
165 //
166 // You must only call this method if context.store() was non-null when you
167 // constructed the cache and persist_clients_across_restarts in your
168 // ReportingPolicy is true.
169 virtual void AddClientsLoadedFromStore(
170 std::vector<ReportingEndpoint> loaded_endpoints,
171 std::vector<CachedReportingEndpointGroup> loaded_endpoint_groups) = 0;
172
Lily Chenefb6fcf2019-04-19 04:17:54173 // Gets endpoints that apply to a delivery for |origin| and |group|.
174 //
175 // First checks for |group| in a client exactly matching |origin|.
176 // If none exists, then checks for |group| in clients for superdomains
177 // of |origin| which have include_subdomains enabled, returning only the
178 // endpoints for the most specific applicable parent origin of |origin|. If
179 // there are multiple origins with that group within the most specific
180 // applicable superdomain, gets endpoints for that group from only one of
181 // them. The group must not be expired.
182 //
183 // For example, given the origin https://foo.bar.baz.com/, the cache
184 // would prioritize returning each potential match below over the ones below
185 // it, for groups with name |group| with include_subdomains enabled:
186 // 1. https://foo.bar.baz.com/ (exact origin match)
187 // 2. https://foo.bar.baz.com:444/ (technically, a superdomain)
188 // 3. https://bar.baz.com/, https://bar.baz.com:444/, etc. (superdomain)
189 // 4. https://baz.com/, https://baz.com:444/, etc. (superdomain)
190 // If both https://bar.baz.com/ and https://bar.baz.com:444/ had a group with
191 // name |group| with include_subdomains enabled, this method would return
192 // endpoints from that group from the earliest-inserted origin.
Lily Chenfc92ff42019-05-06 22:59:10193 virtual std::vector<ReportingEndpoint> GetCandidateEndpointsForDelivery(
Lily Chenad5dd0802020-03-10 21:58:09194 const ReportingEndpointGroupKey& group_key) = 0;
Lily Chenefb6fcf2019-04-19 04:17:54195
196 // Gets the status of all clients in the cache, including expired ones, as a
197 // base::Value.
198 virtual base::Value GetClientsAsValue() const = 0;
199
200 // Gets the total number of endpoints in the cache across all origins.
201 virtual size_t GetEndpointCount() const = 0;
202
Sam Burnettf13c06b2019-07-30 15:53:49203 // Flush the contents of the cache to disk, if applicable.
204 virtual void Flush() = 0;
205
Lily Chenad5dd0802020-03-10 21:58:09206 // Finds an endpoint for the given |group_key| and |url|, otherwise returns an
207 // invalid ReportingEndpoint.
208 virtual ReportingEndpoint GetEndpointForTesting(
209 const ReportingEndpointGroupKey& group_key,
210 const GURL& url) const = 0;
Lily Chenefb6fcf2019-04-19 04:17:54211
212 // Returns whether an endpoint group with exactly the given properties exists
213 // in the cache. If |expires| is base::Time(), it will not be checked.
214 virtual bool EndpointGroupExistsForTesting(
Lily Chenad5dd0802020-03-10 21:58:09215 const ReportingEndpointGroupKey& group_key,
Lily Chenefb6fcf2019-04-19 04:17:54216 OriginSubdomains include_subdomains,
217 base::Time expires) const = 0;
218
Lily Chenad5dd0802020-03-10 21:58:09219 // Returns whether a client for the given (NIK, Origin) exists.
220 virtual bool ClientExistsForTesting(
221 const NetworkIsolationKey& network_isolation_key,
222 const url::Origin& origin) const = 0;
223
Lily Chenefb6fcf2019-04-19 04:17:54224 // Returns number of endpoint groups.
225 virtual size_t GetEndpointGroupCountForTesting() const = 0;
226
Lily Chenad5dd0802020-03-10 21:58:09227 // Returns number of endpoint groups.
228 virtual size_t GetClientCountForTesting() const = 0;
229
Lily Chenefb6fcf2019-04-19 04:17:54230 // Sets an endpoint with the given properties in a group with the given
231 // properties, bypassing header parsing. Note that the endpoint is not
232 // guaranteed to exist in the cache after calling this function, if endpoint
233 // eviction is triggered. Unlike the AddOrUpdate*() methods used in header
234 // parsing, this method inserts or updates a single endpoint while leaving the
235 // exiting configuration for that origin intact.
Lily Chenad5dd0802020-03-10 21:58:09236 virtual void SetEndpointForTesting(const ReportingEndpointGroupKey& group_key,
Lily Chenefb6fcf2019-04-19 04:17:54237 const GURL& url,
238 OriginSubdomains include_subdomains,
239 base::Time expires,
240 int priority,
241 int weight) = 0;
juliatuttle586843332017-03-27 16:22:37242};
243
Lily Chenc5652312019-03-20 21:58:30244// Persistent storage for Reporting reports and clients.
245class NET_EXPORT ReportingCache::PersistentReportingStore {
246 public:
Lily Chen6a00fa362019-04-26 19:22:55247 using ReportingClientsLoadedCallback =
Lily Chenfc92ff42019-05-06 22:59:10248 base::OnceCallback<void(std::vector<ReportingEndpoint>,
Lily Chen6a00fa362019-04-26 19:22:55249 std::vector<CachedReportingEndpointGroup>)>;
250
Lily Chenc5652312019-03-20 21:58:30251 PersistentReportingStore() = default;
252 virtual ~PersistentReportingStore() = default;
253
Lily Chen6a00fa362019-04-26 19:22:55254 // Initializes the store and retrieves stored endpoints and endpoint groups.
255 // Called only once at startup.
256 virtual void LoadReportingClients(
257 ReportingClientsLoadedCallback loaded_callback) = 0;
258
259 // Adds an endpoint to the store.
Lily Chenfc92ff42019-05-06 22:59:10260 virtual void AddReportingEndpoint(const ReportingEndpoint& endpoint) = 0;
Lily Chen6a00fa362019-04-26 19:22:55261 // Adds an endpoint group to the store.
262 virtual void AddReportingEndpointGroup(
263 const CachedReportingEndpointGroup& group) = 0;
264
265 // Updates the access time of an endpoint group in the store.
266 virtual void UpdateReportingEndpointGroupAccessTime(
267 const CachedReportingEndpointGroup& group) = 0;
268
269 // Updates the details of an endpoint in the store.
270 virtual void UpdateReportingEndpointDetails(
Lily Chenfc92ff42019-05-06 22:59:10271 const ReportingEndpoint& endpoint) = 0;
Lily Chen6a00fa362019-04-26 19:22:55272 // Updates the details of an endpoint group in the store.
273 virtual void UpdateReportingEndpointGroupDetails(
274 const CachedReportingEndpointGroup& group) = 0;
275
276 // Deletes an endpoint from the store.
Lily Chenfc92ff42019-05-06 22:59:10277 virtual void DeleteReportingEndpoint(const ReportingEndpoint& endpoint) = 0;
Lily Chen6a00fa362019-04-26 19:22:55278 // Deletes an endpoint group from the store.
279 virtual void DeleteReportingEndpointGroup(
280 const CachedReportingEndpointGroup& group) = 0;
281
282 // TODO(chlily): methods to load, add, and delete reports will be added.
Lily Chenc5652312019-03-20 21:58:30283
284 // Flushes the store.
285 virtual void Flush() = 0;
286
287 private:
288 DISALLOW_COPY_AND_ASSIGN(PersistentReportingStore);
289};
290
juliatuttle586843332017-03-27 16:22:37291} // namespace net
292
293#endif // NET_REPORTING_REPORTING_CACHE_H_