forked from WICG/webpackage
-
Notifications
You must be signed in to change notification settings - Fork 0
/
subresource-loading.bs
661 lines (496 loc) · 27.1 KB
/
subresource-loading.bs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
<pre class="metadata">
Title: Subresource Loading with Web Bundles
Shortname: web-package-subresource-loading
Level: none
Status: CG-DRAFT
Group: WICG
Repository: WICG/webpackage
URL: https://wicg.github.io/webpackage/subresource-loading.html
Editor: Hayato Ito, Google Inc. https://google.com/, [email protected]
Editor: Hiroshige Hayashizaki, Google https://google.com/, [email protected]
Abstract: How UAs load subresources from Web Bundles.
Complain About: accidental-2119 yes, missing-example-ids yes
Indent: 2
Markup Shorthands: markdown yes, css no
Assume Explicit For: yes
</pre>
<pre class='biblio'>
{
"draft-ietf-wpack-bundled-responses-latest": {
"href": "https://wpack-wg.github.io/bundled-responses/draft-ietf-wpack-bundled-responses.html",
"title": "Web Bundles"
}
}
</pre>
<pre class='anchors'>
spec: fetch; urlPrefix: https://fetch.spec.whatwg.org/#
type: dfn
text: fetch params; url: fetch-params
type: dfn
text: processResponse; url: process-response
type: dfn
text: incrementally reading; url: body-incrementally-read
spec: csp; urlPrefix: https://w3c.github.io/webappsec-csp/#
type: dfn
text: policy; url: content-security-policy-object
spec: url; urlPrefix: https://url.spec.whatwg.org/#
type: dfn
text: shortening; url: shorten-a-urls-path
spec: infra; urlPrefix: https://infra.spec.whatwg.org/#
type: dfn
text: continue; url: iteration-continue
spec: html; urlPrefix: https://html.spec.whatwg.org/#
type: dfn
text: the script's type; url: concept-script-type
type: dfn
text: the script's result; url: concept-script-result
type: dfn
text: delay the load event; url: delay-the-load-event
</pre>
<pre class="link-defaults">
spec:fetch; type:dfn; for:/; text:request
spec:fetch; type:dfn; for:/; text:response
spec:html; type:element; text:link
spec:url; type:dfn; for:/; text:url
</pre>
# Introduction # {#intro}
<em>This section is non-normative.</em>
The Subresource Loading with Web Bundles specification describes a way to load a
large number of resources efficiently using a format that allows multiple
resources to be bundled, [Web Bundles](https://web.dev/web-bundles/). This
specification describes how web browsers load those resources. It is expressed
as several monkeypatches to the [[HTML]], [[FETCH]] and [[CSP]] specification
which call algorithms defined here.
Note: This specification is under construction. See
<a href="https://github.com/WICG/webpackage/issues/708">#708</a>.
# Structures # {#structures}
A <dfn>fetched web bundle</dfn> is a representation of a web bundle format
defined in [[draft-ietf-wpack-bundled-responses-latest]].
A <dfn>web bundle fetch entry</dfn> is a [=struct=] with the following
[=struct/items=]:
- <dfn for="web bundle fetch entry">source</dfn>, a [=URL=] of a web bundle.
- <dfn for="web bundle fetch entry">credentials</dfn>, a [=request/credentials
mode=].
- <dfn for="web bundle fetch entry">state</dfn>, an internal state which is
"fetching", "fetched", or "failed". Initially "fetching".
- <dfn for="web bundle fetch entry">fetched bundle</dfn>, a [=fetched web
bundle=] or null.
ISSUE: A better name for [=web bundle fetch entry=]?
A [=web bundle fetch entry=] |entry| is <dfn for="web bundle fetch entry">used
by a registration</dfn> in [=Document=] |document| if |document|'s
[=Document/web bundle registration list=] [=list/contains=] a [=web bundle
registration=] whose [=web bundle registration/fetch entry=] is |entry|.
A <dfn>bundle rule</dfn> is a [=struct=] with the following [=struct/items=]:
- <dfn for="bundle rule">resources</dfn>, a [=list=] of [=URLs=].
- <dfn for="bundle rule">scopes</dfn>, a [=list=] of [=URLs=].
A <dfn>web bundle registration</dfn> is a [=struct=] with the following
[=struct/items=]:
- <dfn for="web bundle registration">fetch entry</dfn>, a [=web bundle fetch
entry=].
- <dfn for="web bundle registration">rule</dfn>, a [=bundle rule=].
A <dfn>web bundle parse result</dfn> is a [=struct=] with the following
[=struct/items=]:
- <dfn for="web bundle parse result">source</dfn>, a [=URL=] of a web bundle.
- <dfn for="web bundle parse result">credentials</dfn>, a [=request/credentials
mode=].
- <dfn for="web bundle parse result">rule</dfn>, a [=bundle rule=].
Each [=environment settings object=] will get a
<dfn for="environment settings object">web bundle registration list</dfn>
algorithm, which returns a [=list=] of [=web bundle registrations=].
A {{Document}} has a <dfn for=Document>web bundle registration list</dfn>, which
is a [=list=] of [=web bundle registrations=]. It is initially empty.
In <a spec="html">set up a window environment settings object</a>,
<var ignore>settings object</var>'s [=environment settings object/web bundle
registration list=] returns the [=Document/web bundle registration list=] of
<var ignore>window</var>'s <a>associated <code>Document</code></a>.
In <a spec="html">set up a worker environment settings object</a>,
<var ignore>settings object</var>'s [=environment settings object/web bundle
registration list=] returns an empty [=list=].
A {{Document}} has a <dfn for=Document>web bundle fetch entry list</dfn>, which
is a [=list=] of [=web bundle fetch entries=]. It is initially empty.
ISSUE: While [=list=] is used for [=Document/web bundle fetch entry list=], the
order shouldn't be important.
ISSUE: Not supported for workers.
# HTML monkeypatches # {#html-monkeypatches}
To process web bundles in the <a spec="html">prepare the script element</a>
algorithm consistently with existing script types (i.e. classic or module), we
make the following changes:
- <a spec="html">the script's type</a> should be either "classic", "module", or
"webbundle"
- Introduce <dfn>web bundle result</dfn>, which is a [=struct=] with two
[=struct/items=]:
- a <dfn for="web bundle result">registration</dfn>, a [=web bundle
registration=]; and
- an <dfn for="web bundle result">error to rethrow</dfn>, a JavaScript value
representing a parse error when non-null.
- <a spec="html">the script's result</a> is either "uninitiated", null,
<a href="https://html.spec.whatwg.org/multipage/webappapis.html#concept-script">script</a>,
or a [=web bundle result=].
Note: Because we don't make [=web bundle result=] a new subclass of
<a href="https://html.spec.whatwg.org/multipage/webappapis.html#concept-script">script</a>,
other script execution-related specs are left unaffected.
## Prepare the script element ## {#prepare-the-script-element}
Inside the <a spec="html">prepare the script element</a> algorithm, we make the
following changes:
- Insert the following step to <a spec="html">prepare the script element</a>
step 10:
- If the script block's type string is an [=ASCII case-insensitive=] match for
the string "`webbundle`", then set el's type to "`webbundle`".
- Insert the following case to <a spec="html">prepare the script element</a>
step 26.7:
- "`webbundle`":
1. [=Queue a task=] to [=fire an event=] named `error` at the element, and
return.
Note: `<script type="webbundle" src=...>` is not supported. There are no
specific requirements for the error handling here, so currently an
`error` event is fired similarly to the case of an empty `src` attribute.
- Insert the following case to <a spec="html">prepare the script element</a>
step 27.2:
- "`webbundle`":
1. [=Prepare a web bundle=] given <var ignore>element</var>,
<var ignore>source text</var> and <var ignore>base URL</var>.
- Insert the following case to <a spec="html">prepare the script element</a>
step 28:
- If <a spec="html">the script's type</a> is "`webbundle`":
1. Assert: script's <a spec="html">ready to be parser-executed</a> is true.
1. [=In parallel=], [=process events for a web bundle=] given
<var ignore>element</var>.
NOTE: CSPs are applied to inline web bundles at Step 15 of
<a spec="html">prepare the script element</a>, just like applied to
classic/module scripts.
To <dfn>prepare a web bundle</dfn>, given an {{HTMLScriptElement}} |element|, a
[=string=] |sourceText| and a [=URL=] |baseURL|:
1. Let |parse result| be the result of [=parse a web bundle string=] given
|sourceText| and |baseURL|.
1. If this throws an exception:
1. Set [=the script's result=] to a new [=web bundle result=] with its [=web
bundle result/registration=] is null and its [=web bundle result/error to
rethrow=] is the exception thrown.
1. <a spec="html">Mark as ready</a>.
1. Return.
1. Let |document| be |element|'s <a spec="html">node document</a>.
1. Set |fetch entry| to null.
1. For each |r| in |document|'s [=Document/web bundle fetch entry list=]:
1. If |r|'s [=web bundle fetch entry/source=] is |parse result|'s [=web
bundle parse result/source=] and |r|'s [=web bundle fetch
entry/credentials=] is |parse result|'s [=web bundle parse
result/credentials=], then:
1. If |r| is not [=web bundle fetch entry/used by a registration=] in
|document|, then set |fetch entry| to |r|.
NOTE: This implies that another script element whose [=the script's
result=]'s [=web bundle result/registration=]'s [=web bundle
registration/fetch entry=] is |r| was removed. This is to ensure that
[=web bundle fetch entries=] are not destructed and re-fetched when
{{HTMLScriptElement}}s with the same web bundle [=web bundle fetch
entry/source=] and [=web bundle fetch entry/credentials=] are removed
and added.
1. If |fetch entry| is null:
1. Set |fetch entry| to a new [=web bundle fetch entry=] with its [=web
bundle fetch entry/source=] is |parse result|'s [=web bundle parse
result/source=], its [=web bundle fetch entry/credentials=] is |parse
result|'s [=web bundle parse result/credentials=], its [=web bundle fetch
entry/state=] is "fetching", and its [=web bundle fetch entry/fetched
bundle=] is null.
1. [=list/Append=] |fetch entry| to |document|'s [=Document/web bundle fetch
entry list=].
1. [=In parallel=], [=fetch a web bundle=] |fetch entry|.
1. Let |registration| be a new [=web bundle registration=] with its [=web bundle
registration/fetch entry=] is |fetch entry| and its [=web bundle
registration/rule=] is |parse result|'s [=web bundle parse result/rule=].
1. [=list/Append=] |registration| to |document|'s [=Document/web bundle
registration list=].
1. Set [=the script's result=] to a new [=web bundle result=] with its [=web
bundle result/registration=] is |registration| and its [=web bundle
result/error to rethrow=] is null.
1. <a spec="html">Mark as ready</a>.
## Firing events ## {#firing-events}
In <a spec="html">execute the script element</a>, add the following case to Step
6:
- "`webbundle`":
1. Assert: Never reached.
Note: Web bundles are processed by [=process events for a web bundle=] instead of <a spec="html">execute the script element</a>.
To <dfn>process events for a web bundle</dfn> given an {{HTMLScriptElement}}
|element|:
1. Let |result| be [=the script's result=] of |element|.
1. Assert: |element|'s <a spec="html">the script's type</a> is "`webbundle`".
1. Assert: |result| is an [=web bundle result=].
1. Await asynchronously until either of the following conditions met:
- |result|'s [=web bundle result/error to rethrow=] is not null, or
- |result|'s [=web bundle result/registration=] is not null and |result|'s
[=web bundle result/registration=]'s [=web bundle registration/fetch
entry=]'s [=web bundle fetch entry/state=] becomes "fetched" or "failed".
Note: Unlike other script types, we wait asynchronously here for [=fetch web
bundle=] before firing `load` events at {{HTMLScriptElement}}. We don't
<a spec="html">delay the load event</a> here, because we <a spec="html">mark
as ready</a> synchronously in <a spec="html">prepare the script element</a>.
This is intentional because [=fetch a web bundle=] is similar to preloading.
1. If [=the script's result=] of |element| is null, then return.
Note: This can happen when |element| was
<a spec="html" href="https://html.spec.whatwg.org/multipage/infrastructure.html#remove-an-element-from-a-document">removed
from the document</a> during the previous step.
Note: This is specified consistently with
<a href="https://github.com/whatwg/html/pull/2673">whatwg/html#2673</a>.
Currently we don't fire `error` events in this case. If we change the
decision at
<a href="https://github.com/whatwg/html/pull/2673">whatwg/html#2673</a> to
fire `error` events, then change this step accordingly.
1. Assert: |element|'s <a spec="html">node document</a> is equal to |element|'s
<a href="spec">preparation-time document</a>.
1. If |result|'s [=web bundle result/error to rethrow=] is not null, then:
1. <a spec="html">Report the exception</a> given |result|'s [=web bundle
result/error to rethrow=].
ISSUE: There are no relevant
<a href="https://html.spec.whatwg.org/multipage/webappapis.html#concept-script">script</a>,
because [=web bundle result=] isn't a
<a href="https://html.spec.whatwg.org/multipage/webappapis.html#concept-script">script</a>.
This needs to wait for
<a href="https://github.com/whatwg/html/issues/958">whatwg/html#958</a>
before it is fixable.
1. Return.
1. Assert: |result|'s [=web bundle result/registration=] is not null.
1. If |result|'s [=web bundle result/registration=]'s [=web bundle
registration/fetch entry=]'s [=web bundle fetch entry/state=] is "failed":
1. [=Fire an event=] named `error` at |element|.
1. Return.
1. Assert: |result|'s [=web bundle result/registration=]'s [=web bundle
registration/fetch entry=]'s [=web bundle fetch entry/state=] is "fetched".
1. [=Fire an event=] named `load` at |element|.
## Removing ## {#removing}
If `script` element is
<a spec="html" href="https://html.spec.whatwg.org/multipage/infrastructure.html#remove-an-element-from-a-document">removed
from the document</a>, user agents must run the following algorithm:
1. If <a spec="html">the script's type</a> is not "`webbundle`", then return.
1. If [=the script's result=] is null, then return.
1. Assert: [=the script's result=] is an [=web bundle result=].
1. Let |registration| be [=the script's result=]'s [=web bundle
result/registration=].
1. Set [=the script's result=] to null.
1. If |registration| is null, then return.
1. Let |document| be the <a spec="html">node document</a>.
1. Assert: |document|'s [=Document/web bundle registration list=]
[=list/contains=] |registration|.
1. [=list/Remove=] |registration| from |document|'s [=Document/web bundle
registration list=].
1. [=Queue a microtask=] to perform the following steps:
1. Let |fetch entry| be |registration|'s [=web bundle registration/fetch
entry=].
1. If |fetch entry| is [=web bundle fetch entry/used by a registration=] in
|document|, then return.
1. [=list/Remove=] |fetch entry| from |document|'s [=Document/web bundle
fetch entry list=].
Note: It is possible that |document|'s [=Document/web bundle fetch entry
list=] doesn't [=list/contain=] |fetch entry| even before this step, if
|fetch entry| is used by [=web bundle registrations=] of multiple `script`
elements and the `script elements` are removed.
Note: At this point, |fetch entry| can no longer used by subsequent
subresource fetches nor subsequent [=prepare a web bundle=] calls, but its
[=web bundle fetch entry/fetched bundle=] can be still in use by ongoing
fetches.
# Fetch monkeypatches # {#fetch-monkeypatches}
## Monkeypatch fetch ## {#monkeypatch-fetch}
In <a spec="fetch">fetch</a>, before
> 2. Let taskDestination be null.
add the following step:
2. If the result of [=find a matching web bundle registration=] given |request|
is null, set |request|'s [=request/service-workers mode=] to "`none`".
Note: This means that no service workers will get events for a subresource
loading from a webbundle.
## Monkeypatch fetch scheme ## {#monkeypatch-fetch-scheme}
Add "`uuid-in-package`" to the schemes listed in <a spec="fetch">fetch
scheme</a>.
Note: This ensures that the <a spec="html">navigate</a> algorithm uses the
<a spec="html">process a navigate fetch</a> algorithm for `uuid-in-package:`
URLs.
Note: The [=url/origin=] of a URL whose scheme is "`uuid-in-package`" is an
opaque origin.
## Monkeypatch HTTP-network-or-cache fetch ## {#monkeypatch-http-network-or-cache-fetch}
In <a spec="fetch">HTTP-network-or-cache fetch</a>, before
> 8.22. Set httpCache to the result of determining the HTTP cache partition,
> given |httpRequest|.
add the following steps:
22. Set the |response| to the result of [=fetch a subresource from web bundle=],
given |httpRequest|.
1. If |response| is [=network error=], return [=network error=].
2. If |response| is non-null, skip the steps 8.22-8.24 and goto the step 9.
Note: That means a subresource from a webbundle never interacts with
HttpCache. We plan to support HttpCache as a feature enhancement in the
future.
# CSP monkeypatches # {#csp-monkeypatches}
## Monkeypatch Does request match source list? ## {#monkeypatch-match-request-to-source-list}
Rewrite
<a href="https://w3c.github.io/webappsec-csp/#match-request-to-source-list">Does
|request| match |source list|?</a> to run these steps:
1. Let |url| be |request|'s [=request/current url=].
2. If |url|'s [=url/scheme=] is "`uuid-in-package`", then:
1. Let |registration| be the result of running [=find a matching web bundle
registration=] given |request|.
2. If |registration| is not null, then set |url| to |registration|'s [=web
bundle registration/fetch entry=]'s [=web bundle fetch entry/source=].
3. Returns the result of executing
<a href="https://w3c.github.io/webappsec-csp/#match-url-to-source-list">Does
url match source list in origin with redirect count?</a> on |url|, |source
list|, |policy|'s [=policy/self-origin=], and |request|'s [=request/redirect
count=].
Note: This means that CSP restrictions are evaluated against the bundle's URL
instead of to the `uuid-in-package:` URL. See
<a href="https://github.com/WICG/webpackage/issues/651">#651</a> for the
detailed motivation.
## Monkeypatch Does response to request match source list? ## {#monkeypatch-match-response-to-source-list}
Rewrite
<a href="https://w3c.github.io/webappsec-csp/#match-response-to-source-list">Does
|response| to |request| match |source list|?</a> to run these steps:
1. Let |url| be |response|'s [=response/url=].
2. If |url|'s [=url/scheme=] is "`uuid-in-package`", then:
1. Let |registration| be the result of running [=find a matching web bundle
registration=] given |request|.
2. If |registration| is not null, then set |url| to |registration|'s [=web
bundle registration/fetch entry=]'s [=web bundle fetch entry/source=].
3. Returns the result of executing
<a href="https://w3c.github.io/webappsec-csp/#match-url-to-source-list">Does
url match source list in origin with redirect count?</a> on |url|, |source
list|, |policy|'s [=policy/self-origin=], and |request|'s [=request/redirect
count=].
Note: This means that CSP restrictions are evaluated against the bundle's URL
instead of to the `uuid-in-package:` URL. See
<a href="https://github.com/WICG/webpackage/issues/651">#651</a> for the
detailed motivation.
# Algorithms # {#algorithms}
## Parsing ## {#parsing}
To <dfn>parse a web bundle string</dfn>, given a [=string=] |sourceText| and a
[=URL=] |baseURL|:
1. Let |parsed| be the result of [=parse JSON into Infra values|parsing JSON
into Infra values=] given |sourceText|.
1. If |parsed| is not a [=map=], then throw a {{TypeError}} indicating that the
top-level value needs to be a JSON object.
1. If |parsed|["`source`"] does not [=map/exist=], then throw a {{TypeError}}.
1. If |parsed|["`source`"] is not a [=string=], then throw a {{TypeError}}.
1. Let |source| be the result of [=URL parser|parsing=] |parsed|["`source`"]
with |baseURL| as the base URL.
1. If |source| is null, then throw a {{TypeError}}.
1. Let |credentials| be "`same-origin`".
1. If |parsed|["`credentials`"] [=map/exists=], then:
1. If |parsed|["`credentials`"] is "`omit`", then set |credentials| to
"`omit`".
1. Otherwise, if |parsed|["`credentials`"] is "`include`", then set
|credentials| to "`include`".
1. Let |resources| be an empty [=list=].
1. If |parsed|["`resources`"] [=map/exists=], then:
1. If |parsed|["`resources`"] is not a [=list=], then throw a {{TypeError}}.
1. Set |resources| to the result of [=parsing a url list=] given
|parsed|["`resources`"] and |source|.
1. Let |scopes| be an empty [=list=].
1. If |parsed|["`scopes`"] [=map/exists=], then:
1. If |parsed|["`scopes`"] is not a [=list=], then throw a {{TypeError}}.
1. Set |scopes| to the result of [=parsing a url list=] given
|parsed|["`scopes`"] and |source|.
1. If |parsed|'s [=map/get the keys|keys=] [=set/contains=] any items besides
"`source`", "`credentials`", "`resources`" or "`scopes`", [=report a warning
to the console=] that an invalid top-level key was present in the web bundle
string.
Note: This can help detect typos. It is not an error, because that would
prevent any future extensions from being added backward-compatibly.
1. Let |rule| be [=bundle rule=] whose [=bundle rule/resources=] are
|resources| and whose [=bundle rule/scopes=] are |scopes|.
1. Return the [=web bundle parse result=] whose [=web bundle parse
result/source=] is |source|, whose [=web bundle parse result/credentials=]
are |credentials| and whose [=web bundle parse result/rule=] is |rule| .
To <dfn>parse a URL list</dfn>, given a [=list=] |originalList| and a [=URL=]
|baseURL|:
1. Let |parsed URL list| be an empty [=list=].
1. [=list/For each=] |item| of |originalList|,
1. If |item| is a [=string=], then
1. Let |URL| be the result of [=URL parser|parsing=] |item| with |baseURL|
as the base URL.
1. If |URL| is not null, [=list/append=] |URL| to |parsed URL list|.
1. Return |parsed URL list|.
## Fetching a web bundle ## {#fetching-web-bundle}
To <dfn>fetch a web bundle</dfn> given [=web bundle fetch entry=] |fetch entry|
and [=fetch params=] |fetch params|:
1. Assert: |fetch entry|'s [=web bundle fetch entry/state=] is "fetching".
1. Let |request| be |fetch params|'s [=request=].
1. Set |request|'s [=request/url=] to |fetch entry|'s [=web bundle fetch
entry/source=].
Note: Source URL is resolved on document's base URL.
1. Set |request|'s [=request/destination=] to "webbundle",
1. Set |request|'s [=request/mode=] to "cors",
1. Set |request|'s [=request/credentials mode=] to |fetch entry|'s [=web bundle
fetch entry/credentials=].
1. Set |request|'s [=request/service-workers mode=] to "`none`".
1. Append a [=header=], a tuple of ("Accept", "application/webbundle;v=b2"), to
|request|'s [=request/header list=].
Note: The final [[draft-ietf-wpack-bundled-responses-latest]] will use a
version of `1`, but this specification tracks what’s actually implemented in
browsers, which still uses draft versions.
1. [=Fetch=] |request| with [=processResponse=] algorithm set to [=process web
bundle response=] which is partially applied with |fetch entry|.
Note: Chromium's current implementation doesn't allow a nested bundle. A Web
bundle is never fetched from other web bundles.
## Process web bundle response ## {#process-web-bundle-response}
To <dfn id="concept-process-web-bundle-response">process web bundle
response</dfn> given [=web bundle fetch entry=] |fetch entry| and [=response=]
|response|:
1. If |response|'s [=response/status=] is an [=ok status=],
1. Parse |response|'s [=response/body=] as a Web Bundle
([[draft-ietf-wpack-bundled-responses-latest]]).
Note: |response|'s body might not be fully available at this moment. UA
might parse the bundle by [=incrementally reading=] a body asynchronously
in order to serve a subresource as early as possible.
Note: In parsing, Chromium's experimental implementation only accepts "b2"
as a web bundle format version number
([[draft-ietf-wpack-bundled-responses-latest]]).
2. When the parse algorithm asynchronously completes, set |fetch entry|'s
[=web bundle fetch entry/fetched bundle=] to the result of parsing and
|fetch entry|'s [=web bundle fetch entry/state=] be "fetched". If parsing
fails, or any other conformance is violated, set [=web bundle fetch
entry/fetched bundle=] to null and [=web bundle fetch entry/state=] to
"failed".
1. Otherwise, set |fetch entry|'s [=web bundle fetch entry/state=] to "failed".
## Fetching subresources from a web bundle ## {#fetching-subresources}
To <dfn>fetch a subresource from web bundle</dfn> given [=request=]
|httpRequest|:
1. Let |registration| be the result of running [=find a matching web bundle
registration=] given |httpRequest|.
2. If |registration| is not null:
1. Let |response| be the result of [=get response from web bundle fetch
entry=] given |httpRequest|'s [=request/url=] and |registration|'s [=web
bundle registration/fetch entry=].
2. If |response| is null, return a [=network error=].
Note: This means a browser does not fallback to fetch a subresource from
network.
3. Otherwise, return |response|.
3. Return null.
Note: Returning null here can fallback to HTTP cache and ordinal network fetch,
unlike returning a [=network error=] above.
To <dfn>get response from web bundle fetch entry</dfn> given [=url=] |url| and
[=web bundle fetch entry=] |fetch entry|:
1. If |fetch entry|'s [=web bundle fetch entry/state=] is "fetching", await
until [=web bundle fetch entry/state=] becomes "fetched" or "failed"
asynchronously.
2. If |fetch entry|'s [=web bundle fetch entry/state=] is "failed", return null.
3. Assert: |fetch entry|'s [=web bundle fetch entry/fetched bundle=] is
non-null.
4. Returns [=response=] from |fetch entry|'s [=web bundle fetch entry/fetched
bundle=] given |url| ([[draft-ietf-wpack-bundled-responses-latest]]). If a
representation of |url| is not found in [=web bundle fetch entry/fetched
bundle=], return null.
## Finding a matching registration ## {#matching-registration}
To <dfn>find a matching web bundle registration</dfn> given [=request=]
|httpRequest|:
1. Let |url| be |httpRequest|'s [=request/url=].
2. For each |registration| of |httpRequest|'s [=request/client=]'s [=environment
settings object/web bundle registration list=]:
1. Let |rule| be |registration|'s [=web bundle registration/rule=].
2. If |url|'s [=url/scheme=] is not "`uuid-in-package`", then
1. If |url|'s [=url/origin=] and |registration|'s [=web bundle
registration/fetch entry=]'s [=web bundle fetch entry/source=]'s
[=url/origin=] are not [=same origin=], then [=continue=].
1. Let |allowed path| be the result of [=shortening=] |registration|'s
[=web bundle registration/fetch entry=]'s [=web bundle fetch
entry/source=]'s [=url/path=].
1. If |url|'s [=url/path=] doesn't start with |allowed path|, then
[=continue=].
3. If |rule|'s [=bundle rule/resources=] [=list/contains=] |url|, then return
|registration|.
4. If |url| starts with any of |rule|'s [=bundle rule/scopes=], then return
|registration|.
3. Return null.