Open Bug 1797408 Opened 2 years ago Updated 1 year ago

[DNR] Implement domainType (firstParty / thirdParty) condition

Categories

(WebExtensions :: Request Handling, enhancement, P3)

enhancement
Points:
1

Tracking

(Not tracked)

People

(Reporter: robwu, Unassigned)

References

(Blocks 1 open bug)

Details

(Whiteboard: [addons-jira])

The DNR API contains a "domainType" condition with the values "firstParty" and "thirdParty".

Before implementing this, examine whether it would help extension developers with a substantial use case. Here is a thread that questions the current behavior of domainType in Chromium's issue tracker: https://bugs.chromium.org/p/chromium/issues/detail?id=1191223

Whiteboard: [add
Whiteboard: [add → [addons-jira]
Points: --- → 1

It would be trivial to implement this, but only once we decide what "thirdParty" / "firstParty" means.

Common across all browsers, the generally understood meaning is "same domain" (or "same-site" or even "same-origin") relative to the top-level document. At least, in the context of cookies (third-party cookies on MDN), that has consistently been the case, and is also reflected in various mechanisms to isolate cookies. For example, all of the following define first/third-party in relation to the top level document:

In Firefox, there is an interpretation of "third-party" exposed in the details.thirdParty in the webRequest API: "Indicates whether the request and its content window hierarchy are third party." In other words, if all documents up to the top are same-domain to the requested URL, then it's first-party. Otherwise it's third-party.

In Safari 15+, in contrast to the above definition of "first-party" (same-site), the domainType in DNR is translated to the "first-party" / "third-party" trigger of the internal Content Blocking API and means "first-party triggers only if the resource has the same scheme, domain, and port as the main page resource. third-party triggers if the resource isn’t from the same domain as the main page resource." . The unusual part here is that the check is "same-origin" instead of "same-domain".

Inconsistent with existing conventions, Chrome, domainType in DNR is documented to mean "whether the network request is first-party or third-party to the domain from which it originated.". In other words, whether the requested URL and "request initiator" are same-domain. Chrome's DNR is backed by a subresource_filter, and its very first implementation already had this interpretation of "first-party" (source of indexed_ruleset.cc, part of commit, still present in the latest version of indexed_ruleset.cc). This implementation has been called out as defective by extension devs, e.g. at https://bugs.chromium.org/p/chromium/issues/detail?id=1191223#c6

To sum up, here are three potential ways to interpret what "first-party" means for a given request URL:

  1. (Chrome's DNR) First-party iff same-domain to (sub)document that initiates the request. Third-party otherwise.
  2. (Safari's DNR) First-party iff same-origin to top-level document. Third-party otherwise.
  3. (Firefox's webRequest) First-party iff same-domain for the whole frame hierarchy. Third-party otherwise.

The following are true:

  • first-party in Firefox implies first-party in Chrome
    • and first-party in Firefox would also have implied first-party in Safari, but since Safari's "same-origin" is stricter than Firefox's "same-domain", it is possible for something to be first-party in Firefox, yet third-party in Safari (e.g. scheme differs).
  • third-party in Chrome implies third-party in Firefox, but not necessarily third-party in Safari.
  • third-party in Safari implies third-party in Firefox, but not necessarily third-party in Chrome.
  • first-party in Chrome or Safari does not guarantee first-party in the other browsers.

In addition to the detailed comparison in comment 1, I'd also like to note that the "allowAllRequests" action was originally designed to support domain hierarchy matching:

But despite the generic API design of allowAllRequests, it does not sufficiently cover the use cases of extension devs, evidenced by:

The distinction between "domainType" (this bug + comment 1) and "allowAllRequests" (and follow-ups) is that domainType describes first/third-party relations (to be decided: immediate initiator, top-level initiator, all frame ancestors), whereas the latter describes relations with explicit domains.

to be decided: immediate initiator, top-level initiator, all frame ancestors

EasyList semantic for its third-party option is "immediate initiator". Implementing a different semantic would make it impossible to properly convert filter lists compliant with EasyList syntax, which is what all top content blockers use, i.e. at least six of the eight top content blockers by usage in Mozilla's AMO: uBO, ABP, Adblock Ultimate, AdBlock, Ghostery, AdGuard. For the remaining two (DuckDuckGo Privacy Essentials, Privacy Badger), I didn't look into it.

(In reply to rhill@raymondhill.net from comment #3)

to be decided: immediate initiator, top-level initiator, all frame ancestors

EasyList semantic for its third-party option is "immediate initiator".

In case of iframes, the initiator (of the navigation) may have a different domain/origin than the embedder of the frame. For example, if A embeds B, the initiator and embedder of B is A in both cases. But if B navigates to C, then the C request is initiated by B while the parent is A.
Which domain should be used to determine whether a navigation request is same-party?

Often, the "domain" can directly be inferred from the document (or Worker) that initiates a request. That is not always the case, e.g. with sandboxed documents. What's the desired behavior here?

You need to log in before you can comment on or make changes to this bug.