// Copyright 2017 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef NET_NETWORK_ERROR_LOGGING_NETWORK_ERROR_LOGGING_SERVICE_H_ #define NET_NETWORK_ERROR_LOGGING_NETWORK_ERROR_LOGGING_SERVICE_H_ #include #include #include #include #include #include "base/feature_list.h" #include "base/memory/raw_ptr.h" #include "base/time/clock.h" #include "base/time/time.h" #include "net/base/ip_address.h" #include "net/base/net_errors.h" #include "net/base/net_export.h" #include "net/base/network_isolation_key.h" #include "url/gurl.h" #include "url/origin.h" namespace base { class Value; } // namespace base namespace net { class ReportingService; } // namespace net namespace url { class Origin; } // namespace url namespace features { extern const base::Feature NET_EXPORT kNetworkErrorLogging; } // namespace features namespace net { class NET_EXPORT NetworkErrorLoggingService { public: class PersistentNelStore; // Every (NIK, origin) pair can have at most one policy. struct NET_EXPORT NelPolicyKey { NelPolicyKey(); NelPolicyKey(const NetworkIsolationKey& network_isolation_key, const url::Origin& origin); NelPolicyKey(const NelPolicyKey& other); ~NelPolicyKey(); bool operator<(const NelPolicyKey& other) const; bool operator==(const NelPolicyKey& other) const; bool operator!=(const NelPolicyKey& other) const; // The NIK of the request this policy was received from. This will be used // for any requests uploading reports according to this policy. (Not // included in the report itself.) NetworkIsolationKey network_isolation_key; url::Origin origin; }; // Used for wildcard policies that are applicable to |domain| and its // subdomains. struct WildcardNelPolicyKey { WildcardNelPolicyKey(); WildcardNelPolicyKey(const NetworkIsolationKey& network_isolation_key, const std::string& domain); explicit WildcardNelPolicyKey(const NelPolicyKey& origin_key); WildcardNelPolicyKey(const WildcardNelPolicyKey& other); ~WildcardNelPolicyKey(); bool operator<(const WildcardNelPolicyKey& other) const; // The NIK of the request this policy was received from. This will be used // for any requests uploading reports according to this policy. (Not // included in the report itself.) NetworkIsolationKey network_isolation_key; std::string domain; }; // NEL policy set by an origin. struct NET_EXPORT NelPolicy { NelPolicy(); NelPolicy(const NelPolicy& other); ~NelPolicy(); NelPolicyKey key; IPAddress received_ip_address = IPAddress(); // Reporting API endpoint group to which reports should be sent. std::string report_to; base::Time expires; double success_fraction = 0.0; double failure_fraction = 1.0; bool include_subdomains = false; // Last time the policy was accessed to create a report, even if no report // ends up being queued. Also updated when the policy is first set. mutable base::Time last_used; }; // The details of a network error that are included in an NEL report. // // See http://wicg.github.io/network-error-logging/#dfn-network-error-object // for details on the semantics of each field. struct NET_EXPORT RequestDetails { RequestDetails(); RequestDetails(const RequestDetails& other); ~RequestDetails(); // NetworkIsolationKey of the request triggering the error. Not included // in the uploaded report. NetworkIsolationKey network_isolation_key; GURL uri; GURL referrer; std::string user_agent; IPAddress server_ip; std::string protocol; std::string method; int status_code; base::TimeDelta elapsed_time; Error type; // Upload nesting depth of this request. // // If the request is not a Reporting upload, the depth is 0. // // If the request is a Reporting upload, the depth is the max of the depth // of the requests reported within it plus 1. (Non-NEL reports are // considered to have depth 0.) int reporting_upload_depth; }; // The details of a signed exchange report. struct NET_EXPORT SignedExchangeReportDetails { SignedExchangeReportDetails(); SignedExchangeReportDetails(const SignedExchangeReportDetails& other); ~SignedExchangeReportDetails(); // NetworkIsolationKey of the request triggering the error. Not included // in the uploaded report. NetworkIsolationKey network_isolation_key; bool success; std::string type; GURL outer_url; GURL inner_url; GURL cert_url; std::string referrer; IPAddress server_ip_address; std::string protocol; std::string method; int32_t status_code; base::TimeDelta elapsed_time; std::string user_agent; }; static const char kHeaderName[]; static const char kReportType[]; static const int kMaxNestedReportDepth; // Keys for data included in report bodies. Exposed for tests. static const char kReferrerKey[]; static const char kSamplingFractionKey[]; static const char kServerIpKey[]; static const char kProtocolKey[]; static const char kMethodKey[]; static const char kStatusCodeKey[]; static const char kElapsedTimeKey[]; static const char kPhaseKey[]; static const char kTypeKey[]; static const char kSignedExchangePhaseValue[]; static const char kSignedExchangeBodyKey[]; static const char kOuterUrlKey[]; static const char kInnerUrlKey[]; static const char kCertUrlKey[]; // Maximum number of NEL policies to store before evicting. static const size_t kMaxPolicies; static const char kSignedExchangeRequestOutcomeHistogram[]; // Used for histogramming Signed Exchange request outcomes only. Previously, // the outcome of all requests would be histogrammed, but this was removed in // crbug.com/1007122 because the histogram was very large and not very useful. enum class RequestOutcome { kDiscardedNoNetworkErrorLoggingService = 0, kDiscardedNoReportingService = 1, kDiscardedInsecureOrigin = 2, kDiscardedNoOriginPolicy = 3, kDiscardedUnmappedError = 4, kDiscardedReportingUpload = 5, kDiscardedUnsampledSuccess = 6, kDiscardedUnsampledFailure = 7, kQueued = 8, kDiscardedNonDNSSubdomainReport = 9, kDiscardedIPAddressMismatch = 10, kMaxValue = kDiscardedIPAddressMismatch }; // NEL policies are persisted to disk if |store| is not null. // The store, if given, should outlive |*this|. static std::unique_ptr Create( PersistentNelStore* store); NetworkErrorLoggingService(const NetworkErrorLoggingService&) = delete; NetworkErrorLoggingService& operator=(const NetworkErrorLoggingService&) = delete; virtual ~NetworkErrorLoggingService(); // Ingests a "NEL:" header received for |network_isolation_key| and |origin| // from |received_ip_address| with normalized value |value|. May or may not // actually set a policy for that origin. virtual void OnHeader(const NetworkIsolationKey& network_isolation_key, const url::Origin& origin, const IPAddress& received_ip_address, const std::string& value) = 0; // Considers queueing a network error report for the request described in // |details|. The contents of |details| might be changed, depending on the // NEL policy associated with the request's origin. Note that |details| is // passed by value, so that it doesn't need to be copied in this function if // it needs to be changed. Consider using std::move to pass this parameter if // the caller doesn't need to access it after this method call. // // Note that Network Error Logging can report a fraction of successful // requests as well (to calculate error rates), so this should be called on // *all* secure requests. NEL is only available to secure origins, so this is // not called on any insecure requests. virtual void OnRequest(RequestDetails details) = 0; // Queues a Signed Exchange report. virtual void QueueSignedExchangeReport( SignedExchangeReportDetails details) = 0; // Removes browsing data (origin policies) associated with any origin for // which |origin_filter| returns true. virtual void RemoveBrowsingData( const base::RepeatingCallback& origin_filter) = 0; // Removes browsing data (origin policies) for all origins. Allows slight // optimization over passing an always-true filter to RemoveBrowsingData. virtual void RemoveAllBrowsingData() = 0; // Sets the ReportingService that will be used to queue network error reports. // If |nullptr| is passed, reports will be queued locally or discarded. // |reporting_service| must outlive the NetworkErrorLoggingService. // Should not be called again if previously called with a non-null pointer. void SetReportingService(ReportingService* reporting_service); // Shuts down the NEL service, so that no more requests or headers can be // processed, no more reports are queued, and browsing data can no longer be // cleared. void OnShutdown(); // Sets a base::Clock (used to track policy expiration) for tests. // |clock| must outlive the NetworkErrorLoggingService, and cannot be // nullptr. void SetClockForTesting(const base::Clock* clock); // Dumps info about all the currently stored policies, including expired ones. // Used to display information about NEL policies on the NetLog Reporting tab. virtual base::Value StatusAsValue() const; // Gets the (NIK, origin) keys of all currently stored policies, including // expired ones. virtual std::set GetPolicyKeysForTesting(); virtual PersistentNelStore* GetPersistentNelStoreForTesting(); virtual ReportingService* GetReportingServiceForTesting(); protected: NetworkErrorLoggingService(); // Unowned: raw_ptr clock_; raw_ptr reporting_service_ = nullptr; bool shut_down_ = false; }; // Persistent storage for NEL policies. class NET_EXPORT NetworkErrorLoggingService::PersistentNelStore { public: using NelPoliciesLoadedCallback = base::OnceCallback)>; PersistentNelStore() = default; PersistentNelStore(const PersistentNelStore&) = delete; PersistentNelStore& operator=(const PersistentNelStore&) = delete; virtual ~PersistentNelStore() = default; // Initializes the store and retrieves stored NEL policies. This will be // called only once at startup. virtual void LoadNelPolicies(NelPoliciesLoadedCallback loaded_callback) = 0; // Adds a NEL policy to the store. virtual void AddNelPolicy(const NelPolicy& policy) = 0; // Updates the access time of the NEL policy in the store. virtual void UpdateNelPolicyAccessTime(const NelPolicy& policy) = 0; // Deletes a NEL policy from the store. virtual void DeleteNelPolicy(const NelPolicy& policy) = 0; // Flushes the store. virtual void Flush() = 0; }; } // namespace net #endif // NET_NETWORK_ERROR_LOGGING_NETWORK_ERROR_LOGGING_SERVICE_H_