forked from WICG/fenced-frame
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathspec.bs
2977 lines (2256 loc) · 133 KB
/
spec.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
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<pre class="metadata">
Title: Fenced Frame
Shortname: fenced-frame
Repository: WICG/fenced-frame
Inline Github Issues: true
Group: WICG
Status: CG-DRAFT
Level: 1
URL: https://wicg.github.io/fenced-frame/
Boilerplate: omit conformance, omit feedback-header
Editor: Dominic Farolino, Google https://www.google.com/, [email protected], https://domfarolino.com
Abstract: The fenced frame enforces a boundary between the embedding page and the cross-site embedded document such that user data visible to the two sites is not able to be joined together.
!Participate: <a href="https://github.com/WICG/fenced-frame">GitHub WICG/fenced-frame</a> (<a href="https://github.com/WICG/fenced-frame/issues/new">new issue</a>, <a href="https://github.com/WICG/fenced-frame/issues?state=open">open issues</a>)
!Commits: <a href="https://github.com/WICG/fenced-frame/commits/master/spec.bs">GitHub spec.bs commits</a>
Complain About: accidental-2119 yes, missing-example-ids yes
Indent: 2
Default Biblio Status: current
Markup Shorthands: markdown yes
Assume Explicit For: yes
WPT Display: open
</pre>
<pre class="link-defaults">
spec: url; for:/; type: dfn; text: url
</pre>
<pre class="biblio">
{
"protected-audience": {
"authors": [
"Paul Jensen"
],
"href": "https://wicg.github.io/turtledove/",
"title": "Protected Audience API",
"status": "CG-DRAFT",
"publisher": "WICG",
"deliveredBy": [
"https://wicg.io/"
]
},
"shared-storage": {
"authors": [
"Cammie Barnes"
],
"href": "https://wicg.github.io/shared-storage/",
"title": "Shared Storage API",
"status": "CG-DRAFT",
"publisher": "WICG",
"deliveredBy": [
"https://wicg.io/"
]
},
"prerendering-revamped": {
"authors": [
"Domenic Denicola",
"Dominic Farolino"
],
"href": "https://wicg.github.io/nav-speculation/prerendering.html",
"title": "Prerendering Revamped",
"status": "CG-DRAFT",
"publisher": "WICG",
"deliveredBy": [
"https://wicg.io/"
]
},
"cspee": {
"authors": [
"Mike West"
],
"href": "https://w3c.github.io/webappsec-cspee/",
"title": "Prerendering Revamped",
"status": "CG-DRAFT",
"publisher": "WICG",
"deliveredBy": [
"https://wicg.io/"
]
}
}
</pre>
<pre class="anchors">
urlPrefix: https://www.ietf.org/rfc/rfc4122.txt
type: dfn; text: urn uuid
spec: prerendering-revamped; urlPrefix: https://wicg.github.io/nav-speculation/prerendering.html
type: dfn
for: navigable
text: loading mode; url: #navigable-loading-mode
spec: html; urlPrefix: https://html.spec.whatwg.org/multipage/
type: dfn
urlPrefix: browsers.html
text: check a navigation response's adherence to its embedder policy; url: check-a-navigation-response's-adherence-to-its-embedder-policy
text: queue a cross-origin embedder policy inheritance violation; url: queue-a-cross-origin-embedder-policy-inheritance-violation
text: determine navigation params policy container; url: determining-navigation-params-policy-container
text: cross-origin opener policy enforcement result; url: coop-enforcement-result
for: cross-origin opener policy enforcement result
text: needs a browsing context group switch; url: coop-enforcement-bcg-switch
urlPrefix: dom.html
text: categories; url: concept-element-categories
text: contexts in which this element can be used; url: concept-element-contexts
text: embedded content; url: embedded-content-category
text: content model; url: concept-element-content-model
text: nothing; url: concept-content-nothing
text: content attributes; url: concept-element-attributes
text: global attributes; url: global-attributes
text: dom interface; url: concept-element-dom
text: accessibility considerations; url: concept-element-accessibility-considerations
text: represents; url: represents
urlPrefix: common-dom-interfaces.html
text: reflect; url: reflect
urlPrefix: embedder-content-other.html
text: width; url: attr-dim-width
text: height; url: attr-dim-height
urlPrefix: document-sequences.html
text: browsing context group; url: browsing-context-group
text: browsing context group set; url: browsing-context-group-set
text: creator base url; url: creator-base-url
text: create a new browsing context and document; url: creating-a-new-browsing-context
text: create a new browsing context group and document; url: creating-a-new-browsing-context-group
text: initialize the navigable; url: initialize-the-navigable
text: node navigable; url: node-navigable
text: system visibility state; url: system-visibility-state
for: navigable
text: active session history entry; url: nav-active-history-entry
text: current session history entry; url: nav-current-history-entry
text: parent; url: nav-parent
text: ongoing navigation
for: traversable navigable
text: session history entries; url: tn-session-history-entries
for: browsing context group
text: cross-origin isolation mode; url: bcg-cross-origin-isolation
for: cross-origin isolation mode
text: none; url:cross-origin-isolation-none
urlPrefix: browsing-the-web.html
text: create and initialize a Document object; url: initialise-the-document-object
text: create navigation params by fetching; url: create-navigation-params-by-fetching
text: document state; url: she-document-state
text: historyHandling; url: navigation-hh
text: referrerPolicy; url: navigation-referrer-policy
text: attempt to populate the history entry's document; url: attempt-to-populate-the-history-entry's-document
text: navigation params; url: navigation-params
text: snapshot source snapshot params; url: snapshotting-source-snapshot-params
for: navigation params
text: response; url: navigation-params-response
text: navigable; url: navigation-params-navigable
text: origin; url: navigation-params-origin
text: COOP enforcement result; url: navigation-params-coop-enforcement-result
for: history handling behavior
text: replace; url: hh-replace
for: document state
text: document; url: document-state-document
text: history policy container; url: document-state-history-policy-container
text: initiator origin; url: document-state-initiator-origin
text: checking if unloading is user-canceled
text: source snapshot params
for: source snapshot params
text: fetch client; url: source-snapshot-params-client
text: source policy container; url: source-snapshot-params-policy-container
text: session-history-entry
for: session history entry
text: step; url: she-step
for: source snapshot params
text: has transient activation; url: source-snapshot-params-activation
urlPrefix: interaction.html
text: activation notification; url: activation-notification
text: consume user activation; url: consume-user-activation
text: activation; url: activation
text: click focusable; url: click-focusable
text: focusable area; url: focusable-area
text: sequential focus navigation; url: sequential-focus-navigation
text: focus; url: dom-window-focus
text: focus chain; url: focus-chain
text: focus update steps; url: focus-update-steps
text: focused; url: focused
text: gain focus; url: gains-focus
text: DOM anchor; url: dom-anchor
text: get the focusable area; url: get-the-focusable-area
text: currently focused area of a top-level traversable; url: currently-focused-area-of-a-top-level-traversable
text: focused area; url: focused-area-of-the-document
text: sequential navigation search algorithm; url: sequential-navigation-search-algorithm
urlPefix: infrastructure.html
text: immediately; url: immediately
urlPrefix: nav-history-apis.html
for: Window
text: navigable; url: window-navigable
text: opener; url: dom-opener
urlPrefix: webappapis.html
for: environment
text: target browsing context; url: concept-environment-target-browsing-context
text: navigation and traversal task source
urlPrefix: document-sequences.html
for: browsing context
text: active document; url: active-document
urlPrefix: interactive-elements.html
text: accesskey attribute command; url: using-the-accesskey-attribute-to-define-a-command-on-other-elements
text: previously focused element; url: previously-focused-element
urlPrefix: popover.html
text: hide popover algorithm; url: hide-popover-algorithm
urlPrefix: form-control-infrastructure.html
text: interactively validate the constraints; url: interactively-validate-the-constraints
urlPrefix: custom-elements.html
text: face validation anchor; url: face-validation-anchor
urlPrefix: webappapis.html
text: fire a click event; url: fire-a-click-event
urlPrefix: urls-and-fetching.html
text: about:srcdoc; url: about:srcdoc
spec: fetch; urlPrefix: https://fetch.spec.whatwg.org/
type: dfn
text: queue a cross-origin embedder policy CORP violation report; url: queue-a-cross-origin-embedder-policy-corp-violation-report
text: should request be blocked due to a bad port; url: block-bad-port
for: response
text: has-cross-origin-redirects; url: response-has-cross-origin-redirects
spec: mixed-content; urlPrefix: https://w3c.github.io/webappsec-mixed-content/
type: dfn
text: should fetching request be blocked as mixed content; url: should-block-fetch
spec: RFC8941; urlPrefix: https://www.rfc-editor.org/rfc/rfc8941.html
type: dfn
text: structured header; url: #section-1
for: structured header
text: token; url: name-tokens
spec: permissions-policy; urlPrefix: https://w3c.github.io/webappsec-permissions-policy
type: dfn
text: ASCII-serialized policy directive; url: serialized-policy-directive
text: serialized permissions policy; url: serialized-permissions-policy
text: supported features; url: supported-features
text: declared policy; url: declared-policy
text: the special value *; url: the-special-value
text: permissions policy; url: permissions-policy
for: permissions
text: matches; url: matches
spec: CSP; urlPrefix: https://w3c.github.io/webappsec-csp/
type: dfn
text: directive value; url: directive-value
text: frame-src pre-request check; url: frame-src-pre-request
text: frame-src post-request check; url: frame-src-post-request
text: Get the effective directive for request; url: effective-directive-for-a-request
spec: CSPEE; urlPrefix: https://w3c.github.io/webappsec-cspee/
type: dfn
text: Is response to request blocked by context's required CSP?; url: process-response
text: required csp; url: browsing-context-required-csp
spec: permissions-policy; urlPrefix: https://w3c.github.io/webappsec-permissions-policy
type: dfn
for: permissions policy
text: inherited policy; url: inherited-policy
spec: css2; urlPrefix: https://www.w3.org/TR/CSS21/visuren.html
type: dfn
for: css2
text: viewport; url: viewport
</pre>
<style>
/* Put nice boxes around each algorithm. */
[data-algorithm]:not(.heading) {
padding: .5em;
border: thin solid #ddd; border-radius: .5em;
margin: .5em calc(-0.5em - 1px);
}
[data-algorithm]:not(.heading) > :first-child {
margin-top: 0;
}
[data-algorithm]:not(.heading) > :last-child {
margin-bottom: 0;
}
[data-algorithm] [data-algorithm] {
margin: 1em 0;
}
.selected-text-file-an-issue {
position: fixed;
bottom: 0;
right: 0;
background: rgba(255, 255, 255, 0.8);
font-size: smaller;
padding: 4px 10px;
z-index: 4;
}
dfn var {
font-style: italic;
}
table {
margin: 1em 0;
}
/* WHATWG-style <hr>s, instead of WICG-style. Specific selector is necessary to override WICG styles. */
:not(.head) > :not(.head) + hr {
display: block;
background: none;
border: none;
padding: 0;
margin: 3em 0;
height: auto;
}
:not(.head) > :not(.head) + hr::before {
content: none;
}
/* WHATWG-style element definition class */
.element {
background: #EEFFEE;
}
dt {
margin-top: 12px;
color: black;
}
dl, dd {
padding-left: .5em;
}
/* domintro from https://resources.whatwg.org/standard.css */
.domintro {
position: relative;
color: green;
background: #DDFFDD;
margin: 2.5em 0 2em 0;
padding: 1.5em 1em 0.5em 2em;
}
.domintro dt, .domintro dt * {
color: black;
font-size: inherit;
}
.domintro dd {
margin: 0.5em 0 1em 2em; padding: 0;
}
.domintro dd p {
margin: 0.5em 0;
}
.domintro::before {
content: 'For web developers (non-normative)';
background: green;
color: white;
padding: 0.15em 0.25em;
font-style: normal;
position: absolute;
top: -0.8em;
left: -0.8em;
}
/* .XXX from https://resources.whatwg.org/standard.css */
.XXX {
color: #D50606;
background: white;
border: solid #D50606;
}
</style>
<script src="https://resources.whatwg.org/file-issue.js" async></script>
<h2 id=introduction>Introduction</h2>
*This section is non-normative.*
In a web that has its cookies and storage partitioned by top-frame site, there are occasions — such
as interest group based advertising as provided by the [[Protected-Audience]] API, or [Conversion
Lift
Measurements](https://github.com/w3c/web-advertising/blob/main/support_for_advertising_use_cases.md#conversion-lift-measurement))
— when it would be useful to display content from different partitions in the same page. This can
only be done in a privacy-preserving way if the {{Document}}s that contain data from different
partitions are isolated from each other, unable to communicate despite being re visually composed on
the same page. <{iframe}> elements are not suitable for this, since they offer many intentional
communication channels with their embedder. This specification introduces the <{fencedframe}>
element, a new element to embed {{Document}}s on a page that explicitly prevents communication
between the {{Document}} and its embedder.
This specification defines the new element, its integration with the rest of the web platform,
including [[#html-integration]] and [[#interaction-with-other-specs]], and its supporting primitives
like {{FencedFrameConfig}}, which is the major input to the <{fencedframe}> in place of normal
[=URLs=] and "`src`" attributes. Given that this specification defines a new element and its
integration with the rest of the platform, it should be read as largely a monkeypatch to the
[[HTML]], with its end goal to be merged into that standard, provided there is adequate
cross-browser support.
<h2 id=the-fencedframe-element>The <dfn element export>fencedframe</dfn> element</h2>
<dl class="element">
<dt>[=Categories=]:</dt>
<dd>[=Flow content=].</dd>
<dd>[=Phrasing content=].</dd>
<dd>[=Embedded content=].</dd>
<dd>[=Interactive content=].</dd>
<dd>[=Palpable content=].</dd>
<dt>[=Contexts in which this element can be used=]:</dt>
<dd>Where [=embedded content=] is expected.</dd>
<dt>[=Content model=]:</dt>
<dd>[=Nothing=].</dd>
<dt>[=Content attributes=]:</dt>
<dd>[=Global attributes=]</dd>
<dd><code>[=width=]</code> — Horizontal dimension</dd>
<dd><code>[=height=]</code> — Vertical dimension</dd>
<dd><code><{fencedframe/allow}></code> — [=Permissions policy=] to be applied to the <{fencedframe}>'s contents</dd>
<dt>[=Accessibility considerations=]:</dt>
<dd><p class=XXX>TODO</p></dd>
<dt>[=DOM interface=]:</dt>
<dd>
<xmp class=idl>
[Exposed=Window]
interface HTMLFencedFrameElement : HTMLElement {
[HTMLConstructor] constructor();
[CEReactions] attribute FencedFrameConfig? config;
[CEReactions] attribute DOMString width;
[CEReactions] attribute DOMString height;
[CEReactions] attribute DOMString allow;
};
</xmp>
</dd>
</dl>
The <{fencedframe}> element [=represents=] its [=fenced navigable container/fenced navigable=].
Descendants of <{fencedframe}> elements represent nothing.
Each <{fencedframe}> has a <dfn for=fencedframe>config</dfn>, which is either a
{{FencedFrameConfig}} or null. It is initially null.
<div algorithm=insertion>
When a <{fencedframe}> element |element| is [=node is inserted into a document|inserted into a
document=] whose [=Document/browsing context=] is non-null, run these steps:
1. Let |nested traversable| be the result of [=create a new nested traversable|creating a new
nested traversable=] for |element|.
1. Set |nested traversable|'s [=navigable/loading mode=] to "`fencedframe`".
1. <span class=XXX>Parse the sandbox attributes, once it exists</span>
Issue: It's not necessary to call the <a
href=https://html.spec.whatwg.org/multipage/browsing-the-web.html#url-and-history-update-steps>URL
and history update steps</a> as we do during usual <a
href=https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-iframe-element:url-and-history-update-steps>child
navigable creation</a> or <a
href=https://html.spec.whatwg.org/multipage/nav-history-apis.html#apis-for-creating-and-navigating-browsing-contexts-by-name:url-and-history-update-steps>top-level
traversable creation</a>, but we still need a mechanism to initialize
{{History}}.{{History/length}} in the new navigable. This is an existing issue in the HTML
Standard: <a
href=https://github.com/whatwg/html/issues/9030>https://github.com/whatwg/html/issues/9030</a>.
</div>
<div algorithm=destroy>
When a <{fencedframe}> element is [=removed from a document=], the user agent <p class=XXX>TODO:
destroy the nested traversable</p>.
</div>
The <dfn attribute for=HTMLFencedFrameElement>config</dfn> IDL attribute getter steps are to return
[=this=]'s [=fencedframe/config=].
<div algorithm=config-setter>
The {{HTMLFencedFrameElement/config}} IDL attribute setter steps are:
1. If [=this=] is not [=connected=]:
1. [=Assert=]: [=this=]'s [=fenced navigable container/fenced navigable=] is null.
Note: This holds because when the element has been removed from the DOM, its removal steps
immediately destroy the [=fenced navigable container/fenced navigable=].
1. Let |urn uuid| be the given {{FencedFrameConfig}}'s [=fencedframeconfig/urn=].
1. Let |shared storage context| be the given {{FencedFrameConfig}}'s [=fencedframeconfig/
sharedStorageContext=].
1. [=Navigate=] |element|'s [=fenced navigable container/fenced navigable=] to |urn uuid| using
|element|'s [=Node/node document=], with [=historyHandling=] set to "<a for="history handling
behavior">`replace`</a>", [=referrerPolicy=] set to <a>"`no-referrer`"</a>, and
|shared storage context|.
Note: See [[#navigation-changes]] for the <{fencedframe}>-specific changes to the ordinary
navigation flow.
<wpt>
/fenced-frame/header-referrer.https.html
</wpt>
</div>
The <dfn element-attr for=fencedframe>allow</dfn> attribute, when specified, determines the
[=container policy=] that will be used when the [=Document/permissions policy=] for a {{Document}}
in the <{fencedframe}>'s [=fenced navigable container/fenced navigable=] is initialized. Its value
must be a [=serialized permissions policy=]. [[!PERMISSIONS-POLICY]]
The IDL attribute <dfn attribute for=HTMLFencedFrameElement>allow</dfn> must [=reflect=] the
respective content attribute of the same name.
<h3 id=dimension-attributes>Dimension attributes</h3>
This section details monkeypatches to [[!HTML]]'s <a
href="https://html.spec.whatwg.org/multipage/embedded-content-other.html#dimension-attributes">Dimension
attributes</a> section. That section will be updated to include <{fencedframe}> in the list of
elements whose own <dfn element-attr for=fencedframe>width</dfn> and <dfn element-attr
for=fencedframe>height</dfn> dimension attributes have the same author requirements that apply to
the general <code>[=width=]</code> and <code>[=height=]</code> dimension attributes defined in
[[HTML]].
Furthermore, the IDL attributes <dfn attribute for=HTMLFencedFrameElement>width</dfn> and <dfn
attribute for=HTMLFencedFrameElement>height</dfn> must [=reflect=] the respective content attributes
of the same name.
<h3 id=fenced-frame-config-map>Fenced frame config mapping</h3>
Each [=traversable navigable=] has a <dfn for="traversable navigable" export>fenced frame config
mapping</dfn>, which is a [=fenced frame config mapping=].
Note: This mapping is consulted during [=navigate|navigation=], and written to by what we
colloquially refer to as *URN-generating APIs* or *config-generating APIs*, that generate both [=urn
uuids=] and [=fenced frame configs=] for use in navigating <{fencedframe}> and <{iframe}> elements.
See for example, the [[Protected-Audience]] API and [[Shared-Storage]] specifications.
A <dfn>fenced frame config mapping</dfn> has three submappings:
<dl dfn-for="fenced frame config mapping">
: <dfn>pending config mapping</dfn>
:: a [=map=] whose [=map/keys=] are [=urn uuids=] and whose [=map/values=] are [=fenced frame
configs=]
: <dfn>finalized config mapping</dfn>
:: a [=map=] whose [=map/keys=] are [=urn uuids=] and whose [=map/values=] are [=fenced frame
configs=]
: <dfn>nested config mapping</dfn>
:: a [=map=] whose [=map/keys=] are [=urn uuids=] and whose [=map/values=] are [=fenced frame
configs=]
</dl>
Note: The purpose of pending configs is to enable config-generating APIs to resolve configs
asynchronously in a way that doesn't create timing side channels, i.e., the pending config is
returned to the web platform in a constant amount of time, before any computation whose duration
depends on cross-site data. Because the privacy of this depends on the web platform not being able
to discern when a pending config is finalized, it is important that all visibilities and values of
transparent fields do not change from the pending config to the finalized config, given that they
can be inspected through {{FencedFrameConfig}}'s getters. Therefore, a {{FencedFrameConfig}} that is
created and exposed to the web platform is effectively immutable even if the [=fenced frame config=]
represented by the [=fencedframe/config=]'s [=fencedframeconfig/urn=] is technically "pending", and
will finish resolving completely later.
Each [=fenced frame config mapping=] has a <dfn for="fenced frame config mapping">maximum number of
configs</dfn>, which is implementation-defined. The [=fenced frame config mapping/maximum number of
configs=] may be a non-negative number or infinity.
Note: It is important to specify the behavior of
[=fenced frame config mapping/maximum number of configs=] because its semantics can interact with
config-generating APIs in a privacy sensitive way.
At a high level, in order to store a [=fenced frame config=] in the
[=traversable navigable/fenced frame config mapping=], the creator of the config must first store a
pending config, and then turn the pending config into a finalized config. Those procedures are as
follows:
<div algorithm>
To <dfn for="fenced frame config mapping" export>store a pending config</dfn> in a [=fenced frame
config mapping=] |mapping| given a [=fenced frame config=] |config|, run these steps:
1. Let |pendingMapping| be |mapping|'s [=fenced frame config mapping/pending config mapping=].
1. If the [=map/size=] of |pendingMapping| + the [=map/size=] of |mapping|'s [=fenced frame config
mapping/finalized config mapping=] ≥ |mapping|'s [=fenced frame config mapping/maximum number
of configs=], return failure.
1. Let |urn| be a randomly generated [=urn uuid=].
1. [=Assert=]: |urn| does not [=map/exist=] in |pendingMapping|.
1. [=map/Set=] |pendingMapping|[|urn|] to |config|.
1. Return |urn|.
</div>
<div algorithm>
To <dfn for="fenced frame config mapping" export>finalize a pending config</dfn> in a [=fenced
frame config mapping=] |mapping| given a [=urn uuid=] |urn| and [=fenced frame config=]
|config|, run these steps:
1. Let |pendingMapping| be |mapping|'s [=fenced frame config mapping/pending config mapping=].
1. Let |finalizedMapping| be |mapping|'s [=fenced frame config mapping/finalized config mapping=].
1. If |pendingMapping|[|urn|] does not [=map/exist=], return failure.
1. [=map/Remove=] |pendingMapping|[|urn|].
1. [=map/Set=] |finalizedMapping|[|urn|] to |config|.
</div>
<div algorithm>
To <dfn for="fenced frame config mapping" export>store nested configs</dfn> in a [=fenced frame
config mapping=] |mapping| given a [=fenced frame config instance/nested configs=]
|nestedConfigs|, run these steps:
1. Let |nestedMapping| be |mapping|'s [=fenced frame config mapping/nested config mapping=].
1. If |nestedConfigs| is null, return.
1. [=map/iterate|For each=] |urn| → |config| of |nestedConfigs|:
1. [=map/Set=] |nestedMapping|[|urn|] to |config|.
</div>
<div algorithm>
To <dfn for="fenced frame config mapping" export>find a config</dfn> in a [=fenced frame config
mapping=] |mapping| given a [=urn uuid=] |urn|, run these steps:
1. Let |nestedMapping| be |mapping|'s [=fenced frame config mapping/nested config mapping=].
1. Let |pendingMapping| be |mapping|'s [=fenced frame config mapping/pending config mapping=].
1. Let |finalizedMapping| be |mapping|'s [=fenced frame config mapping/finalized config mapping=].
1. If |nestedMapping|[|urn|] [=map/exists=], return its value.
1. If |pendingMapping|[|urn|] [=map/exists=], wait until it does not [=map/exist=].
1. If |finalizedMapping|[|urn|] [=map/exists=], return its value.
1. Return failure.
</div>
<h3 id=fenced-frame-config-section>Fenced frame configs</h3>
<h4 id=fenced-frame-config-intro>Introduction</h4>
*This section is non-normative.*
A key feature of the <{fencedframe}> element is that web platform APIs can configure the behavior
of the frame in a way that limits the ability of other execution contexts to modify or inspect this
configuration, for security and privacy reasons. For example, the [[Protected-Audience]] API
performs on-device ad auctions over cross-site data, and it is important that the ad that wins the
auction can be loaded into a frame, without the API caller knowing *which ad* won the auction or
being able to manipulate the environment in which the ad loads.
We achieve this using the concept of a "[=fenced frame config=]". A [=fenced frame config=] is a
collection of fields that can be loaded into <{fencedframe}> elements and that specifies the
resulting environments. [=Fenced frame configs=] can only be created by specific web platform APIs,
and not constructed or modified by script. Their fields also contain "[=visibilities=]", which
dictate whether the field should be "redacted" when inspected through the {{FencedFrameConfig}}
interface. Config-generating APIs like the [[Protected-Audience]] and [[Shared-Storage]] APIs must
specify values for all fields of their [=fenced frame configs=] in order to ensure that they have
considered the privacy implications of each field, though they may choose to set the values to null.
Each time a <{fencedframe}> navigates to a [=fenced frame config=], it is instantiated as a new
[=fenced frame config instance=], which governs the particular [=browsing context group=] inside the
[=fenced navigable container/fenced navigable=].
<h4 id=fenced-frame-config-struct>The [=fenced frame config=] [=struct=]</h4>
We now establish some preliminary types:
A <dfn export for=fencedframeconfig>visibility</dfn> is either "<dfn export
for=visibility>`opaque`</dfn>" or "<dfn export for=visibility>`transparent`</dfn>".
A <dfn export for=fencedframetype>size</dfn> is a [=struct=] with the following [=struct/items=]:
<dl export dfn-for="size">
: <dfn>width</dfn>
:: a non-negative integer
: <dfn>height</dfn>
:: a non-negative integer
</dl>
<span class=XXX>TODO: Consider different numeric types for these members.</span>
An <dfn export for=fencedframetype>interest group descriptor</dfn> is a [=struct=] with the
following [=struct/items=]:
<dl export dfn-for="interest group descriptor">
: <dfn>owner</dfn>
:: an [=origin=]
: <dfn>name</dfn>
:: a [=string=]
</dl>
An <dfn export for=fencedframetype>exhaustive set of sandbox flags</dfn> is a [=sandboxing flag
set=].
A <dfn export for=fencedframetype>pending event</dfn> is a [=struct=] with the following
[=struct/items=]:
<dl export dfn-for="pending event">
: <dfn>destination</dfn>
:: a {{FenceReportingDestination}}
: <dfn>event</dfn>
:: a [=fencedframetype/destination event=]
</dl>
A <dfn export for=fencedframetype>reporting destination info</dfn> is a [=struct=] with the
following [=struct/items=]:
<dl export dfn-for="reporting destination info">
: <dfn>reporting url map</dfn>
:: a [=map=] whose [=map/keys=] are [=strings=] and whose [=map/values=] are [=URLs=]
: <dfn>reporting macro map</dfn>
:: null, or a [=map=] whose [=map/keys=] are [=strings=] and whose [=map/values=] are [=strings=]
</dl>
A <dfn export for=fencedframetype>fenced frame reporting map</dfn> is a [=map=] whose [=map/keys=]
are {{FenceReportingDestination}}s and whose [=map/values=] are either:
* [=lists=] of [=fencedframetype/pending events=] (which are used to represent events that need to
be reported asynchronously, because the metadata has not been finalized yet); or
* [=fencedframetype/reporting destination infos=] (which are used
to represent the actual metadata once it is finalized).
Note: This representation is meant to allow config-generating APIs to reduce latency by resolving
the values of reporting destinations asynchronously, after they've already constructed and returned
the fenced frame config (and even after the config has been loaded, and event reports have been
generated inside the fenced frame). When the config-generating API declares the [=fencedframetype/
fenced frame reporting map=], they can mark certain destinations as pending using an empty
[=list=], and then maintain a reference to the map for later. If the fenced frame attempts to
[=report an event=] to a destination while it is still pending, it stores the event in this
[=list=] for later handling. When the config-generating API or its callback eventually [=finalizes
a reporting destination=] through the reference it kept, it will handle all of the pending events
stored in the [=list=]. If the destination is never finalized, then the pending events will never
be sent.
<div algorithm>
In order to <dfn export>finalize a reporting destination</dfn>, given a [=fencedframetype/fenced
frame reporting map=] |reporting map|, a {{FenceReportingDestination}} |destination|, a [=map=]
|destination map| whose [=map/keys=] are [=strings=] and whose [=map/values=] are [=urls=], and
|macro map|, which is either null or a [=map=] whose [=map/keys=] are [=strings=] and whose
[=map/values=] are [=strings=], run these steps:
1. [=Assert=] that |reporting map|[|destination|] is a [=list=] (i.e., that |destination|'s
metadata has not yet been finalized).
1. Let |pending event list| be |reporting map|[|destination|].
1. [=map/Set=] |reporting map|[|destination|] to a [=struct=] with the following [=struct/items=]:
: [=reporting destination info/reporting url map=]
:: |destination map|
: [=reporting destination info/reporting macro map=]
:: |macro map|
1. [=list/For each=] |pending event| of |pending event list|:
1. [=Send a beacon=] with |destination map| and |pending event|'s [=pending event/event=].
</div>
A <dfn export for=fencedframetype>fenced frame reporting metadata</dfn> is a [=struct=] with the
following [=struct/items=]:
<dl export dfn-for="fenced frame reporting metadata">
: <dfn>fenced frame reporting map</dfn>
:: a [=fencedframetype/fenced frame reporting map=]
: <dfn>direct seller is seller</dfn>
:: a [=boolean=], initially true
: <dfn>allowed reporting origins</dfn>
:: null or a [=list=] of [=origins=]. An origin must be present in this list to be the
destination of a [=fencedframetype/destination URL event=] report.
: <dfn>attempted custom url report to disallowed origin</dfn>
:: a [=boolean=], initially false
</dl>
A <dfn export for=fencedframetype>fenced frame reporter</dfn> is a [=struct=] with the following
[=struct/items=]:
<dl export dfn-for="fenced frame reporter">
: <dfn>fenced frame reporting metadata reference</dfn>
:: a mutable reference to a [=fencedframetype/fenced frame reporting metadata=]
<span class=XXX>TODO: Handle pointers/references in a more spec-y way</span>
: <dfn>automatic beacon data</dfn>
:: null, or a [=struct=] with the following [=struct/items=]:
<dl dfn-for="automatic beacon data">
: <dfn>eventData</dfn>
:: a [=string=]
: <dfn>destination</dfn>
:: a [=list=] of {{FenceReportingDestination}}s
: <dfn>once</dfn>
:: a [=boolean=]
</dl>
</dl>
A <dfn export for=fencedframetype>destination enum event</dfn> is a [=struct=] with the following
[=struct/items=]:
<dl export dfn-for="destination enum event">
: <dfn>type</dfn>
:: a [=string=]
: <dfn>data</dfn>
:: a [=string=]
</dl>
A <dfn export for=fencedframetype>destination URL event</dfn> is a [=URL=].
A <dfn export for=fencedframetype>destination event</dfn> is either a
[=fencedframetype/destination enum event=] or a [=fencedframetype/destination URL event=].
<div algorithm>
In order to <dfn>send a beacon</dfn> with a [=fencedframetype/reporting destination info=]
|destination info| and a [=fencedframetype/destination event=] |event|, run these steps:
1. Let |destination url| be an empty [=string=].
1. If |event| is a [=fencedframetype/destination enum event=], then:
1. Let |destination map| be |destination info|'s
[=reporting destination info/reporting url map=].
1. Let |eventType| be |event|'s [=destination enum event/type=].
1. If |destination map|[|eventType|] does not [=map/exist=], return.
1. Set |destination url| to |destination map|[|eventType|].
1. Otherwise:
1. [=Assert=]: |event| is a [=fencedframetype/destination URL event=].
1. Let |macro map| be |destination info|'s [=reporting destination info/reporting macro map=].
1. If |macro map| is null, return.
1. Set |destination url| to |event|.
1. Let |destination url| be the result of [=fencedframeutil/substituting macros=] with
|macro map| into |destination url|.
1. Optionally, return.
Note: This [=implementation-defined=] condition is intended to allow user agents to drop the
beacon for a number of reasons, for example user opt-out or |destination url|'s [=site=] not
being <a href="https://github.com/privacysandbox/attestation">enrolled</a>.
1. Let |request| be a new [=request=] with the following properties:
: [=request/method=]
:: <code>`POST`</code> if |event| is a [=fencedframetype/destination enum event=], otherwise
<code>`GET`</code>.
: [=request/URL=]
:: |destination url|
: [=request/header list=]
:: A new [=header list=] containing a [=header=] whose [=header/name=] is `"Content-Type"` and
[=header/value=] is `"text/plain"`.
: [=request/body=]
:: If |event| is a [=fencedframetype/destination enum event=], a [=body=] whose [=body/source=]
is |event|'s [=destination enum event/data=], otherwise null.
: [=request/client=]
:: null
: [=request/service-workers mode=]
:: `"all"`
Issue: The default is `"all"`, so we technically don't have to set anything here. We do in order
to remind ourselves that it might be more appropriate to skip service workers here, like some
[other
beacons](https://wicg.github.io/attribution-reporting-api/#ref-for-request-service-workers-mode).
: [=request/origin=]
:: <span class=XXX>Get the origin from somewhere, like the [implementation
does](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:content/browser/fenced_frame/fenced_frame_reporter.cc;l=384;drc=183dd920ea5d6aed92e007c40e226f1f840c0567)</span>.
: [=request/referrer=]
:: `"no-referrer"`
: [=request/mode=]
:: `"cors"`
: [=request/credentials mode=]
:: `"omit"`
1. [=Fetch=] |request|.
Note: This algorithm can be invoked from while [=in parallel=] or while on a {{Document}}'s main
thread. To handle the [=in parallel=] invocation correctly, ordinarily we would invoke [=fetch=]
with [=fetch/useParallelQueue=] set to true, but since we don't pass in any of the <span
class=allow-2119>optional</span> [=response=]-handling algorithms, there is no need to do this.
</div>
<div algorithm>
In order to <dfn>report an event</dfn> using a [=fencedframetype/fenced frame reporter=]
|reporter| with a {{FenceReportingDestination}} |destination|, and a
[=fencedframetype/destination event=] |event|, run these steps:
1. Let |metadata| be |reporter|'s
[=fenced frame reporter/fenced frame reporting metadata reference=].
1. If |destination| is `"direct-seller"`:
1. If |metadata|'s [=fenced frame reporting metadata/direct seller is seller=] is true, set
|destination| to `"seller"`.
1. Otherwise, set |destination| to `"component-seller"`.
1. If |event| is a [=fencedframetype/destination URL event=]:
1. If |event|'s [=url/origin=] is not [=same origin=] with any of the entries in
|metadata|'s [=fenced frame reporting metadata/allowed reporting origins=]:
1. Set |metadata|'s
[=fenced frame reporting metadata/attempted custom url report to disallowed origin=] to
true.
1. If |metadata|'s
[=fenced frame reporting metadata/attempted custom url report to disallowed origin=] is
true, return.
1. Let |reporting map| be a reference to |metadata|'s
[=fenced frame reporting metadata/fenced frame reporting map=].
1. If |reporting map|[|destination|] does not [=map/exist=], return.
1. If |reporting map|[|destination|] is a [=list=]:
1. Let |newEvent| be a new [=fencedframetype/pending event=] with the following:
: [=pending event/destination=]
:: |destination|
: [=pending event/event=]
:: |event|
1. [=list/Append=] |newEvent| to |reporting map|[|destination|].
1. Return.
Note: The pending event will be sent asynchronously.
1. [=Assert=] that |reporting map|[|destination|] is a [=map=] (i.e. that |destination|'s
metadata has been finalized).
1. [=Send a beacon=] with |reporting map|[|destination|] and |event|.
</div>
<div algorithm>
In order to <dfn>report a private aggregation event</dfn> using a [=fencedframetype/fenced frame
reporter=] |reporter| with a [=string=] |event|, run these steps:
1. |reporter| |event| <span class=XXX>TODO: Fill this in</span>
</div>
An <dfn export for=fencedframetype>exfiltration budget metadata</dfn> is a [=struct=] with the
following [=struct/items=]:
<dl export dfn-for="exfiltration budget metadata">
: <dfn>origin</dfn>
:: an [=origin=]
: <dfn>amount to debit</dfn>
:: a non-negative valid floating point number
</dl>
An <dfn export for=fencedframetype>exfiltration budget metadata reference</dfn> is a [=struct=] with
the following [=struct/items=]:
<dl export dfn-for="exfiltration budget metadata reference">
: <dfn>origin</dfn>
:: an [=origin=]
: <dfn>amount to debit reference</dfn>
:: a mutable reference to a non-negative valid floating point number
<span class=XXX>TODO: Handle pointers/references in a more specy-y way</span>
</dl>
A <dfn export>partition nonce</dfn> is an [=implementation-defined=] value.
Note: This is similar to the <a href=https://fetch.spec.whatwg.org/#network-partition-key>network
partition key</a> used by <a href=https://fetch.spec.whatwg.org/>Fetch</a>.
A <dfn export>fenced frame config</dfn> is a [=struct=] with the following [=struct/items=]:
<dl export dfn-for="fenced frame config">
: <dfn>mapped url</dfn>
:: a [=struct=] with the following [=struct/items=]:
: <dfn for="mapped url">value</dfn>
:: a [=URL=]
: <dfn for="mapped url">visibility</dfn>
:: a [=fencedframeconfig/visibility=]
: <dfn>container size</dfn>
:: null, or a [=fencedframetype/size=]
: <dfn>content size</dfn>
:: null, or a [=struct=] with the following [=struct/items=]:
: <dfn for="content size">value</dfn>
:: a [=fencedframetype/size=]
: <dfn for="content size">visibility</dfn>
:: a [=fencedframeconfig/visibility=]
: <dfn>interest group descriptor</dfn>
:: null, or a [=struct=] with the following [=struct/items=]:
: <dfn for="interest group descriptor">value</dfn>
:: an [=fencedframetype/interest group descriptor=]
: <dfn for="interest group descriptor">visibility</dfn>
:: a [=fencedframeconfig/visibility=]
: <dfn>on navigate callback</dfn>
:: null, or a series of steps
: <dfn>effective sandbox flags</dfn>
:: null, or a [=struct=] with the following [=struct/items=]: