reporting_cache.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. // 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. #ifndef NET_REPORTING_REPORTING_CACHE_H_
  5. #define NET_REPORTING_REPORTING_CACHE_H_
  6. #include <memory>
  7. #include <set>
  8. #include <string>
  9. #include <vector>
  10. #include "base/callback.h"
  11. #include "base/containers/flat_map.h"
  12. #include "base/containers/flat_set.h"
  13. #include "base/time/time.h"
  14. #include "base/unguessable_token.h"
  15. #include "base/values.h"
  16. #include "net/base/net_export.h"
  17. #include "net/reporting/reporting_endpoint.h"
  18. #include "net/reporting/reporting_header_parser.h"
  19. #include "net/reporting/reporting_report.h"
  20. #include "third_party/abseil-cpp/absl/types/optional.h"
  21. #include "url/gurl.h"
  22. #include "url/origin.h"
  23. namespace net {
  24. class ReportingContext;
  25. class IsolationInfo;
  26. // The cache holds undelivered reports and clients (per-origin endpoint
  27. // configurations) in memory. (It is not responsible for persisting them.)
  28. //
  29. // Each Reporting "endpoint" represents a report collector at some specified
  30. // URL. Endpoints are organized into named "endpoint groups", each of which
  31. // additionally specifies some properties such as expiration time.
  32. // A "client" represents the entire endpoint configuration set by an origin via
  33. // a Report-To header, which consists of multiple endpoint groups, each of which
  34. // consists of multiple endpoints. An endpoint group is keyed by its name. An
  35. // endpoint is unkeyed except by the client and group structure tree above it.
  36. //
  37. // The cache implementation corresponds roughly to the "Reporting cache"
  38. // described in the spec, except that endpoints and clients are stored in a more
  39. // structurally-convenient way, and endpoint failures/retry-after are tracked in
  40. // ReportingEndpointManager.
  41. //
  42. // The cache implementation has the notion of "pending" reports. These are
  43. // reports that are part of an active delivery attempt, so they won't be
  44. // actually deallocated. Any attempt to remove a pending report will mark it
  45. // "doomed", which will cause it to be deallocated once it is no longer pending.
  46. class NET_EXPORT ReportingCache {
  47. public:
  48. class PersistentReportingStore;
  49. static std::unique_ptr<ReportingCache> Create(ReportingContext* context);
  50. virtual ~ReportingCache();
  51. // Adds a report to the cache.
  52. //
  53. // |reporting_source| and |network_isolation_key| will be used when the
  54. // report is delivered, to determine which endpoints are eligible to receive
  55. // this report, and which other reports this report can be batched with.
  56. //
  57. // All other parameters correspond to the desired values for the relevant
  58. // fields in ReportingReport.
  59. virtual void AddReport(
  60. const absl::optional<base::UnguessableToken>& reporting_source,
  61. const NetworkIsolationKey& network_isolation_key,
  62. const GURL& url,
  63. const std::string& user_agent,
  64. const std::string& group_name,
  65. const std::string& type,
  66. base::Value::Dict body,
  67. int depth,
  68. base::TimeTicks queued,
  69. int attempts) = 0;
  70. // Gets all reports in the cache. The returned pointers are valid as long as
  71. // either no calls to |RemoveReports| have happened or the reports' |pending|
  72. // flag has been set to true using |SetReportsPending|. Does not return
  73. // doomed reports (pending reports for which removal has been requested).
  74. //
  75. // (Clears any existing data in |*reports_out|.)
  76. virtual void GetReports(
  77. std::vector<const ReportingReport*>* reports_out) const = 0;
  78. // Gets all reports in the cache, including pending and doomed reports, as a
  79. // base::Value.
  80. virtual base::Value GetReportsAsValue() const = 0;
  81. // Gets all reports in the cache that aren't pending or doomed (i.e. that are
  82. // eligible for delivery), and marks returned reports as pending in
  83. // preparation for a delivery attempt. The returned pointers are valid as long
  84. // as the reports are still pending.
  85. virtual std::vector<const ReportingReport*> GetReportsToDeliver() = 0;
  86. // Gets all reports in the cache which are eligible for delivery, which were
  87. // queued for a single `reporting_source`, and marks returned reports as
  88. // pending in preparation for a delivery attempt. The returned pointers are
  89. // valid as long as the reports are still pending. This method is used when a
  90. // reporting source is being destroyed, to trigger delivery of any remaining
  91. // outstanding reports.
  92. virtual std::vector<const ReportingReport*> GetReportsToDeliverForSource(
  93. const base::UnguessableToken& reporting_source) = 0;
  94. // Unmarks a set of reports as pending. |reports| must be previously marked as
  95. // pending.
  96. virtual void ClearReportsPending(
  97. const std::vector<const ReportingReport*>& reports) = 0;
  98. // Increments |attempts| on a set of reports.
  99. virtual void IncrementReportsAttempts(
  100. const std::vector<const ReportingReport*>& reports) = 0;
  101. // Records that we attempted (and possibly succeeded at) delivering
  102. // |reports_delivered| reports to the specified endpoint.
  103. virtual void IncrementEndpointDeliveries(
  104. const ReportingEndpointGroupKey& group_key,
  105. const GURL& url,
  106. int reports_delivered,
  107. bool successful) = 0;
  108. // Marks a `reporting_source` as expired, when the source (document or
  109. // worker) has beed destroyed. The endpoint configuration for the source will
  110. // be removed by the garbage collector once all outstanding reports have been
  111. // delivered or expired.
  112. virtual void SetExpiredSource(
  113. const base::UnguessableToken& reporting_source) = 0;
  114. // Gets the current set of expired reporting sources.
  115. virtual const base::flat_set<base::UnguessableToken>& GetExpiredSources()
  116. const = 0;
  117. // Removes a set of reports. Any reports that are pending will not be removed
  118. // immediately, but rather marked doomed and removed once they are no longer
  119. // pending.
  120. virtual void RemoveReports(
  121. const std::vector<const ReportingReport*>& reports) = 0;
  122. virtual void RemoveReports(const std::vector<const ReportingReport*>& reports,
  123. bool delivery_success) = 0;
  124. // Removes all reports. Like |RemoveReports()|, pending reports are doomed
  125. // until no longer pending.
  126. virtual void RemoveAllReports() = 0;
  127. // Gets the count of reports in the cache, *including* doomed reports.
  128. //
  129. // Needed to ensure that doomed reports are eventually deleted, since no
  130. // method provides a view of *every* report in the cache, just non-doomed
  131. // ones.
  132. virtual size_t GetFullReportCountForTesting() const = 0;
  133. // Gets the count of reports in the cache with a specific `status`.
  134. virtual size_t GetReportCountWithStatusForTesting(
  135. ReportingReport::Status status) const = 0;
  136. virtual bool IsReportPendingForTesting(
  137. const ReportingReport* report) const = 0;
  138. virtual bool IsReportDoomedForTesting(
  139. const ReportingReport* report) const = 0;
  140. // Adds a new client to the cache for |origin|, or updates the existing one
  141. // to match the new header. All values are assumed to be valid as they have
  142. // passed through the ReportingHeaderParser.
  143. virtual void OnParsedHeader(
  144. const NetworkIsolationKey& network_isolation_key,
  145. const url::Origin& origin,
  146. std::vector<ReportingEndpointGroup> parsed_header) = 0;
  147. // Adds named endpoints for |reporting_source| to the cache, based on the
  148. // received Reporting-Endpoints header.
  149. // |reporting_source| is the token identifying the document or worker with
  150. // which this header was received, and may not be empty.
  151. // |isolation_info| is the appropriate network isolation info struct for that
  152. // source, and is used for determining credentials to send with reports.
  153. virtual void OnParsedReportingEndpointsHeader(
  154. const base::UnguessableToken& reporting_source,
  155. const IsolationInfo& isolation_info,
  156. std::vector<ReportingEndpoint> parsed_header) = 0;
  157. // Gets all the origins of clients in the cache.
  158. virtual std::set<url::Origin> GetAllOrigins() const = 0;
  159. // Remove client for the given (NIK, origin) pair, if it exists in the cache.
  160. // All endpoint groups and endpoints for that client are also removed.
  161. virtual void RemoveClient(const NetworkIsolationKey& network_isolation_key,
  162. const url::Origin& origin) = 0;
  163. // Remove all clients for the given |origin|, if any exists in the cache.
  164. // All endpoint groups and endpoints for |origin| are also removed.
  165. virtual void RemoveClientsForOrigin(const url::Origin& origin) = 0;
  166. // Remove all clients, groups, and endpoints from the cache.
  167. virtual void RemoveAllClients() = 0;
  168. // Remove the endpoint group matching |group_key|, and remove
  169. // all endpoints for that group. May cause the client it was associated with
  170. // to be deleted if it becomes empty.
  171. virtual void RemoveEndpointGroup(
  172. const ReportingEndpointGroupKey& group_key) = 0;
  173. // Remove all endpoints for with |url|, regardless of origin or group. Used
  174. // when a delivery returns 410 Gone. May cause deletion of groups/clients if
  175. // they become empty.
  176. virtual void RemoveEndpointsForUrl(const GURL& url) = 0;
  177. // Remove `reporting_source` from the cache, including any configured
  178. // endpoints. There should be no non-doomed reports in the cache for
  179. // `reporting_source` when this is called.
  180. virtual void RemoveSourceAndEndpoints(
  181. const base::UnguessableToken& reporting_source) = 0;
  182. // Insert endpoints and endpoint groups that have been loaded from the store.
  183. //
  184. // You must only call this method if context.store() was non-null when you
  185. // constructed the cache and persist_clients_across_restarts in your
  186. // ReportingPolicy is true.
  187. virtual void AddClientsLoadedFromStore(
  188. std::vector<ReportingEndpoint> loaded_endpoints,
  189. std::vector<CachedReportingEndpointGroup> loaded_endpoint_groups) = 0;
  190. // Gets endpoints that apply to a delivery for |origin| and |group|.
  191. //
  192. // First checks for |group| in a client exactly matching |origin|.
  193. // If none exists, then checks for |group| in clients for superdomains
  194. // of |origin| which have include_subdomains enabled, returning only the
  195. // endpoints for the most specific applicable parent origin of |origin|. If
  196. // there are multiple origins with that group within the most specific
  197. // applicable superdomain, gets endpoints for that group from only one of
  198. // them. The group must not be expired.
  199. //
  200. // For example, given the origin https://foo.bar.baz.com/, the cache
  201. // would prioritize returning each potential match below over the ones below
  202. // it, for groups with name |group| with include_subdomains enabled:
  203. // 1. https://foo.bar.baz.com/ (exact origin match)
  204. // 2. https://foo.bar.baz.com:444/ (technically, a superdomain)
  205. // 3. https://bar.baz.com/, https://bar.baz.com:444/, etc. (superdomain)
  206. // 4. https://baz.com/, https://baz.com:444/, etc. (superdomain)
  207. // If both https://bar.baz.com/ and https://bar.baz.com:444/ had a group with
  208. // name |group| with include_subdomains enabled, this method would return
  209. // endpoints from that group from the earliest-inserted origin.
  210. virtual std::vector<ReportingEndpoint> GetCandidateEndpointsForDelivery(
  211. const ReportingEndpointGroupKey& group_key) = 0;
  212. // Gets the status of all clients in the cache, including expired ones, as a
  213. // base::Value.
  214. virtual base::Value GetClientsAsValue() const = 0;
  215. // Gets the total number of endpoints in the cache across all origins.
  216. virtual size_t GetEndpointCount() const = 0;
  217. // Flush the contents of the cache to disk, if applicable.
  218. virtual void Flush() = 0;
  219. // Returns all V1 endpoints keyed by origin.
  220. virtual base::flat_map<url::Origin, std::vector<ReportingEndpoint>>
  221. GetV1ReportingEndpointsByOrigin() const = 0;
  222. // Returns the endpoint named |endpoint_name| for the reporting source, if it
  223. // was configured with the Reporting-Endpoints header, otherwise returns an
  224. // invalid ReportingEndpoint.
  225. // |reporting_source| must not be empty.
  226. virtual ReportingEndpoint GetV1EndpointForTesting(
  227. const base::UnguessableToken& reporting_source,
  228. const std::string& endpoint_name) const = 0;
  229. // Finds an endpoint for the given |group_key| and |url|, otherwise returns an
  230. // invalid ReportingEndpoint.
  231. virtual ReportingEndpoint GetEndpointForTesting(
  232. const ReportingEndpointGroupKey& group_key,
  233. const GURL& url) const = 0;
  234. // Returns whether an endpoint group with exactly the given properties exists
  235. // in the cache. If |expires| is base::Time(), it will not be checked.
  236. virtual bool EndpointGroupExistsForTesting(
  237. const ReportingEndpointGroupKey& group_key,
  238. OriginSubdomains include_subdomains,
  239. base::Time expires) const = 0;
  240. // Returns whether a client for the given (NIK, Origin) exists.
  241. virtual bool ClientExistsForTesting(
  242. const NetworkIsolationKey& network_isolation_key,
  243. const url::Origin& origin) const = 0;
  244. // Returns number of endpoint groups.
  245. virtual size_t GetEndpointGroupCountForTesting() const = 0;
  246. // Returns number of endpoint groups.
  247. virtual size_t GetClientCountForTesting() const = 0;
  248. // Returns number of reporting source tokens associated with endpoints.
  249. virtual size_t GetReportingSourceCountForTesting() const = 0;
  250. // Sets an endpoint with the given properties in a group with the given
  251. // properties, bypassing header parsing. Note that the endpoint is not
  252. // guaranteed to exist in the cache after calling this function, if endpoint
  253. // eviction is triggered. Unlike the AddOrUpdate*() methods used in header
  254. // parsing, this method inserts or updates a single endpoint while leaving the
  255. // existing configuration for that origin intact.
  256. virtual void SetEndpointForTesting(const ReportingEndpointGroupKey& group_key,
  257. const GURL& url,
  258. OriginSubdomains include_subdomains,
  259. base::Time expires,
  260. int priority,
  261. int weight) = 0;
  262. // Sets a V1 named endpoint with the given key for `reporting_source`,
  263. // bypassing header parsing. This method inserts a single endpoint while
  264. // leaving the existing configuration for that source intact. If any
  265. // endpoints already exist for this source, then `isolation_info` must
  266. // match the value that was previously associated with it.
  267. virtual void SetV1EndpointForTesting(
  268. const ReportingEndpointGroupKey& group_key,
  269. const base::UnguessableToken& reporting_source,
  270. const IsolationInfo& isolation_info,
  271. const GURL& url) = 0;
  272. // Gets the isolation info associated with `reporting_source`, used when
  273. // determining which credentials to send for a given report. If
  274. // `reporting_source` is nullopt, as when a report is being delivered to a V0
  275. // reporting endpoint group, this always will return an empty site.
  276. virtual IsolationInfo GetIsolationInfoForEndpoint(
  277. const ReportingEndpoint& endpoint) const = 0;
  278. };
  279. // Persistent storage for Reporting reports and clients.
  280. class NET_EXPORT ReportingCache::PersistentReportingStore {
  281. public:
  282. using ReportingClientsLoadedCallback =
  283. base::OnceCallback<void(std::vector<ReportingEndpoint>,
  284. std::vector<CachedReportingEndpointGroup>)>;
  285. PersistentReportingStore() = default;
  286. PersistentReportingStore(const PersistentReportingStore&) = delete;
  287. PersistentReportingStore& operator=(const PersistentReportingStore&) = delete;
  288. virtual ~PersistentReportingStore() = default;
  289. // Initializes the store and retrieves stored endpoints and endpoint groups.
  290. // Called only once at startup.
  291. virtual void LoadReportingClients(
  292. ReportingClientsLoadedCallback loaded_callback) = 0;
  293. // Adds an endpoint to the store.
  294. virtual void AddReportingEndpoint(const ReportingEndpoint& endpoint) = 0;
  295. // Adds an endpoint group to the store.
  296. virtual void AddReportingEndpointGroup(
  297. const CachedReportingEndpointGroup& group) = 0;
  298. // Updates the access time of an endpoint group in the store.
  299. virtual void UpdateReportingEndpointGroupAccessTime(
  300. const CachedReportingEndpointGroup& group) = 0;
  301. // Updates the details of an endpoint in the store.
  302. virtual void UpdateReportingEndpointDetails(
  303. const ReportingEndpoint& endpoint) = 0;
  304. // Updates the details of an endpoint group in the store.
  305. virtual void UpdateReportingEndpointGroupDetails(
  306. const CachedReportingEndpointGroup& group) = 0;
  307. // Deletes an endpoint from the store.
  308. virtual void DeleteReportingEndpoint(const ReportingEndpoint& endpoint) = 0;
  309. // Deletes an endpoint group from the store.
  310. virtual void DeleteReportingEndpointGroup(
  311. const CachedReportingEndpointGroup& group) = 0;
  312. // TODO(chlily): methods to load, add, and delete reports will be added.
  313. // Flushes the store.
  314. virtual void Flush() = 0;
  315. };
  316. } // namespace net
  317. #endif // NET_REPORTING_REPORTING_CACHE_H_