1# Reporting 2 3Reporting is a central mechanism for sending out-of-band error reports 4to origins from various other components (e.g. HTTP Public Key Pinning, 5Interventions, or Content Security Policy could potentially use it). 6 7The parts of it that are exposed to the web platform are specified in three 8documents: 9 * The original API implemented in Chrome (Reporting V0) can be found at 10 [https://www.w3.org/TR/2018/WD-reporting-1-20180925/]. 11 * The newer API is split into two parts. Document and worker-level reporting 12 (Reporting V1) is specified in the [draft reporting spec] 13 (https://w3c.github.io/reporting/), while Network-level reporting is 14 specified in the [draft network reporting spec] 15 (https://w3c.github.io/reporting/network-reporting.html). 16 17This document assumes that you've read those ones. 18 19## Reporting in Chromium 20 21Reporting is implemented as part of the network stack in Chromium, such 22that it can be used by other parts of the network stack (e.g. HPKP) or 23by non-browser embedders as well as by Chromium. 24 25### Inside `//net` 26 27* The top-level class is the *`ReportingService`*. This lives in the 28 `URLRequestContext`, and provides the high-level operations used by 29 other parts of `//net` and other components: queueing reports, 30 handling configuration headers, clearing browsing data, and so on. 31 32 * A *`ReportingPolicy`* specifies a number of parameters for the Reporting 33 API, such as the maximum number of reports and endpoints to queue, the 34 time interval between delivery attempts, whether or not to persist reports 35 and clients across network changes, etc. It is used to create a 36 `ReportingService` obeying the specified parameters. 37 38 * Within `ReportingService` lives *`ReportingContext`*, which in turn 39 contains the inner workings of Reporting, spread across several classes: 40 41 * The *`ReportingCache`* stores undelivered reports and endpoint 42 configurations (aka "clients" in the V0 spec, and the named endpoint 43 per reporting source in the V1 spec). 44 45 * The *`ReportingHeaderParser`* parses `Report-To:` and 46 `Reporting-Endpoints' headers and updates the cache accordingly. 47 48 * The *`ReportingDeliveryAgent`* reads reports from the cache, decides 49 which endpoints to deliver them to, and attempts to do so. It uses a 50 couple of helper classes: 51 52 * The *`ReportingUploader`* does the low-level work of delivering 53 reports: accepts a URL and JSON from the `DeliveryAgent`, creates 54 a `URLRequest`, and parses the result. It also handles sending 55 CORS preflight requests for cross-origin report uploads. 56 57 * The *`ReportingEndpointManager`* chooses an endpoint from the 58 cache when one is requested by the `ReportingDeliveryAgent`, and 59 manages exponential backoff (using `BackoffEntry`) for failing 60 endpoints. 61 62 * The *`ReportingGarbageCollector`* periodically examines the cache 63 and removes reports that have remained undelivered for too long, or 64 that have failed delivery too many times. 65 66 * The *`ReportingBrowsingDataRemover`* examines the cache upon request 67 and removes browsing data (reports and endpoints) of selected types 68 and origins. 69 70 * The *`ReportingDelegate`* calls upon the `NetworkDelegate` (see below) 71 to check permissions for queueing/sending reports and setting/using 72 clients. 73 74* The `ReportingService` is set up in a `URLRequestContext` by passing a 75 `ReportingPolicy` to the `URLRequestContextBuilder`. This creates a 76 `ReportingService` which is owned by the `URLRequestContext`. 77 78* `Report-To:` headers are processed by an `HttpNetworkTransaction` when they 79 are received, and passed on to the `ReportingService` to be added to the 80 cache. 81 82* `Reporting-Endpoints:` headers are initially parsed by 83 `PopulateParsedHeaders`, where the raw header data is run through the 84 Structured Headers parser. If valid, this structure is stored on the network 85 response until a reporting source can be associated with it, and is then 86 passed through the `ReportingService` to be further validated and added to the 87 cache. 88 89* A reporting source, used only by V1 reports, is a `base::UnguessableToken` 90 associated with the document (or worker eventually) which configures reporting 91 using a `Reporting-Endpoints:` header. This same token must be passed into 92 the `ReportingService` when a report is queued for the correct endpoint to be 93 found. Since the `ReportingService` in `//net` does not know anything about 94 documents or workers, it tracks configurations and reports using this source 95 token. Any object creating such a token is responsible for informing the 96 `ReportingService` when the token will no longer be used (when the document 97 is destroyed, for instance.) This will cause any outstanding reports for that 98 token to be sent, and the configuration removed from the cache. 99 100### Outside `//net` 101 102* In the network service, a `network::NetworkContext` queues reports by getting 103 the `ReportingService` from the `URLRequestContext`. 104 105* The JavaScript [ReportingObserver](https://w3c.github.io/reporting/#observers) 106 interface lives [in `//third_party/blink/renderer/core/frame/`][1]. 107 108 * It queues reports via the `NetworkContext` using a 109 `blink::mojom::ReportingServiceProxy` (implemented [in 110 `//content/browser/network/`][2]), which can queue Intervention, Deprecation, 111 CSP Violation, and Permissions Policy Violation reports. 112 113* The `ChromeNetworkDelegate` [in `//chrome/browser/net/`][3] checks permissions 114 for queueing reports and setting/using clients based on whether cookie access 115 is allowed, and checks permissions for sending reports using a 116 `ReportingPermissionsChecker`, which checks whether the user has allowed 117 report uploading via the BACKGROUND_SYNC permission. 118 119* Cronet can configure "preloaded" `Report-To:` headers (as well as Network 120 Error Logging headers) when initializing a `CronetURLRequestContext`, to allow 121 embedders to collect and send reports before having received a header in an 122 actual response. 123 124 * This functionality is tested on Android by way of sending Network Error 125 Logging reports [in the Cronet Java tests][4]. 126 127## Differences between V0 and V1 reporting 128 129The original V0 reporting API included support for the `Report-To` header only, 130which configures endpoint groups which apply to an entire origin. This is still 131required for Network Error Logging, as those reports are not associated with 132any successful document load. 133 134All V0 reports destined for the same endpoint group may be bundled together for 135delivery, regardless of their source (subject to NAK isolation). 136 137V1 reporting drops the `Report-To` header in favor of `Reporting-Endpoints`, 138which configures named endpoints (single URLs) which are only valid for the 139network resource with which the header was sent. (In general, this means 140documents and workers, since other resources do not currently generate reports. 141Chrome ignores any `Reporting-Endpoints` headers on those responses.) The V1 API 142does not support multiple weighted URLs for an endpoint, or failover between 143them. 144 145V1 reports from the same source may be bundled together in a single delivery, 146but must be delivered separtely from other reports, even those coming from a 147different `Document` object at the same URL. 148 149## Supporting both V0 and V1 reporting in the same codebase 150 151Chrome cannot yet drop support for NEL, and therefore for the `Report-To` 152header. Until we can, it is possible for reports to be sent to endpoints 153configured with either header. NEL reports can only go to those endpoint groups 154configured with `Report-To`. 155 156To support both mechanisms simultaneously, we do the following: 157 158* V1 endpoints are stored in the cache along with V0 endpoint groups. Separate 159 maps are kept of (origin -> endpoint groups) and (source token -> endpoints). 160 161* All reports which can be associated with a specific source (currently all 162 reports except for NEL, which requires origin-scoped V0 configuration) must be 163 queued with that source's reporting source token. 164 165* When a report is to be delivered, the `ReportingDeliveryAgent` will first 166 attempt to find a matching V1 endpoint for the source. Only if that is 167 unsuccessful, because the source is null, or because the named endpoint is not 168 configured, will it fall back to searching for a matching V0 named endpoint 169 group. 170 171[1]: https://chromium.googlesource.com/chromium/src/+/HEAD/third_party/blink/renderer/core/frame/reporting_observer.h 172[2]: https://chromium.googlesource.com/chromium/src/+/HEAD/content/browser/network/reporting_service_proxy.cc 173[3]: https://chromium.googlesource.com/chromium/src/+/HEAD/chrome/browser/net/chrome_network_delegate.h 174[4]: https://chromium.googlesource.com/chromium/src/+/HEAD/components/cronet/android/test/javatests/src/org/chromium/net/NetworkErrorLoggingTest.java 175