New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 912951 link

Starred by 1 user

Issue metadata

Status: Started
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 3
Type: Bug

Blocking:
issue 895821



Sign in to add a comment

Reporting: Assumption that origins only include each endpoint in one group

Project Member Reported by chlily@chromium.org, Dec 7

Issue description

Currently we assume that each origin only registers a given endpoint in one group, as the endpoint configs (ReportingClients) are stored as a std::map<url::Origin, std::map<GURL, std::unique_ptr<ReportingClient>>> keyed on the origin, then the endpoint URL. This could be inaccurate if the same endpoint is in multiple groups for an origin (perhaps with different priorities or weights), as the spec does not preclude this.

This could result in missing (overwritten) clients, and thus reports that are erroneously undeliverable. For example, suppose the server sends a Report-To header like this:

Report-To: { "group": "group_a",
             "max_age": 10886400,
             "endpoints": [
               { "url": "https://endpoints.com/default" }
             ] },
           { "group": "group_b",
             "max_age": 10886400,
             "endpoints": [
               { "url": "https://endpoints.com/preferred",
                 "priority": 0 },
               { "url": "https://endpoints.com/default",
                 "priority": 1 }
             ] }

Then ReportingCache::SetClient() will overwrite the group_a ReportingClient with a new ReportingClient of the same endpoint URL but in group_b, thus leaving group_a with no endpoints. Then let's say a report gets queued up to be sent to group_a. ReportingEndpointManager::FindClientForOriginAndGroup() will not be able to find a client for group_a, thus resulting in ReportingDeliveryAgent skipping the report (and eventually it gets evicted, expired, or garbage collected).
 
Cc: dcreager@chromium.org
+dcreager

Did I miss something obvious? I'm not sure why we keep the clients in a std::map<url::Origin, std::map<GURL, std::unique_ptr<ReportingClient>>>. Was there a reason for this in the initial implementation?

I'm thinking of switching it over to a std::map<url::Origin, std::multimap<std::string, std::unique_ptr<ReportingClient>>>, to key on the origin then the group name.
Great catch!  This is a holdover from an earlier draft of the Reporting spec.  Before https://github.com/w3c/reporting/pull/67, each endpoint URL was a top-level element of the Report-To header, and so it was structurally impossible for there to be more than one ReportingClient with the same URL.  But now, you're right, this data structure doesn't line up with what you can express in a Report-To header.

I think your suggested refactoring is a good possibility.  Another would be to make proper classes for each of the named concepts in the spec: clients, endpoint groups, and endpoints.  What is currently named ReportingClient is really closer to what's now called "endpoint" in the spec — a single URL, within a single group, for a single origin.  If you go down this route, you'd end up with:

- rename ReportingClient to ReportingEndpoint
- clients is a std::map<url::Origin, ReportingClient>
- ReportingClient would contain a std::map<std::string, ReportingEndpointGroup> (i.e., all of the endpoint groups for the origin, keyed by their name)
- ReportingEndpointGroup would contain a std::vector<ReportingEndpoint>

That might be more invasive of a change than you're looking for, but it would make all of the named concepts in the code line up with the spec!
Status: Started (was: Assigned)
Ah I see, thanks a lot for the context!
Blocking: 895821

Sign in to add a comment