Skip to content

Report body interfaces #216

Open

Description

@domenic

Looking at Chromium's implementation, I see a lot of "report body" interfaces:

However, most of these don't exist in specifications. And, many of them are using [NoInterfaceObject], which no longer exists on the web platform (it was removed from Web IDL).

I'm unsure how the spec is supposed to work here, and the specs definitely don't seem to match implementations.

  • The Reporting API's "queue a violation report" algorithm takes an "object". But, the ReportingObserver API uses ReportBody, so is there an implicit requirement that such objects be subclasses of ReportBody?

  • Some specs appear to fill this out using a generic "a new object" language, e.g. Fetch and COEP. This does not involve any interfaces. The proposed COOP reporting spec in Cross origin opener policy reporting whatwg/html#5518 does the same, although as noted above, the in-progress Chromium implementation seems to use an interface. How do these things show up in ReportingObserver?

  • I can't figure out what the CSP spec is doing, but it certainly doesn't use CSPViolationReportBody.

  • I can't find any spec for InterventionReportBody or DeprecationReportBody.

  • DocumentPolicyViolationReportBody doesn't exist in Document Policy, and I can't find where that spec queues reports. Maybe that part isn't written yet?

  • Permissions Policy seems to be fully on board the interface train: it declares a proper, non-NoInterfaceObject report body interface, and sends that through the "queue a violation report" algorithm.

This seems like a pretty big mess.

My recommendation if we were starting from scratch would be to not use interfaces for this, and have "queue a violation report" take either an object, or something more structured (like a record<USVString, any> or an Infra ordered map) to give guidance to callers. Implementations could unobservably use IDL dictionaries behind the scenes if they wanted, but specs would use the Fetch/COEP/COOP style of just supplying a table of keys/values. And we'd get rid of ReportBody entirely and make ReportingObserver's body just an object? instead of a ReportBody?.

However, we're not starting from scratch, so I'm unsure what the best path forward is.

/cc @clelland @camillelamy @mikewest

Activity

  1. jpchase commented on Aug 27, 2020

    @jpchase
    Collaborator

    Re not finding a spec for InterventionReportBody or DeprecationReportBody. In #189, crash, deprecation and intervention reports were moved to their own separate repos:
    Crash reporting (spec)
    Deprecation reporting (spec)
    Intervention reporting (spec)

    All three of these use the full interface approach, similar to Permissions Policy.

  2. domenic commented on Aug 27, 2020

    @domenic
    ContributorAuthor

    Thanks! That certainly tips the balance, at least in specs space, toward the full-interface approach. Although it feels a little unnecessary to create new constructor-less classes for things that are just data holders (see w3ctag/design-principles#11), it's not the end of the world. It's the current inconsistency that's troublesome, and in particular as HTML editor reviewing the COEP and COOP spec patches, I'm not sure what to do.

  3. clelland commented on Aug 27, 2020

    @clelland
    Contributor
    • Document Policy should define its report type; that's an omission.
    • Chrome needs to remove the "NoInterfaceObject" from the various body types. I just filed crbug.com/1122656 for that.
    • In ReportingObserver, these objects (as the 'body' property of the observed Report) are instances of their respective types, and are not simply ES dictionaries. The Reporting spec just says

    Each report has a body, which is either null or an object which can be serialized into a JSON text. The fields contained in a report’s body are determined by the report’s type.

    • Crash reports are necessarily not visible to reporting observers; it doesn't really matter what we do with those as long as the serialized report is correct.
  4. clelland commented on Aug 28, 2020

    @clelland
    Contributor

    We could switch to plain ES objects; there's really no benefit that I can see to using classes. It was added to support ReportingObserver; I suspect that it was originally so that we could use IDL to express the structure and the members that would be present.

  5. domenic commented on Aug 28, 2020

    @domenic
    ContributorAuthor

    You could still use dictionaries, either behind the scenes in implementations, or in specs if desired (although I'm not sure that would buy much).

  6. jpchase commented on Aug 28, 2020

    @jpchase
    Collaborator

    There was #164 where toJSON() wasn't working in Chromium, but there were also spec changes made. Just pointing it out, in case it matters here.

  7. domenic commented on Aug 28, 2020

    @domenic
    ContributorAuthor

    Yeah, using normal JS objects (dictionaries) would be a more natural way of solving that, instead of having the code generator generate a bunch of getters and a toJSON() method.

  8. self-assigned this
    on Jun 20, 2022
  9. RByers commented on Nov 25, 2022

    @RByers
    Collaborator

    Following up from discussion of this on blink-dev.

    The principle of using dictionaries when there's only data makes sense to me. But dictionaries can't be used as attributes and Report has a body attribute.

  10. domenic commented on Nov 25, 2022

    @domenic
    ContributorAuthor

    I think Report itself can be a dictionary, looking at how it's used?

  11. clelland commented on Nov 25, 2022

    @clelland
    Contributor

    Yes, Report could also be a dictionary; I don't believe that there are any constraints on dictionaries being dictionary members.

  12. RByers commented on Nov 25, 2022

    @RByers
    Collaborator

    I think Report itself can be a dictionary, looking at how it's used?

    Oh I see, make Report a dictionary and then ReportBody isn't an attribute anymore so all of them can be dictionaries too. Yeah that makes sense. I'm just looking over to try to understand if there would be any non-trivial web compat implications of this. @clelland thoughts?

  13. clelland commented on Nov 25, 2022

    @clelland
    Contributor

    I can't see any compat issues -- without the interface object currently being exposed, there doesn't seem to be any way to get the type of a Report or ReportBody -- so there shouldn't be any type-detection going on right now that would fail if we switched to dictionaries.

    Reports (and their bodies) currently look like Objects to a script, and that wouldn't change. (The "Report" and e.g. "DeprecationReportBody" names are visible in DevTools' representation of the reports, so I'm not 100% sure that there's no way to discover them currently, but I don't believe it's likely.

  14. clelland commented on Nov 25, 2022

    @clelland
    Contributor

    (Not that anyone should be using something other than the type member to do report-type detection; I was just checking to see if it's currently even possible)

  15. RByers commented on Nov 25, 2022

    @RByers
    Collaborator

    Yeah it looks like it is possible in theory, eg:

    > window.speechSynthesis.getVoices()[0][Symbol.toStringTag]
    'SpeechSynthesisVoice'
    

    But poking around at this stuff (like __proto__ etc.) has always been somewhat implementation defined AFAIK, so I'm not worried about it as a real compat risk in practice.

  16. 1 remaining item

  17. clelland commented on Nov 25, 2022

    @clelland
    Contributor

    That's the one that does it... rpt.body[Symbol.toStringTag] reports the internal type.

    That would change to Object for a dictionary, I suspect, if anyone were actually relying on it. It does seem substantially less likely to be a compatibility risk, for sure.

  18. added a commit that references this issue on Dec 4, 2022
    e894337
  19. clelland commented on Dec 5, 2022

    @clelland
    Contributor

    Moving to dictionaries makes sense to me -- I've put up a PR at #258 for that.

    @bakulf, do you think this would work for Gecko?

  20. TimvdLippe commented on Jun 12, 2025

    @TimvdLippe

    In #284 these interfaces were removed. I was working on implementing this spec in Servo and was working on implementing https://w3c.github.io/webappsec-csp/#cspviolationreportbody as well. The web IDL currently doesn't compile anymore, as interface CSPViolationReportBody : ReportBody is invalid. Should we remove the : ReportBody from CSPViolationReportBody in CSP or also make it a dictionary (not sure if that's legal web IDL):

    dictionary CSPViolationReportBody : ReportBody {
      USVString documentURL;
      USVString? referrer;
      USVString? blockedURL;
      DOMString effectiveDirective;
      DOMString originalPolicy;
      USVString? sourceFile;
      DOMString? sample;
      SecurityPolicyViolationEventDisposition disposition;
      unsigned short statusCode;
      unsigned long? lineNumber;
      unsigned long? columnNumber;
    };
  21. tidoust commented on Jun 13, 2025

    @tidoust
    Member

    More generally, cross-spec checks in Webref now complain about the following specs because they still define interfaces that inherit from ReportBody. Is there a plan to fix them or should I raise individual issues?

  22. TimvdLippe commented on Jun 13, 2025

    @TimvdLippe

    Based on w3c/webappsec-subresource-integrity#141 it seems like the dictionary CSPViolationReportBody : ReportBody solution is the way to go

  23. hamishwillee commented on Jun 17, 2025

    @hamishwillee

    Is it the intent that all report bodies will have a dictionary in the IDL? I ask because COOP and COEP violations do not, as discussed in whatwg/html#11365

  24. domenic commented on Jun 17, 2025

    @domenic
    ContributorAuthor

    No, only report bodies which need to show up in ReportingObserver need a dictionary.

  25. hamishwillee commented on Jun 17, 2025

    @hamishwillee

    @domenic Ah, so you're saying that COEP and COOP violations report only to server endpoints? I missed that entirely.

  26. ddbeck commented on Feb 20, 2026

    @ddbeck

    This discrepancy between specifications (i.e., inheriting from a former interface) mentioned by @tidoust in #216 (comment) has come up again in recording these changes in MDN and browser compat data. See: mdn/browser-compat-data#27047 (comment). It'd be nice to have issues (or fixed specs) to help future contributors understand what's going on here.

  27. theIDinside commented on Mar 2, 2026

    @theIDinside

    Visibility

    Chrome L* Firefox L* Safari L*
    Report None Yes None Yes Window, Worker No
    ReportBody Window, Worker No Window, Worker No Window, Worker No
    ReportingObserver Window, Worker No Window, Worker No Window, Worker No
    The Different Types Of Reports
    CSPViolationReportBody Window No Window No Window No
    DeprecationReportBody None Yes None Yes Window, Worker No
    IntegrityPolicyViolationReportBody Window No Window No None Yes

    (L* = LegacyNoInterfaceObject)

    We implemented and turned on Reporting API by default recently, and while deciding on if they should be dictionaries or interfaces, to be as webcompatible as possible, we also went with interfaces, trying to be as close as possible to other browsers. The table shows some of the web visible interfaces that we found at that time at least.

    Is there any push amongst other browsers to start using dictionaries? For now, Firefox will continue using interfaces for these.

  28. hamishwillee commented on Mar 2, 2026

    @hamishwillee

    FYI, there is at least

    The MDN docs have been updated to assume that they are all dictionaries - the interfaces are stripped mdn/content#43195.

  29. annevk commented on Nov 5, 2026

    @annevk
    Member

    I'm looking at fixing the WPT situation while also fixing this in WebKit: WebKit/WebKit#79766. I also filed an issue for one library that might be impacted by this (though not in a way that would impact the end user): nextcloud/spreed#20155.

    Changes to tests:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions