.. | ||
DIR_METADATA | ||
mock_persistent_reporting_store.cc | ||
mock_persistent_reporting_store.h | ||
OWNERS | ||
README.md | ||
reporting_browsing_data_remover.cc | ||
reporting_browsing_data_remover.h | ||
reporting_cache_impl.cc | ||
reporting_cache_impl.h | ||
reporting_cache_observer.cc | ||
reporting_cache_observer.h | ||
reporting_cache.cc | ||
reporting_cache.h | ||
reporting_context.cc | ||
reporting_context.h | ||
reporting_delegate.cc | ||
reporting_delegate.h | ||
reporting_delivery_agent.cc | ||
reporting_delivery_agent.h | ||
reporting_endpoint_manager.cc | ||
reporting_endpoint_manager.h | ||
reporting_endpoint.cc | ||
reporting_endpoint.h | ||
reporting_garbage_collector.cc | ||
reporting_garbage_collector.h | ||
reporting_header_parser.cc | ||
reporting_header_parser.h | ||
reporting_network_change_observer.cc | ||
reporting_network_change_observer.h | ||
reporting_policy.cc | ||
reporting_policy.h | ||
reporting_policy.proto | ||
reporting_report.cc | ||
reporting_report.h | ||
reporting_service.cc | ||
reporting_service.h | ||
reporting_target_type.h | ||
reporting_test_util.cc | ||
reporting_test_util.h | ||
reporting_uploader.cc | ||
reporting_uploader.h |
Reporting
Reporting is a central mechanism for sending out-of-band error reports to origins from various other components (e.g. HTTP Public Key Pinning, Interventions, or Content Security Policy could potentially use it).
The parts of it that are exposed to the web platform are specified in three documents:
- The original API implemented in Chrome (Reporting V0) can be found at [https://www.w3.org/TR/2018/WD-reporting-1-20180925/].
- The newer API is split into two parts. Document and worker-level reporting (Reporting V1) is specified in the [draft reporting spec] (https://w3c.github.io/reporting/), while Network-level reporting is specified in the [draft network reporting spec] (https://w3c.github.io/reporting/network-reporting.html).
This document assumes that you've read those ones.
Reporting in Chromium
Reporting is implemented as part of the network stack in Chromium, such that it can be used by other parts of the network stack (e.g. HPKP) or by non-browser embedders as well as by Chromium.
Inside //net
-
The top-level class is the
ReportingService
. This lives in theURLRequestContext
, and provides the high-level operations used by other parts of//net
and other components: queueing reports, handling configuration headers, clearing browsing data, and so on.-
A
ReportingPolicy
specifies a number of parameters for the Reporting API, such as the maximum number of reports and endpoints to queue, the time interval between delivery attempts, whether or not to persist reports and clients across network changes, etc. It is used to create aReportingService
obeying the specified parameters. -
Within
ReportingService
livesReportingContext
, which in turn contains the inner workings of Reporting, spread across several classes:-
The
ReportingCache
stores undelivered reports and endpoint configurations (aka "clients" in the V0 spec, and the named endpoint per reporting source in the V1 spec). -
The
ReportingHeaderParser
parsesReport-To:
and `Reporting-Endpoints' headers and updates the cache accordingly. -
The
ReportingDeliveryAgent
reads reports from the cache, decides which endpoints to deliver them to, and attempts to do so. It uses a couple of helper classes:-
The
ReportingUploader
does the low-level work of delivering reports: accepts a URL and JSON from theDeliveryAgent
, creates aURLRequest
, and parses the result. It also handles sending CORS preflight requests for cross-origin report uploads. -
The
ReportingEndpointManager
chooses an endpoint from the cache when one is requested by theReportingDeliveryAgent
, and manages exponential backoff (usingBackoffEntry
) for failing endpoints.
-
-
The
ReportingGarbageCollector
periodically examines the cache and removes reports that have remained undelivered for too long, or that have failed delivery too many times. -
The
ReportingBrowsingDataRemover
examines the cache upon request and removes browsing data (reports and endpoints) of selected types and origins. -
The
ReportingDelegate
calls upon theNetworkDelegate
(see below) to check permissions for queueing/sending reports and setting/using clients.
-
-
-
The
ReportingService
is set up in aURLRequestContext
by passing aReportingPolicy
to theURLRequestContextBuilder
. This creates aReportingService
which is owned by theURLRequestContext
. -
Report-To:
headers are processed by anHttpNetworkTransaction
when they are received, and passed on to theReportingService
to be added to the cache. -
Reporting-Endpoints:
headers are initially parsed byPopulateParsedHeaders
, where the raw header data is run through the Structured Headers parser. If valid, this structure is stored on the network response until a reporting source can be associated with it, and is then passed through theReportingService
to be further validated and added to the cache. -
A reporting source, used only by V1 reports, is a
base::UnguessableToken
associated with the document (or worker eventually) which configures reporting using aReporting-Endpoints:
header. This same token must be passed into theReportingService
when a report is queued for the correct endpoint to be found. Since theReportingService
in//net
does not know anything about documents or workers, it tracks configurations and reports using this source token. Any object creating such a token is responsible for informing theReportingService
when the token will no longer be used (when the document is destroyed, for instance.) This will cause any outstanding reports for that token to be sent, and the configuration removed from the cache.
Outside //net
-
In the network service, a
network::NetworkContext
queues reports by getting theReportingService
from theURLRequestContext
. -
The JavaScript ReportingObserver interface lives in
//third_party/blink/renderer/core/frame/
.- It queues reports via the
NetworkContext
using ablink::mojom::ReportingServiceProxy
(implemented in//content/browser/network/
), which can queue Intervention, Deprecation, CSP Violation, and Permissions Policy Violation reports.
- It queues reports via the
-
The
ChromeNetworkDelegate
in//chrome/browser/net/
checks permissions for queueing reports and setting/using clients based on whether cookie access is allowed, and checks permissions for sending reports using aReportingPermissionsChecker
, which checks whether the user has allowed report uploading via the BACKGROUND_SYNC permission. -
Cronet can configure "preloaded"
Report-To:
headers (as well as Network Error Logging headers) when initializing aCronetURLRequestContext
, to allow embedders to collect and send reports before having received a header in an actual response.- This functionality is tested on Android by way of sending Network Error Logging reports in the Cronet Java tests.
Differences between V0 and V1 reporting
The original V0 reporting API included support for the Report-To
header only,
which configures endpoint groups which apply to an entire origin. This is still
required for Network Error Logging, as those reports are not associated with
any successful document load.
All V0 reports destined for the same endpoint group may be bundled together for delivery, regardless of their source (subject to NAK isolation).
V1 reporting drops the Report-To
header in favor of Reporting-Endpoints
,
which configures named endpoints (single URLs) which are only valid for the
network resource with which the header was sent. (In general, this means
documents and workers, since other resources do not currently generate reports.
Chrome ignores any Reporting-Endpoints
headers on those responses.) The V1 API
does not support multiple weighted URLs for an endpoint, or failover between
them.
V1 reports from the same source may be bundled together in a single delivery,
but must be delivered separtely from other reports, even those coming from a
different Document
object at the same URL.
Supporting both V0 and V1 reporting in the same codebase
Chrome cannot yet drop support for NEL, and therefore for the Report-To
header. Until we can, it is possible for reports to be sent to endpoints
configured with either header. NEL reports can only go to those endpoint groups
configured with Report-To
.
To support both mechanisms simultaneously, we do the following:
-
V1 endpoints are stored in the cache along with V0 endpoint groups. Separate maps are kept of (origin -> endpoint groups) and (source token -> endpoints).
-
All reports which can be associated with a specific source (currently all reports except for NEL, which requires origin-scoped V0 configuration) must be queued with that source's reporting source token.
-
When a report is to be delivered, the
ReportingDeliveryAgent
will first attempt to find a matching V1 endpoint for the source. Only if that is unsuccessful, because the source is null, or because the named endpoint is not configured, will it fall back to searching for a matching V0 named endpoint group.