Skip to content

Commit fbc0faa

Browse files
Navigation preload (#983)
* Rebasing on new, cleaner spec. * Fixing linking & formatting bugs * Invalid state error is more consistent with the rest of the spec * Following review feeback * Service workers mode * Reverting skip-sw-flag change
1 parent 03578ce commit fbc0faa

File tree

2 files changed

+581
-184
lines changed

2 files changed

+581
-184
lines changed

docs/index.bs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
201201

202202
A [=/service worker registration=] has one or more <dfn export id="dfn-service-worker-registration-task-queue">task queues</dfn> that back up the <a>tasks</a> from its <a>active worker</a>'s <a>event loop</a>'s corresponding [=/task queues=]. (The target task sources for this back up operation are the <a>handle fetch task source</a> and the <a>handle functional event task source</a>.) The user agent dumps the <a>active worker</a>'s <a>tasks</a> to the [=/service worker registration=]'s [=service worker registration/task queues=] when the <a>active worker</a> is <a lt="terminate service worker">terminated</a> and <a lt="queue a task">re-queues those tasks</a> to the <a>active worker</a>'s <a>event loop</a>'s corresponding [=/task queues=] when the <a>active worker</a> spins off. Unlike the [=/task queues=] owned by <a>event loops</a>, the [=/service worker registration=]'s [=service worker registration/task queues=] are not processed by any <a>event loops</a> in and of itself.
203203

204+
A [=/service worker registration=] has an associated <dfn export>{{NavigationPreloadManager}}</dfn> object.
205+
206+
A [=/service worker registration=] has an associated <dfn export>navigation preload enabled flag</dfn>. It is initially unset.
207+
208+
A [=/service worker registration=] has an associated <dfn export>navigation preload header value</dfn>, which is a [=byte sequence=]. It is initially set to \`<code>true</code>\`.
209+
204210
<section>
205211
<h4 id="service-worker-registration-lifetime">Lifetime</h4>
206212

@@ -389,6 +395,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
389395
readonly attribute ServiceWorker? installing;
390396
readonly attribute ServiceWorker? waiting;
391397
readonly attribute ServiceWorker? active;
398+
readonly attribute NavigationPreloadManager navigationPreload;
392399

393400
readonly attribute USVString scope;
394401
readonly attribute boolean useCache;
@@ -427,6 +434,12 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
427434
Note: The {{ServiceWorker}} objects returned from this attribute getter that represent the same [=/service worker=] are the same objects.
428435
</section>
429436

437+
<section algorithm>
438+
<h4 id="service-worker-registration-navigationpreload"><dfn>{{ServiceWorkerRegistration/navigationPreload}}</dfn></h4>
439+
440+
The {{navigationPreload}} attribute's getter *must* return the [=/service worker registration's=] {{NavigationPreloadManager}} object.
441+
</section>
442+
430443
<section algorithm="service-worker-registration-scope">
431444
<h4 id="service-worker-registration-scope">{{ServiceWorkerRegistration/scope}}</h4>
432445

@@ -731,6 +744,71 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
731744
</section>
732745
</section>
733746

747+
<section>
748+
<h3 id="navigation-preload-manager">{{NavigationPreloadManager}}</h3>
749+
750+
<pre class="idl">
751+
[SecureContext, Exposed=(Window,Worker)]
752+
interface NavigationPreloadManager {
753+
Promise&lt;void&gt; enable();
754+
Promise&lt;void&gt; disable();
755+
Promise&lt;void&gt; setHeaderValue(ByteString value);
756+
Promise&lt;NavigationPreloadState&gt; getState();
757+
};
758+
759+
dictionary NavigationPreloadState {
760+
boolean enabled = false;
761+
ByteString headerValue;
762+
};
763+
</pre>
764+
765+
<section algorithm>
766+
<h4 id="navigation-preload-manager-enable"><dfn>{{NavigationPreloadManager/enable()}}</dfn></h4>
767+
768+
The {{NavigationPreloadManager/enable()}} method, when invoked, *must* return a new [=promise=] |promise| and run the following steps [=in parallel=]:
769+
770+
1. Let |registration| be the [=context object=]'s associated [=/service worker registration=].
771+
1. If |registration|'s [=active worker=] is null, [=reject=] |promise| with an "{{InvalidStateError}}" exception, and abort these steps.
772+
1. Set |registration|'s [=navigation preload enabled flag=].
773+
1. [=Resolve=] |promise| with undefined.
774+
</section>
775+
776+
<section algorithm>
777+
<h4 id="navigation-preload-manager-disable"><dfn>{{NavigationPreloadManager/disable()}}</dfn></h4>
778+
779+
The {{NavigationPreloadManager/disable()}} method, when invoked, *must* return a new [=promise=] |promise| and run the following steps [=in parallel=]:
780+
781+
1. Let |registration| be the [=context object=]'s associated [=/service worker registration=].
782+
1. If |registration|'s [=active worker=] is null, [=reject=] |promise| with an "{{InvalidStateError}}" exception, and abort these steps.
783+
1. Unset |registration|'s [=navigation preload enabled flag=].
784+
1. [=Resolve=] |promise| with undefined.
785+
</section>
786+
787+
<section algorithm>
788+
<h4 id="navigation-preload-manager-setheadervalue"><dfn>{{NavigationPreloadManager/setHeaderValue(value)}}</dfn></h4>
789+
790+
The <a method for="NavigationPreloadManager"><code>setHeaderValue(|value|)</code></a> method, when invoked, *must* return [=a new promise=] |promise| and run the following steps [=in parallel=]:
791+
792+
1. Let |registration| be the [=context object=]'s associated [=/service worker registration=].
793+
1. If |registration|'s [=active worker=] is null, [=reject=] |promise| with an "{{InvalidStateError}}" exception, and abort these steps.
794+
1. Set |registration|'s [=navigation preload header value=] to |value|.
795+
1. [=Resolve=] |promise| with undefined.
796+
</section>
797+
798+
<section algorithm>
799+
<h4 id="navigation-preload-manager-getstate"><dfn>{{NavigationPreloadManager/getState()}}</dfn></h4>
800+
801+
The {{NavigationPreloadManager/getState()}} method, when invoked, *must* return [=a new promise=] |promise| and run the following steps [=in parallel=]:
802+
803+
1. Let |registration| be the [=context object=]'s associated [=/service worker registration=].
804+
1. Let |state| be a new {{NavigationPreloadState}} dictionary.
805+
1. If |registration|'s [=navigation preload enabled flag=] is set, set |state|'s {{NavigationPreloadState/enabled}} dictionary member to true.
806+
1. Set |state|'s {{NavigationPreloadState/headerValue}} dictionary member to the |registration|'s [=navigation preload header value=].
807+
1. [=Resolve=] |promise| with |state|.
808+
</section>
809+
810+
</section>
811+
734812
<section>
735813
<h2 id="execution-context">Execution Context</h2>
736814

@@ -1292,6 +1370,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
12921370
[Constructor(DOMString type, FetchEventInit eventInitDict), Exposed=ServiceWorker]
12931371
interface FetchEvent : ExtendableEvent {
12941372
[SameObject] readonly attribute Request request;
1373+
readonly attribute Promise&lt;any&gt; preloadResponse;
12951374
readonly attribute DOMString clientId;
12961375
readonly attribute DOMString reservedClientId;
12971376
readonly attribute DOMString targetClientId;
@@ -1303,6 +1382,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
13031382
<pre class="idl" id="fetch-event-init-dictionary">
13041383
dictionary FetchEventInit : ExtendableEventInit {
13051384
required Request request;
1385+
required Promise&lt;any&gt; preloadResponse;
13061386
DOMString clientId = "";
13071387
DOMString reservedClientId = "";
13081388
DOMString targetClientId = "";
@@ -1324,6 +1404,12 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
13241404
<dfn attribute for="FetchEvent"><code>request</code></dfn> attribute *must* return the value it was initialized to.
13251405
</section>
13261406

1407+
<section>
1408+
<h4 id="fetch-event-preloadresponse">{{FetchEvent/preloadResponse|event.preloadResponse}}</h4>
1409+
1410+
<dfn attribute for="FetchEvent"><code>preloadResponse</code></dfn> attribute *must* return the value it was initialized to.
1411+
</section>
1412+
13271413
<section>
13281414
<h4 id="fetch-event-clientid">{{FetchEvent/clientId|event.clientId}}</h4>
13291415

@@ -2782,6 +2868,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
27822868
1. Let |registration| be null.
27832869
1. Let |client| be |request|'s [=request/client=].
27842870
1. Let |reservedClient| be |request|'s [=request/reserved client=].
2871+
1. Let |preloadResponse| be a new [=promise=].
27852872
1. Assert: |request|'s [=request/destination=] is not "<code>serviceworker</code>".
27862873
1. If |request| is a <a>potential-navigation-or-subresource request</a>, then:
27872874
1. Return null.
@@ -2797,6 +2884,21 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
27972884
1. Set |registration| to the result of running <a>Match Service Worker Registration</a> algorithm passing |request|'s [=request/url=] as the argument.
27982885
1. If |registration| is null or |registration|'s <a>active worker</a> is null, return null.
27992886
1. If |request|'s [=request/destination=] is not {{RequestDestination/"report"}}, set |reservedClient|'s <a>active service worker</a> to |registration|'s <a>active worker</a>.
2887+
1. If |request| is a [=navigation request=] and |registration|'s [=navigation preload enabled flag=] is set, and |request|'s [=request/method=] is \`<code>GET</code>\`, then:
2888+
1. Let |preloadRequest| be the result of [=request/cloning=] the request |request|.
2889+
1. Let |preloadRequestHeaders| be |preloadRequest|'s [=request/header list=].
2890+
1. Let |preloadResponseObject| be a new {{Response}} object and a new associated {{Headers}} object whose [=guard=] is "`immutable`".
2891+
1. [=header list/Append=] to |preloadRequestHeaders| a new [=header=] whose [=header/name=] is \`<code>Service-Worker-Navigation-Preload</code>\` and [=header/value=] is |registration|'s [=navigation preload header value=].
2892+
1. Set |preloadRequest|'s [=skip-service-worker flag=].
2893+
1. Run the following substeps [=in parallel=]:
2894+
1. [=Fetch=] |preloadRequest|.
2895+
2896+
To [=process response=] for |navigationPreloadResponse|, run these substeps:
2897+
2898+
1. If |navigationPreloadResponse|'s [=response/type=] is "`error`", reject |preloadResponse| with a `TypeError` and terminate these substeps.
2899+
1. Associate |preloadResponseObject| with |navigationPreloadResponse|.
2900+
1. Resolve |preloadResponse| with |navigationPreloadResponse|.
2901+
1. Else, resolve |preloadResponse| with undefined.
28002902

28012903
Note: From this point, the [=/service worker client=] starts to <a>use</a> its <a>active service worker</a>'s <a>containing service worker registration</a>.
28022904

@@ -2818,6 +2920,7 @@ spec: webappsec-referrer-policy; urlPrefix: https://w3c.github.io/webappsec-refe
28182920
1. Initialize |e|’s {{Event/type}} attribute to {{fetch!!event}}.
28192921
1. Initialize |e|’s {{Event/cancelable}} attribute to true.
28202922
1. Initialize |e|’s {{FetchEvent/request}} attribute to |r|.
2923+
1. Initialize |e|’s {{FetchEvent/preloadResponse}} to |preloadResponse|.
28212924
1. Initialize |e|'s {{FetchEvent/clientId}} attribute to |client|'s [=environment/id=].
28222925
1. If |request| is a <a>non-subresource request</a> and |request|'s [=request/destination=] is not {{RequestDestination/"report"}}, initialize |e|'s {{FetchEvent/reservedClientId}} attribute to |reservedClient|'s [=environment/id=], and to the empty string otherwise.
28232926
1. If |request| is a <a>navigation request</a>, initialize |e|'s {{FetchEvent/targetClientId}} attribute to |request|'s [=request/target client id=], and to the empty string otherwise.

0 commit comments

Comments
 (0)