reporting_cache_impl.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. // Copyright 2019 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_IMPL_H_
  5. #define NET_REPORTING_REPORTING_CACHE_IMPL_H_
  6. #include <map>
  7. #include <memory>
  8. #include <set>
  9. #include <string>
  10. #include <unordered_set>
  11. #include <utility>
  12. #include <vector>
  13. #include "base/containers/flat_map.h"
  14. #include "base/containers/flat_set.h"
  15. #include "base/containers/unique_ptr_adapters.h"
  16. #include "base/memory/raw_ptr.h"
  17. #include "base/sequence_checker.h"
  18. #include "base/time/time.h"
  19. #include "base/unguessable_token.h"
  20. #include "base/values.h"
  21. #include "net/base/isolation_info.h"
  22. #include "net/reporting/reporting_cache.h"
  23. #include "net/reporting/reporting_context.h"
  24. #include "net/reporting/reporting_endpoint.h"
  25. #include "net/reporting/reporting_header_parser.h"
  26. #include "net/reporting/reporting_report.h"
  27. #include "third_party/abseil-cpp/absl/types/optional.h"
  28. #include "url/gurl.h"
  29. #include "url/origin.h"
  30. namespace net {
  31. class ReportingCacheImpl : public ReportingCache {
  32. public:
  33. explicit ReportingCacheImpl(ReportingContext* context);
  34. ReportingCacheImpl(const ReportingCacheImpl&) = delete;
  35. ReportingCacheImpl& operator=(const ReportingCacheImpl&) = delete;
  36. ~ReportingCacheImpl() override;
  37. // ReportingCache implementation
  38. void AddReport(const absl::optional<base::UnguessableToken>& reporting_source,
  39. const NetworkIsolationKey& network_isolation_key,
  40. const GURL& url,
  41. const std::string& user_agent,
  42. const std::string& group_name,
  43. const std::string& type,
  44. base::Value::Dict body,
  45. int depth,
  46. base::TimeTicks queued,
  47. int attempts) override;
  48. void GetReports(
  49. std::vector<const ReportingReport*>* reports_out) const override;
  50. base::Value GetReportsAsValue() const override;
  51. std::vector<const ReportingReport*> GetReportsToDeliver() override;
  52. std::vector<const ReportingReport*> GetReportsToDeliverForSource(
  53. const base::UnguessableToken& reporting_source) override;
  54. void ClearReportsPending(
  55. const std::vector<const ReportingReport*>& reports) override;
  56. void IncrementReportsAttempts(
  57. const std::vector<const ReportingReport*>& reports) override;
  58. base::flat_map<url::Origin, std::vector<ReportingEndpoint>>
  59. GetV1ReportingEndpointsByOrigin() const override;
  60. void IncrementEndpointDeliveries(const ReportingEndpointGroupKey& group_key,
  61. const GURL& url,
  62. int reports_delivered,
  63. bool successful) override;
  64. void SetExpiredSource(
  65. const base::UnguessableToken& reporting_source) override;
  66. const base::flat_set<base::UnguessableToken>& GetExpiredSources()
  67. const override;
  68. void RemoveReports(
  69. const std::vector<const ReportingReport*>& reports) override;
  70. void RemoveReports(const std::vector<const ReportingReport*>& reports,
  71. bool delivery_success) override;
  72. void RemoveAllReports() override;
  73. size_t GetFullReportCountForTesting() const override;
  74. size_t GetReportCountWithStatusForTesting(
  75. ReportingReport::Status status) const override;
  76. bool IsReportPendingForTesting(const ReportingReport* report) const override;
  77. bool IsReportDoomedForTesting(const ReportingReport* report) const override;
  78. void OnParsedHeader(
  79. const NetworkIsolationKey& network_isolation_key,
  80. const url::Origin& origin,
  81. std::vector<ReportingEndpointGroup> parsed_header) override;
  82. void OnParsedReportingEndpointsHeader(
  83. const base::UnguessableToken& reporting_source,
  84. const IsolationInfo& isolation_info,
  85. std::vector<ReportingEndpoint> parsed_header) override;
  86. std::set<url::Origin> GetAllOrigins() const override;
  87. void RemoveClient(const NetworkIsolationKey& network_isolation_key,
  88. const url::Origin& origin) override;
  89. void RemoveClientsForOrigin(const url::Origin& origin) override;
  90. void RemoveAllClients() override;
  91. void RemoveEndpointGroup(const ReportingEndpointGroupKey& group_key) override;
  92. void RemoveEndpointsForUrl(const GURL& url) override;
  93. void RemoveSourceAndEndpoints(
  94. const base::UnguessableToken& reporting_source) override;
  95. void AddClientsLoadedFromStore(
  96. std::vector<ReportingEndpoint> loaded_endpoints,
  97. std::vector<CachedReportingEndpointGroup> loaded_endpoint_groups)
  98. override;
  99. std::vector<ReportingEndpoint> GetCandidateEndpointsForDelivery(
  100. const ReportingEndpointGroupKey& group_key) override;
  101. base::Value GetClientsAsValue() const override;
  102. size_t GetEndpointCount() const override;
  103. void Flush() override;
  104. ReportingEndpoint GetV1EndpointForTesting(
  105. const base::UnguessableToken& reporting_source,
  106. const std::string& endpoint_name) const override;
  107. ReportingEndpoint GetEndpointForTesting(
  108. const ReportingEndpointGroupKey& group_key,
  109. const GURL& url) const override;
  110. bool EndpointGroupExistsForTesting(const ReportingEndpointGroupKey& group_key,
  111. OriginSubdomains include_subdomains,
  112. base::Time expires) const override;
  113. bool ClientExistsForTesting(const NetworkIsolationKey& network_isolation_key,
  114. const url::Origin& origin) const override;
  115. size_t GetEndpointGroupCountForTesting() const override;
  116. size_t GetClientCountForTesting() const override;
  117. size_t GetReportingSourceCountForTesting() const override;
  118. void SetEndpointForTesting(const ReportingEndpointGroupKey& group_key,
  119. const GURL& url,
  120. OriginSubdomains include_subdomains,
  121. base::Time expires,
  122. int priority,
  123. int weight) override;
  124. void SetV1EndpointForTesting(const ReportingEndpointGroupKey& group_key,
  125. const base::UnguessableToken& reporting_source,
  126. const IsolationInfo& isolation_info,
  127. const GURL& url) override;
  128. IsolationInfo GetIsolationInfoForEndpoint(
  129. const ReportingEndpoint& endpoint) const override;
  130. private:
  131. // Represents the entire Report-To configuration for a (NIK, origin) pair.
  132. struct Client {
  133. Client(const NetworkIsolationKey& network_isolation_key,
  134. const url::Origin& origin);
  135. Client(const Client& other);
  136. Client(Client&& other);
  137. Client& operator=(const Client& other);
  138. Client& operator=(Client&& other);
  139. ~Client();
  140. // NIK of the context associated with this client. Needed to prevent leaking
  141. // third party contexts across sites.
  142. NetworkIsolationKey network_isolation_key;
  143. // Origin that configured this client.
  144. url::Origin origin;
  145. // Total number of endpoints for this origin. Should stay in sync with the
  146. // sum of endpoint counts for all the groups within this client.
  147. size_t endpoint_count = 0;
  148. // Last time that any of the groups for this origin was accessed for a
  149. // delivery or updated via a new header. Should stay in sync with the latest
  150. // |last_used| of all the groups within this client.
  151. base::Time last_used;
  152. // Set of endpoint group names for this origin.
  153. std::set<std::string> endpoint_group_names;
  154. };
  155. using ReportSet = base::flat_set<std::unique_ptr<ReportingReport>,
  156. base::UniquePtrComparator>;
  157. using ClientMap = std::multimap<std::string, Client>;
  158. using EndpointGroupMap =
  159. std::map<ReportingEndpointGroupKey, CachedReportingEndpointGroup>;
  160. using EndpointMap =
  161. std::multimap<ReportingEndpointGroupKey, ReportingEndpoint>;
  162. ReportSet::const_iterator FindReportToEvict() const;
  163. // Consistency-checks the entire data structure of clients, groups, and
  164. // endpoints, if DCHECK is on. The cached clients should pass this consistency
  165. // check after completely parsing a header (i.e. not after the intermediate
  166. // steps), and before and after any of the public methods that remove or
  167. // retrieve client info. Also calls |sequence_checker_| to DCHECK that we are
  168. // being called on a valid sequence.
  169. void ConsistencyCheckClients() const;
  170. // Helper methods for ConsistencyCheckClients():
  171. #if DCHECK_IS_ON()
  172. // Returns number of endpoint groups found in |client|.
  173. size_t ConsistencyCheckClient(const std::string& domain,
  174. const Client& client) const;
  175. // Returns the number of endpoints found in |group|.
  176. size_t ConsistencyCheckEndpointGroup(
  177. const ReportingEndpointGroupKey& key,
  178. const CachedReportingEndpointGroup& group) const;
  179. void ConsistencyCheckEndpoint(const ReportingEndpointGroupKey& key,
  180. const ReportingEndpoint& endpoint,
  181. EndpointMap::const_iterator endpoint_it) const;
  182. #endif // DCHECK_IS_ON()
  183. // Finds iterator to the client with the given |network_isolation_key| and
  184. // |origin|, if one exists. Returns |clients_.end()| if none is found.
  185. ClientMap::iterator FindClientIt(
  186. const NetworkIsolationKey& network_isolation_key,
  187. const url::Origin& origin);
  188. // Overload that takes a ReportingEndpointGroupKey and finds the client
  189. // to which a group specified by the |group_key| would belong. The group name
  190. // of the key is ignored.
  191. ClientMap::iterator FindClientIt(const ReportingEndpointGroupKey& group_key);
  192. // Finds iterator to the endpoint group identified by |group_key| (origin and
  193. // name), if one exists. Returns |endpoint_groups_.end()| if none is found.
  194. EndpointGroupMap::iterator FindEndpointGroupIt(
  195. const ReportingEndpointGroupKey& group_key);
  196. // Finds iterator to the endpoint for the given |group_key| (origin and group
  197. // name) and |url|, if one exists. Returns |endpoints_.end()| if none is
  198. // found.
  199. EndpointMap::iterator FindEndpointIt(
  200. const ReportingEndpointGroupKey& group_key,
  201. const GURL& url);
  202. // Adds a new client, endpoint group, or endpoint to the cache, if none
  203. // exists. If one already exists, updates the existing entry to match the new
  204. // one. Returns iterator to newly added client.
  205. ClientMap::iterator AddOrUpdateClient(Client new_client);
  206. void AddOrUpdateEndpointGroup(CachedReportingEndpointGroup new_group);
  207. void AddOrUpdateEndpoint(ReportingEndpoint new_endpoint);
  208. // Remove all the endpoints configured for |origin| and |group| whose urls are
  209. // not in |endpoints_to_keep_urls|. Does not guarantee that all the endpoints
  210. // in |endpoints_to_keep_urls| exist in the cache for that group.
  211. void RemoveEndpointsInGroupOtherThan(
  212. const ReportingEndpointGroupKey& group_key,
  213. const std::set<GURL>& endpoints_to_keep_urls);
  214. // Remove all the endpoint groups for the NIK and origin whose names are not
  215. // in |groups_to_keep_names|. Does not guarantee that all the groups in
  216. // |groups_to_keep_names| exist in the cache for that client.
  217. void RemoveEndpointGroupsForClientOtherThan(
  218. const NetworkIsolationKey& network_isolation_key,
  219. const url::Origin& origin,
  220. const std::set<std::string>& groups_to_keep_names);
  221. // Gets the endpoints in the given group.
  222. std::vector<ReportingEndpoint> GetEndpointsInGroup(
  223. const ReportingEndpointGroupKey& group_key) const;
  224. // Gets the number of endpoints for the given origin and group.
  225. size_t GetEndpointCountInGroup(
  226. const ReportingEndpointGroupKey& group_key) const;
  227. // Updates the last_used time for the given origin and endpoint group.
  228. void MarkEndpointGroupAndClientUsed(ClientMap::iterator client_it,
  229. EndpointGroupMap::iterator group_it,
  230. base::Time now);
  231. // Removes the endpoint at the given iterator, which must exist in the cache.
  232. // Also takes iterators to the client and endpoint group to avoid repeated
  233. // lookups. May cause the client and/or group to be removed if they become
  234. // empty, which would invalidate those iterators.
  235. // Returns the iterator following the endpoint removed, or absl::nullopt if
  236. // either of |group_it| or |client_it| were invalidated. (If |client_it| is
  237. // invalidated, then so must |group_it|).
  238. absl::optional<EndpointMap::iterator> RemoveEndpointInternal(
  239. ClientMap::iterator client_it,
  240. EndpointGroupMap::iterator group_it,
  241. EndpointMap::iterator endpoint_it);
  242. // Removes the endpoint group at the given iterator (which must exist in the
  243. // cache). Also takes iterator to the client to avoid repeated lookups. May
  244. // cause the client to be removed if it becomes empty, which would
  245. // invalidate |client_it|. If |num_endpoints_removed| is not null, then
  246. // |*num_endpoints_removed| is incremented by the number of endpoints
  247. // removed.
  248. // Returns the iterator following the endpoint group removed, or absl::nullopt
  249. // if |client_it| was invalidated.
  250. absl::optional<EndpointGroupMap::iterator> RemoveEndpointGroupInternal(
  251. ClientMap::iterator client_it,
  252. EndpointGroupMap::iterator group_it,
  253. size_t* num_endpoints_removed = nullptr);
  254. // Removes the client at the given iterator (which must exist in the cache),
  255. // along with all of its endpoint groups and endpoints. Invalidates
  256. // |client_it|.
  257. // Returns the iterator following the client removed.
  258. ClientMap::iterator RemoveClientInternal(ClientMap::iterator client_it);
  259. // Evict endpoints from the specified client and globally, if necessary to
  260. // obey the per-client and global endpoint limits set in the ReportingPolicy.
  261. //
  262. // To evict from a client: First evicts any stale or expired groups for that
  263. // origin. If that removes enough endpoints, then stop. Otherwise, find the
  264. // stalest group (which has not been accessed for a delivery in the longest
  265. // time) with the most endpoints, and evict the least important endpoints from
  266. // that group.
  267. // To evict globally: Find the stalest client with the most endpoints and do
  268. // the above.
  269. void EnforcePerClientAndGlobalEndpointLimits(ClientMap::iterator client_it);
  270. // Evicts endpoints from a client until it has evicted |endpoints_to_evict|
  271. // endpoints. First tries to remove expired and stale groups. If that fails to
  272. // satisfy the limit, finds the stalest group with the most endpoints and
  273. // evicts the least important endpoints from it.
  274. void EvictEndpointsFromClient(ClientMap::iterator client_it,
  275. size_t endpoints_to_evict);
  276. // Evicts the least important endpoint from a group (the endpoint with lowest
  277. // priority and lowest weight). May cause the group and/or client to be
  278. // deleted and the iterators invalidated.
  279. void EvictEndpointFromGroup(ClientMap::iterator client_it,
  280. EndpointGroupMap::iterator group_it);
  281. // Removes all expired or stale groups from the given client. May delete the
  282. // client and invalidate |client_it| if it becomes empty.
  283. // Increments |*num_endpoints_removed| by the number of endpoints removed.
  284. // Returns true if |client_it| was invalidated.
  285. bool RemoveExpiredOrStaleGroups(ClientMap::iterator client_it,
  286. size_t* num_endpoints_removed);
  287. // Adds/removes (if it exists) |endpoint_it| from |endpoint_its_by_url_|.
  288. void AddEndpointItToIndex(EndpointMap::iterator endpoint_it);
  289. void RemoveEndpointItFromIndex(EndpointMap::iterator endpoint_it);
  290. // Helper method for IncrementEndpointDeliveries
  291. ReportingEndpoint::Statistics* GetEndpointStats(
  292. const ReportingEndpointGroupKey& group_key,
  293. const GURL& url);
  294. // Helper methods for GetClientsAsValue().
  295. base::Value GetClientAsValue(const Client& client) const;
  296. base::Value GetEndpointGroupAsValue(
  297. const CachedReportingEndpointGroup& group) const;
  298. base::Value GetEndpointAsValue(const ReportingEndpoint& endpoint) const;
  299. // Convenience methods for fetching things from the context_.
  300. const base::Clock& clock() const { return context_->clock(); }
  301. const base::TickClock& tick_clock() const { return context_->tick_clock(); }
  302. PersistentReportingStore* store() { return context_->store(); }
  303. raw_ptr<ReportingContext> context_;
  304. // Reports that have not yet been successfully uploaded.
  305. ReportSet reports_;
  306. // Reporting API V0 Cache:
  307. // The |clients_|, |endpoint_groups_| and |endpoints_| members all hold
  308. // endpoint group configuration for the V0 API. These endpoint groups are
  309. // configured through the Report-To HTTP header, and are currently used for
  310. // both document and network reports.
  311. // Map of clients for all configured origins and NIKs, keyed on domain name
  312. // (there may be multiple NIKs and origins per domain name).
  313. ClientMap clients_;
  314. // Map of endpoint groups, keyed on origin and group name. Keys and values
  315. // must only contain V0 endpoint group keys.
  316. EndpointGroupMap endpoint_groups_;
  317. // Map of endpoints, keyed on origin and group name (there may be multiple
  318. // endpoints for a given origin and group, with different urls). Keys must
  319. // only contain V0 endpoint group keys.
  320. EndpointMap endpoints_;
  321. // Index of endpoints stored in |endpoints_| keyed on URL, for easier lookup
  322. // during RemoveEndpointsForUrl(). Should stay in sync with |endpoints_|.
  323. std::multimap<GURL, EndpointMap::iterator> endpoint_its_by_url_;
  324. // Reporting API V1 Cache:
  325. // The `document_endpoints_` member holds endpoint configuration for the V1
  326. // API, configured through the Reporting-Endpoints HTTP header. These
  327. // endpoints are strongly associated with the resource which configured them,
  328. // and are only used for document reports.
  329. // Map of endpoints for each reporting source, keyed on the reporting source
  330. // token. This contains only V1 document endpoints.
  331. std::map<base::UnguessableToken, std::vector<ReportingEndpoint>>
  332. document_endpoints_;
  333. // Isolation info for each reporting source. Used for determining credentials
  334. // to send when delivering reports. This contains only V1 document endpoints.
  335. std::map<base::UnguessableToken, IsolationInfo> isolation_info_;
  336. // Reporting source tokens representing sources which have been destroyed.
  337. // The configuration in `document_endpoints_` and `isolation_info_` for these
  338. // sources can be removed once all outstanding reports are delivered (or
  339. // expired).
  340. base::flat_set<base::UnguessableToken> expired_sources_;
  341. SEQUENCE_CHECKER(sequence_checker_);
  342. };
  343. } // namespace net
  344. #endif // NET_REPORTING_REPORTING_CACHE_IMPL_H_