Skip to content

Commit db00367

Browse files
authored
Fix request clients for prefetch + service workers (#378)
Fixes #346. In particular: * Fixed prefetch activation to use the correct reserved clients. Previously, the prefetch activation parts of the specification (in "create a navigation params from a prefetch record") would assume that the request they were being passed had a reserved client, when in reality they did not, because "create a navigation request" did not set a reserved client. We change them to consult the reserved clients from the redirect chain, which is more correct anyway. * Properly creates a new reserved environment during each prefetch activation, by creating a new environment with correct values, including the active service worker. This is necessary to avoid prefetch record reuse from causing the creation of multiple clients with the same ID. * Makes the resultingClientId on the FetchEvent that occurs during prefetch be the empty string. The client ID is not known at the time of the prefetch, so this is the only possibility that makes sense.
1 parent 16c6d5a commit db00367

File tree

1 file changed

+35
-11
lines changed

1 file changed

+35
-11
lines changed

prefetch.bs

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -360,28 +360,33 @@ The user agent may [=prefetch record/cancel and discard=] records from the [=Doc
360360
1. Let |coopEnforcementResult| be the result of [=creating a cross-origin opener policy enforcement result for navigation=] given |navigable|'s [=navigable/active document=] and |documentState|'s [=document state/initiator origin=].
361361
1. Let |finalSandboxFlags| be an empty [=sandboxing flag set=].
362362
1. Let |responsePolicyContainer| be null.
363+
1. Let |activeServiceWorker| be null.
363364
1. Let |urlList| be an empty [=list=].
364365
1. [=list/For each=] |exchangeRecord| in |record|'s [=prefetch record/redirect chain=]:
365-
1. Let |response| be |exchangeRecord|'s [=exchange record/response=].
366-
1. [=list/Append=] |response|'s [=response/URL=] to |urlList|.
367-
1. Set |responsePolicyContainer| to the result of [=creating a policy container from a fetch response=] given |response| and |request|'s [=request/reserved client=].
366+
1. Let |redirectChainRequest| be |exchangeRecord|'s [=exchange record/request=].
367+
1. Let |redirectChainResponse| be |exchangeRecord|'s [=exchange record/response=].
368+
1. [=list/Append=] |redirectChainRequest|'s [=request/URL=] to |urlList|.
369+
1. Set |responsePolicyContainer| to the result of [=creating a policy container from a fetch response=] given |redirectChainResponse| and |redirectChainRequest|'s [=request/reserved client=].
368370
1. Set |finalSandboxFlags| to the [=set/union=] of |targetSnapshotParams|'s [=target snapshot params/sandboxing flags=] and |responsePolicyContainer|'s [=policy container/CSP list=]'s [=CSP-derived sandboxing flags=].
369-
1. Set |responseOrigin| to the result of [=determining the origin=] given |response|'s [=response/URL=], |finalSandboxFlags|, |documentState|'s [=document state/initiator origin=], and null.
371+
1. Set |responseOrigin| to the result of [=determining the origin=] given |redirectChainResponse|'s [=response/URL=], |finalSandboxFlags|, |documentState|'s [=document state/initiator origin=], and null.
372+
1. Set |activeServiceWorker| to |redirectChainRequest|'s [=request/reserved client=]'s [=environment/active service worker=].
370373
1. If |navigable| is a [=top-level traversable=], then:
371-
1. Set |responseCOOP| to the result of [=obtaining a cross-origin opener policy=] given |response| and |request|'s [=request/reserved client=].
374+
1. Set |responseCOOP| to the result of [=obtaining a cross-origin opener policy=] given |redirectChainResponse| and |redirectChainRequest|'s [=request/reserved client=].
372375
1. [=Assert=]: If |finalSandboxFlags| is not empty, then |responseCOOP|'s [=cross-origin opener policy/value=] is "`unsafe-none`".
373376

374377
<p class="note">This is guaranteed since the sandboxing flags of the document cannot change to become non-empty since this was prefetched, and the check was not done for a different window. If this changes, this will need to be able to handle failure of this check.</p>
375-
1. Set |coopEnforcementResult| to the result of [=enforcing a response's cross-origin opener policy=] given |navigable|'s [=active browsing context=], |response|'s [=response/URL=], |responseOrigin|, |responseCOOP|, |coopEnforcementResult|, and |exchangeRecord|'s [=exchange record/request=]'s [=request/referrer=].
378+
1. Set |coopEnforcementResult| to the result of [=enforcing a response's cross-origin opener policy=] given |navigable|'s [=active browsing context=], |redirectChainResponse|'s [=response/URL=], |responseOrigin|, |responseCOOP|, |coopEnforcementResult|, and |exchangeRecord|'s [=exchange record/request=]'s [=request/referrer=].
376379
1. Set |request|'s [=request/URL list=] to |urlList|.
380+
1. <span id="prefetch-activation-client-creation"></span>Set |request|'s [=request/reserved client=] to the result of [=creating a reserved client=] given |navigable| and |request|'s [=request/URL=].
381+
382+
<p class="note">This will be the [=environment=] used for constructing the resulting {{Document}} and [=environment settings object=]. We need a separate [=environment=] for each time a [=prefetch record=] is consumed, instead of using |record|'s [=prefetch record/redirect chain=]'s last item's [=exchange record/request=]'s [=request/reserved client=], because otherwise reusing the same prefetch record for multiple [=navigation params=] (i.e., multiple navigations) would cause the created [=environment settings objects=] to share an [=environment/id=]. This would then be visible, e.g., through the {{Clients/get()|clients.get()}} API, in a very confusing way.
383+
1. Set |request|'s [=request/reserved client=]'s [=environment/active service worker=] to |activeServiceWorker|.
377384
1. Let |resultPolicyContainer| be the result of [=determining navigation params policy container=] given |record|'s [=prefetch record/response=]'s [=response/URL=], |documentState|'s [=document state/history policy container=], |sourceSnapshotParams|'s [=source snapshot params/source policy container=], null, and |responsePolicyContainer|.
378385
1. Let |response| be |record|'s [=prefetch record/response=].
379386
1. Optionally, set |response| to a [=response/clone=] of |response|.
380387

381388
<p class="note">An implementation might wish to do this if it believes that the prefetch will be consumed more than once. For example, if in the future the response is consumed by a prerender, that [=prerendering traversable=] might be [=destroy a top-level traversable|destroyed=] through various means. Normally that would mean the response is discarded, but if the implementation performs this step, then the prefetched response will still be available to serve a future navigation. [[PRERENDERING-REVAMPED]]
382389
1. If the user agent did not perform the previous optional step, then it must [=list/remove=] |record| from |navigable|'s [=navigable/active document=]'s [=Document/prefetch records=].
383-
384-
385390
1. Return a new [=navigation params=], with:
386391
: [=navigation params/id=]
387392
:: |navigationId|
@@ -433,6 +438,11 @@ A <dfn export>cross-origin prefetch IP anonymization policy</dfn> has an <dfn ex
433438

434439
This section contains patches to [[HTML]].
435440

441+
Add an additional item to [=environment=] as follows:
442+
443+
: <dfn for="environment">is navigational prefetch client</dfn>
444+
:: a [=boolean=] (default false)
445+
436446
Add an additional item to [=navigation params=] as follows:
437447
: <dfn for="navigation params">delivery type</dfn>
438448
:: a [=string=] (corresponding to {{PerformanceResourceTiming}} [=PerformanceResourceTiming/delivery type=])
@@ -587,7 +597,9 @@ Modify the [=snapshot source snapshot params=] algorithm to set the return value
587597
1. Run the [=environment discarding steps=] for |request|'s [=request/reserved client=].
588598
1. Set |request|'s [=request/reserved client=] to null.
589599
1. Set |commitEarlyHints| to null.
590-
1. If |request|'s [=request/reserved client=] is null, then set |request|'s [=request/reserved client=] to the result of [=creating a reserved client=] given |navigable|, |currentURL| and |isolationOrigin|.
600+
1. If |request|'s [=request/reserved client=] is null, then:
601+
1. Set |request|'s [=request/reserved client=] to the result of [=creating a reserved client=] given |navigable|, |currentURL| and |isolationOrigin|.
602+
1. If |prefetchRecord| was given, then set |request|'s [=request/reserved client=]'s [=environment/is navigational prefetch client=] to true.
591603
1. If the result of [=should navigation request of type be blocked by Content Security Policy?=] given |request| and |cspNavigationType| is "`Blocked`", then set |response| to a [=network error=] and [=iteration/break=]. [[CSP]]
592604
1. If |prefetchRecord| was given, then:
593605
1. Let |purpose| be a [=structured header/List=] containing the [=structured header/Token=] `prefetch`.
@@ -721,6 +733,20 @@ This section contains patches to [[NAVIGATION-TIMING]].
721733
Add an additional parameter to [=create the navigation timing entry=], which is a [=string=] <var ignore>deliveryType</var>, and pass it as an additional argument to [=setup the resource timing entry=].
722734
</div>
723735

736+
<h2 id="service-workers-patches">Service Workers Patches</h2>
737+
738+
This section contains patches to [[SERVICE-WORKERS]].
739+
740+
<div algorithm="Create Fetch Event and Dispatch">
741+
Modify <a spec="SERVICE-WORKERS">Create Fetch Event and Dispatch</a>'s step which sets {{FetchEvent/resultingClientId}} as follows:
742+
743+
<blockquote>
744+
If |request| is a [=non-subresource request=] and |request|'s [=request/destination=] is not "{{RequestDestination/report}}"<ins> and |reservedClient|'s [=environment/is navigational prefetch client=] is false</ins>, initialize <var ignore>e</var>'s {{FetchEvent/resultingClientId}} attribute to |reservedClient|'s [=environment/id=], and to the empty string otherwise.
745+
</blockquote>
746+
747+
<p class="note">In the prefetch case, although |request| has a [=request/reserved client=] at this time, it is just a specification fiction to help the request go through. It does not represent an actual client, of the sort that can be seen in e.g. {{Clients/matchAll()|clients.matchAll()}}. Actual client creation happens <a href="#prefetch-activation-client-creation">at activation time</a>, which will be after the {{FetchEvent}} is done firing.
748+
</div>
749+
724750
<h2 id="clear-site-data-patches">Clear Site Data patches</h2>
725751

726752
Add an additional header value description in [[CLEAR-SITE-DATA#header]]:
@@ -755,8 +781,6 @@ Modify <a abstract-op spec="CLEAR-SITE-DATA">clear site data for response</a>'s
755781

756782
<h2 id="prefetch-algorithms">Prefetch algorithms</h2>
757783

758-
<p class="issue">Check Service Worker integration</p>
759-
760784
The <dfn>list of sufficiently strict speculative navigation referrer policies</dfn> is a list containing the following: "", "`strict-origin-when-cross-origin`", "`strict-origin`", "`same-origin`", "`no-referrer`".
761785

762786
<div algorithm>

0 commit comments

Comments
 (0)