#ifndef NET_REPORTING_REPORTING_CACHE_IMPL_H_
#define NET_REPORTING_REPORTING_CACHE_IMPL_H_
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/containers/unique_ptr_adapters.h"
#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "base/values.h"
#include "net/base/isolation_info.h"
#include "net/base/network_anonymization_key.h"
#include "net/reporting/reporting_cache.h"
#include "net/reporting/reporting_context.h"
#include "net/reporting/reporting_endpoint.h"
#include "net/reporting/reporting_header_parser.h"
#include "net/reporting/reporting_report.h"
#include "net/reporting/reporting_target_type.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace net {
class ReportingCacheImpl : public ReportingCache {
public:
explicit ReportingCacheImpl(
ReportingContext* context,
const base::flat_map<std::string, GURL>& enterprise_reporting_endpoints);
ReportingCacheImpl(const ReportingCacheImpl&) = delete;
ReportingCacheImpl& operator=(const ReportingCacheImpl&) = delete;
~ReportingCacheImpl() override;
void AddReport(const std::optional<base::UnguessableToken>& reporting_source,
const NetworkAnonymizationKey& network_anonymization_key,
const GURL& url,
const std::string& user_agent,
const std::string& group_name,
const std::string& type,
base::Value::Dict body,
int depth,
base::TimeTicks queued,
ReportingTargetType target_type) override;
void GetReports(
std::vector<raw_ptr<const ReportingReport, VectorExperimental>>*
reports_out) const override;
base::Value GetReportsAsValue() const override;
std::vector<raw_ptr<const ReportingReport, VectorExperimental>>
GetReportsToDeliver() override;
std::vector<raw_ptr<const ReportingReport, VectorExperimental>>
GetReportsToDeliverForSource(
const base::UnguessableToken& reporting_source) override;
void ClearReportsPending(
const std::vector<raw_ptr<const ReportingReport, VectorExperimental>>&
reports) override;
void IncrementReportsAttempts(
const std::vector<raw_ptr<const ReportingReport, VectorExperimental>>&
reports) override;
base::flat_map<url::Origin, std::vector<ReportingEndpoint>>
GetV1ReportingEndpointsByOrigin() const override;
void IncrementEndpointDeliveries(const ReportingEndpointGroupKey& group_key,
const GURL& url,
int reports_delivered,
bool successful) override;
void SetExpiredSource(
const base::UnguessableToken& reporting_source) override;
const base::flat_set<base::UnguessableToken>& GetExpiredSources()
const override;
void RemoveReports(
const std::vector<raw_ptr<const ReportingReport, VectorExperimental>>&
reports) override;
void RemoveReports(
const std::vector<raw_ptr<const ReportingReport, VectorExperimental>>&
reports,
bool delivery_success) override;
void RemoveAllReports() override;
size_t GetFullReportCountForTesting() const override;
size_t GetReportCountWithStatusForTesting(
ReportingReport::Status status) const override;
bool IsReportPendingForTesting(const ReportingReport* report) const override;
bool IsReportDoomedForTesting(const ReportingReport* report) const override;
void OnParsedHeader(
const NetworkAnonymizationKey& network_anonymization_key,
const url::Origin& origin,
std::vector<ReportingEndpointGroup> parsed_header) override;
void OnParsedReportingEndpointsHeader(
const base::UnguessableToken& reporting_source,
const IsolationInfo& isolation_info,
std::vector<ReportingEndpoint> parsed_header) override;
void SetEnterpriseReportingEndpoints(
const base::flat_map<std::string, GURL>& endpoints) override;
std::set<url::Origin> GetAllOrigins() const override;
void RemoveClient(const NetworkAnonymizationKey& network_anonymization_key,
const url::Origin& origin) override;
void RemoveClientsForOrigin(const url::Origin& origin) override;
void RemoveAllClients() override;
void RemoveEndpointGroup(const ReportingEndpointGroupKey& group_key) override;
void RemoveEndpointsForUrl(const GURL& url) override;
void RemoveSourceAndEndpoints(
const base::UnguessableToken& reporting_source) override;
void AddClientsLoadedFromStore(
std::vector<ReportingEndpoint> loaded_endpoints,
std::vector<CachedReportingEndpointGroup> loaded_endpoint_groups)
override;
std::vector<ReportingEndpoint> GetCandidateEndpointsForDelivery(
const ReportingEndpointGroupKey& group_key) override;
base::Value GetClientsAsValue() const override;
size_t GetEndpointCount() const override;
void Flush() override;
ReportingEndpoint GetV1EndpointForTesting(
const base::UnguessableToken& reporting_source,
const std::string& endpoint_name) const override;
ReportingEndpoint GetEndpointForTesting(
const ReportingEndpointGroupKey& group_key,
const GURL& url) const override;
std::vector<ReportingEndpoint> GetEnterpriseEndpointsForTesting()
const override;
bool EndpointGroupExistsForTesting(const ReportingEndpointGroupKey& group_key,
OriginSubdomains include_subdomains,
base::Time expires) const override;
bool ClientExistsForTesting(
const NetworkAnonymizationKey& network_anonymization_key,
const url::Origin& origin) const override;
size_t GetEndpointGroupCountForTesting() const override;
size_t GetClientCountForTesting() const override;
size_t GetReportingSourceCountForTesting() const override;
void SetEndpointForTesting(const ReportingEndpointGroupKey& group_key,
const GURL& url,
OriginSubdomains include_subdomains,
base::Time expires,
int priority,
int weight) override;
void SetV1EndpointForTesting(const ReportingEndpointGroupKey& group_key,
const base::UnguessableToken& reporting_source,
const IsolationInfo& isolation_info,
const GURL& url) override;
void SetEnterpriseEndpointForTesting(
const ReportingEndpointGroupKey& group_key,
const GURL& url) override;
IsolationInfo GetIsolationInfoForEndpoint(
const ReportingEndpoint& endpoint) const override;
private:
struct Client {
Client(const NetworkAnonymizationKey& network_anonymization_key,
const url::Origin& origin);
Client(const Client& other);
Client(Client&& other);
Client& operator=(const Client& other);
Client& operator=(Client&& other);
~Client();
NetworkAnonymizationKey network_anonymization_key;
url::Origin origin;
size_t endpoint_count = 0;
base::Time last_used;
std::set<std::string> endpoint_group_names;
};
using ReportSet = base::flat_set<std::unique_ptr<ReportingReport>,
base::UniquePtrComparator>;
using ClientMap = std::multimap<std::string, Client>;
using EndpointGroupMap =
std::map<ReportingEndpointGroupKey, CachedReportingEndpointGroup>;
using EndpointMap =
std::multimap<ReportingEndpointGroupKey, ReportingEndpoint>;
ReportSet::const_iterator FindReportToEvict() const;
void ConsistencyCheckClients() const;
#if DCHECK_IS_ON()
size_t ConsistencyCheckClient(const std::string& domain,
const Client& client) const;
size_t ConsistencyCheckEndpointGroup(
const ReportingEndpointGroupKey& key,
const CachedReportingEndpointGroup& group) const;
void ConsistencyCheckEndpoint(const ReportingEndpointGroupKey& key,
const ReportingEndpoint& endpoint,
EndpointMap::const_iterator endpoint_it) const;
#endif
ClientMap::iterator FindClientIt(
const NetworkAnonymizationKey& network_anonymization_key,
const url::Origin& origin);
ClientMap::iterator FindClientIt(const ReportingEndpointGroupKey& group_key);
EndpointGroupMap::iterator FindEndpointGroupIt(
const ReportingEndpointGroupKey& group_key);
EndpointMap::iterator FindEndpointIt(
const ReportingEndpointGroupKey& group_key,
const GURL& url);
ClientMap::iterator AddOrUpdateClient(Client new_client);
void AddOrUpdateEndpointGroup(CachedReportingEndpointGroup new_group);
void AddOrUpdateEndpoint(ReportingEndpoint new_endpoint);
void RemoveEndpointsInGroupOtherThan(
const ReportingEndpointGroupKey& group_key,
const std::set<GURL>& endpoints_to_keep_urls);
void RemoveEndpointGroupsForClientOtherThan(
const NetworkAnonymizationKey& network_anonymization_key,
const url::Origin& origin,
const std::set<std::string>& groups_to_keep_names);
std::vector<ReportingEndpoint> GetEndpointsInGroup(
const ReportingEndpointGroupKey& group_key) const;
size_t GetEndpointCountInGroup(
const ReportingEndpointGroupKey& group_key) const;
void MarkEndpointGroupAndClientUsed(ClientMap::iterator client_it,
EndpointGroupMap::iterator group_it,
base::Time now);
std::optional<EndpointMap::iterator> RemoveEndpointInternal(
ClientMap::iterator client_it,
EndpointGroupMap::iterator group_it,
EndpointMap::iterator endpoint_it);
std::optional<EndpointGroupMap::iterator> RemoveEndpointGroupInternal(
ClientMap::iterator client_it,
EndpointGroupMap::iterator group_it,
size_t* num_endpoints_removed = nullptr);
ClientMap::iterator RemoveClientInternal(ClientMap::iterator client_it);
void EnforcePerClientAndGlobalEndpointLimits(ClientMap::iterator client_it);
void EvictEndpointsFromClient(ClientMap::iterator client_it,
size_t endpoints_to_evict);
void EvictEndpointFromGroup(ClientMap::iterator client_it,
EndpointGroupMap::iterator group_it);
bool RemoveExpiredOrStaleGroups(ClientMap::iterator client_it,
size_t* num_endpoints_removed);
void AddEndpointItToIndex(EndpointMap::iterator endpoint_it);
void RemoveEndpointItFromIndex(EndpointMap::iterator endpoint_it);
ReportingEndpoint::Statistics* GetEndpointStats(
const ReportingEndpointGroupKey& group_key,
const GURL& url);
base::Value GetClientAsValue(const Client& client) const;
base::Value GetEndpointGroupAsValue(
const CachedReportingEndpointGroup& group) const;
base::Value GetEndpointAsValue(const ReportingEndpoint& endpoint) const;
const base::Clock& clock() const { return context_->clock(); }
const base::TickClock& tick_clock() const { return context_->tick_clock(); }
PersistentReportingStore* store() { return context_->store(); }
raw_ptr<ReportingContext> context_;
ReportSet reports_;
ClientMap clients_;
EndpointGroupMap endpoint_groups_;
EndpointMap endpoints_;
std::multimap<GURL, EndpointMap::iterator> endpoint_its_by_url_;
std::map<base::UnguessableToken, std::vector<ReportingEndpoint>>
document_endpoints_;
std::vector<ReportingEndpoint> enterprise_endpoints_;
std::map<base::UnguessableToken, IsolationInfo> isolation_info_;
base::flat_set<base::UnguessableToken> expired_sources_;
SEQUENCE_CHECKER(sequence_checker_);
};
}
#endif