Skip to content
144 changes: 144 additions & 0 deletions compatibility.bs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,21 @@ urlPrefix: https://drafts.fxtf.org/css-masking-1/
urlPrefix: https://drafts.csswg.org/css-values-3/
type: dfn
text: dppx; url: #dppx
urlPrefix: https://html.spec.whatwg.org/multipage/
urlPrefix: document-sequences.html
type: dfn
for: browsing context
text: is popup
text: opener browsing context
text: opener origin at creation
urlPrefix: https://privacycg.github.io/nav-tracking-mitigations/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be a tough sell for a WHATWG standard to accept. If this doesn't fly then maybe we could move this PR to a more local spec? Curious what @miketaylr would think.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The link targets here are an extra field on HTML's top-level traversable. Part of merging this PR might be to merge that field into HTML. (Merging it into Compat is also possible, but I believe the bounce tracking record is intended to be more permanent than the heuristics in this PR.)

type: dfn
for: top-level traversable
text: bounce tracking record; url: top-level-traversable-bounce-tracking-record
for: bounce tracking record
text: initial host; url: #bounce-tracking-record-initial-host
text: bounce set; url: #bounce-tracking-record-bounce-set
text: user activation set; url: #bounce-tracking-record-user-activation-set
</pre>

<pre class="biblio">
Expand All @@ -67,9 +82,11 @@ spec:css-display-3; type:value; for:display; text:flex
spec:css-flexbox-1; type:value; text:inline-flex
spec:css-syntax-3; type:dfn; text:invalid
spec:filter-effects-1; type:property; text:filter
spec:infra; type:dfn; text:list
spec:infra; type:dfn; text:user agent
spec:svg2; type:dfn; text:fill
spec:svg2; type:dfn; text:stroke
spec:url; type:dfn; for:url; text:host
</pre>

<!-- Commented out until we know what the heck to put here:
Expand Down Expand Up @@ -836,6 +853,133 @@ supported on all {{Window}} objects and <code><{body}></code> elements as attrib
</tbody>
</table>

<h2 id="sa-heuristics-section">Cookie Access Heuristics</h2>

User agents are blocking third-party cookies by default while avoiding user-facing
breakage by removing support for common web patterns, particularly login flows via
third-party identity providers. Browsers should follow the established patterns in
this specification in order to provide short-term cookie access to unbreak these flows.

<h3 id="sa-heuristics-global-data">Global Data</h3>

A <dfn>site pair</dfn> is a [=tuple=] consisting of a [=site=] <dfn for=site pair>third party site</dfn>
and a [=site=] <dfn for=site pair>first party site</dfn>

The user agent holds a <dfn>heuristic grants map</dfn> which is a [=map=] of [=site pairs=] to
[=moments=]. The [=moment=] represents the expiration timestamp of a cookie access grant
for [=third party site=] on [=first party site=].

<h3 id="sa-heuristics-constants">Constants</h3>

The <dfn>popup heuristic grant duration</dfn> is an [=implementation-defined=]
[=duration=] that represents the length of time after the popup heuristic is
triggered that a user agent will store the corresponding popup heuristic grant
in its [=heuristic grants map=].

Note: Most implementations use 30 days as the [=popup heuristic grant duration=].

The <dfn>redirect heuristic grant duration</dfn> is an [=implementation-defined=]
[=duration=] that represents the length of time after the redirect heuristic is
triggered that a user agent will store the corresponding redirect heuristic grant
in its [=heuristic grants map=].

Note: Most implementations use 15 minutes as the [=redirect heuristic grant duration=].

<h3 id="sa-heuristics-access-grant">Cookie Access Grant</h3>

<div algorithm>

To <dfn>grant access for heuristics</dfn> given a [=site=] |site|, [=site=]
|firstPartySite|, [=moment=] |currentWallTime|, and [=duration=] |duration|,
perform the following steps:

1. Let |key| be a [=site pair=] with [=third party site=] set to |site| and
[=first party site=] set to |firstPartySite|.
1. Let |expirationTime| be |duration| after |currentWallTime|.
1. Set [=heuristic grants map=][|key|] to |expirationTime|.

</div>

<h3 id="sa-heuristics-access">Cookie Access Monkey Patch</h3>

Issue: TODO: add monkey patch to network fetch cookie access that reads from [=heuristic grants map=].

<h3 id="sa-heuristics-popup">Popup Heuristic</h3>

Append the following steps to the [[!HTML]]'s <a spec="html">activation notification</a> algorithm:

<div algorithm="user-activation-patch">

1. Run [=detect a popup heuristic=] given <var ignore>document</var>.

</div>

<div algorithm>

To <dfn>detect a popup heuristic</dfn> given a [=Document=] |document|,
perform the following steps:

1. Let |browsingContext| be |document|'s [=Document/browsing context=].
1. If |browsingContext|'s [=browsing context/is popup=] is false, then return.
1. If |browsingContext|'s [=browsing context/opener browsing context=] is null, then return.
1. If |browsingContext|'s [=browsing context/opener origin at creation=] is null, then return.
1. Let |firstPartySite| be the result of running [=obtain a site=] given the |browsingContext|'s
[=browsing context/opener origin at creation=].
1. Let |navigable| be |document|'s [=node navigable=].
1. If |navigable| is null, then return.
1. Let |topDocument| be |navigable|'s [=navigable/top-level traversable=]'s
[=navigable/active document=].
1. Let |origin| be |topDocument|'s [=Document/origin=].
1. If |origin| is an [=opaque origin=] then return.
1. Let |site| be the result of running [=obtain a site=] given |origin|.
1. Let |currentWallTime| be |topDocument|'s [=relevant settings object=]'s
[=environment settings object/current wall time=].
1. [=Grant access for heuristics=] given |site|, |firstPartySite|, |currentWallTime|, and
[=popup heuristic grant duration=].

Issue(amaliev/3pcd-exemption-heuristics#3): TODO: Consider whether to check for third-party iframe initiators.

</div>

<h3 id="sa-heuristics-redirect">Redirect Heuristic</h3>

Insert the following steps at the start of [[!HTML]]'s <a spec="html">load a document</a> algorithm.

<div algorithm="loading-a-document-patch">

1. Run [=detect a redirect heuristic=] given <var ignore>navigationParams</var>'s <var ignore>navigable</var>.

</div>

<div algorithm>

To <dfn>detect a redirect heuristic</dfn> given a [=/navigable=] |navigable|, perform the following
steps:

1. Let |topDocument| be |navigable|'s [=navigable/top-level traversable=]'s
[=navigable/active document=].
1. Let |firstPartyOrigin| be |topDocument|'s [=Document/origin=].
1. If |firstPartyOrigin| is an [=opaque origin=] then return.
1. Let |firstPartySite| be the result of running [=obtain a site=] given |firstPartyOrigin|.
1. Let |bounceTrackingRecord| be |navigable|'s [=navigable/top-level traversable=]'s
[=top-level traversable/bounce tracking record=].
1. Let |currentWallTime| be |topDocument|'s [=relevant settings object=]'s
[=environment settings object/current wall time=].
1. Let |navigatedUrlsSet| be |bounceTrackingRecord|'s [=bounce tracking record/bounce set=].
1. Append |bounceTrackingRecord|'s [=bounce tracking record/initial host=] to |navigatedUrlsSet|.
1. [=list/For each=] |bounceUrl| in |navigatedUrlsSet|:
1. Let |site| be the result of running [=obtain a site=] given |bounceUrl|.
1. If |site| is [=site/same site=] to |firstPartySite|, [=iteration/continue=].
1. If |bounceTrackingRecord|'s [=bounce tracking record/user activation set=] does not contain |site|,
[=iteration/continue=].
<!-- TODO: Check that the user visited |firstPartySite| before |site|, to verify the
[A-B-A flow](https://github.com/amaliev/3pcd-exemption-heuristics/blob/main/explainer.md#scenario-c2).
This will require traversing the navigable's history. -->
1. [=Grant access for heuristics=] given |site|, |firstPartySite|, |currentWallTime|, and
[=redirect heuristic grant duration=].

</div>

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a description of how this impacts the (admittedly underspecified) cookie computation in Fetch like in https://privacycg.github.io/nav-tracking-mitigations/#bounce-tracking-mitigations-network-cookie-write-monkey-patch

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a new section with a TODO for now. Will update soon.

<h2 id="ua-string-section">The User-Agent String</h2>

The <code>User-Agent</code> header field syntax is formally defined by [[!HTTP-SEMANTICS]] and
Expand Down