1. Introduction
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)
— 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 § 3 HTML Integration and § 4 Interactions with other specifications, 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.
2. The fencedframe
element
- Categories:
- Flow content.
- Phrasing content.
- Embedded content.
- Interactive content.
- Palpable content.
- Phrasing content.
- Contexts in which this element can be used:
- Where embedded content is expected.
- Content model:
- Nothing.
- Content attributes:
- Global attributes
width
— Horizontal dimensionheight
— Vertical dimension
— Permissions policy to be applied to theallow
fencedframe
's contents - Accessibility considerations:
-
TODO
- DOM interface:
-
[
Exposed =Window ]interface
:HTMLFencedFrameElement HTMLElement { [HTMLConstructor ]
(); [constructor CEReactions ]attribute FencedFrameConfig ?config ; [CEReactions ]attribute DOMString width ; [CEReactions ]attribute DOMString height ; [SameObject ,PutForwards =value ]readonly attribute DOMTokenList sandbox ; [CEReactions ]attribute DOMString allow ; };
The fencedframe
element represents its fenced navigable.
Descendants of fencedframe
elements represent nothing.
Each fencedframe
has a config, which is either a FencedFrameConfig
or null. It is initially null.
Each fencedframe
has a fencedframe sandboxing flag set, which is a sandboxing flag set. Which flags in a fencedframe sandboxing flag set are set
at any particular time is determined by the fencedframe
element’s sandbox
attribute.
-
If embedder is an
iframe
element, then: the flags set on embedder’s iframe sandboxing flag set. -
If embedder is a
fencedframe
element, then: the flags set on embedder’s fencedframe sandboxing flag set.
fencedframe
element element is inserted into a
document whose browsing context is non-null, run these steps:
-
Let nested traversable be the result of creating a new nested traversable for element.
-
Set nested traversable’s loading mode to "
fencedframe
". -
If element has a
sandbox
attribute, then parse a sandboxing directive given the attribute’s value and element’s fencedframe sandboxing flag set.
It’s not necessary to call the URL
and history update steps as we do during usual child
navigable creation or top-level
traversable creation, but we still need a mechanism to initialize History
.length
in the new navigable. This is an existing issue in the HTML
Standard: https://github.com/whatwg/html/issues/9030.
fencedframe
element is removed from a document, the user agent
TODO: destroy the nested traversable
.The config
IDL attribute getter steps are to return this's config.
config
IDL attribute setter steps are:
-
-
Assert: this's 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.
-
-
Let navigation url or urn be the given
FencedFrameConfig
's url if the givenFencedFrameConfig
's url is not null, and the givenFencedFrameConfig
's urn otherwise. -
If navigation url or urn is failure, then return.
-
Let shared storage context be the given
FencedFrameConfig
's sharedStorageContext. -
Navigate element’s fenced navigable to navigation url or urn using element’s node document, with historyHandling set to "
replace
", referrerPolicy set to "no-referrer
", and shared storage context.Note: See § 3.8.5 Actual navigation changes for the
fencedframe
-specific changes to the ordinary navigation flow.
The allow
attribute, when specified, determines the container policy that will be used when the permissions policy for a Document
in the fencedframe
's fenced navigable is initialized. Its value
must be a serialized permissions policy. [PERMISSIONS-POLICY]
The sandbox
attribute, when specified, enables a set of
extra restrictions on any content hosted by the fencedframe
. Its value must be an unordered
set of unique space-separated tokens that are ASCII case-insensitive. The allowed values are:
The IDL attributes allow
and sandbox
must reflect the respective content attribute of the
same name.
The supported tokens for sandbox
's DOMTokenList
are the allowed
values defined in the sandbox
attribute and supported by the user agent.
fencedframe
elements:
-
Assert: namespace is the HTML namespace.
-
If localName is
sandbox
, then:-
If value is null, then empty element’s fencedframe sandboxing flag set.
-
Otherwise, run parse a sandboxing directive given the value and element’s fencedframe sandboxing flag set.
-
2.1. Dimension attributes
This section details monkeypatches to [HTML]'s Dimension
attributes section. That section will be updated to include fencedframe
in the list of
elements whose own width
and height
dimension attributes have the same author requirements that apply to
the general width
and height
dimension attributes defined in [HTML].
Furthermore, the IDL attributes width
and height
must reflect the respective content attributes
of the same name.
2.2. Fenced frame config mapping
Each traversable navigable has a fenced frame config mapping, which is a fenced frame config mapping.
Note: This mapping is consulted during 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 fenced frame config mapping has three submappings:
- pending config mapping
-
a map whose keys are urn uuids and whose values are fenced frame configs
- finalized config mapping
-
a map whose keys are urn uuids and whose values are fenced frame configs
- nested config mapping
-
a map whose keys are urn uuids and whose values are fenced frame configs
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 config's urn is technically "pending", and
will finish resolving completely later.
Each fenced frame config mapping has a maximum number of configs, which is implementation-defined. The maximum number of configs may be a non-negative number or infinity.
Note: It is important to specify the behavior of 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 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:
-
Let pendingMapping be mapping’s pending config mapping.
-
If the size of pendingMapping + the size of mapping’s finalized config mapping ≥ mapping’s maximum number of configs, return failure.
-
Let urn be a randomly generated urn uuid.
-
Set pendingMapping[urn] to config.
-
Return urn.
-
Let pendingMapping be mapping’s pending config mapping.
-
Let finalizedMapping be mapping’s finalized config mapping.
-
If pendingMapping[urn] does not exist, return failure.
-
Remove pendingMapping[urn].
-
Set finalizedMapping[urn] to config.
-
Let nestedMapping be mapping’s nested config mapping.
-
If nestedConfigs is null, return.
-
For each urn → config of nestedConfigs:
-
Set nestedMapping[urn] to config.
-
Set nestedMapping[urn]'s is ad component to true.
-
-
Let nestedMapping be mapping’s nested config mapping.
-
Let pendingMapping be mapping’s pending config mapping.
-
Let finalizedMapping be mapping’s finalized config mapping.
-
If nestedMapping[urn] exists, return its value.
-
If pendingMapping[urn] exists, wait until it does not exist.
-
If finalizedMapping[urn] exists, return its value.
-
Return failure.
2.3. Fenced frame configs
2.3.1. Introduction
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.
2.3.2. Use cases
Rendering an ad created through an ad auction:
An ad auction API runs an auction and determines a winning ad. Details about the winning ad must be
hidden from the embedder, and the embedding context is not allowed to influence the environment of
the fencedframe
. Either of those would allow for information to flow across the fenced frame
boundary, which can allow for colluding parties to join cross-site data and build a profile on the
user. To prevent that, the ad auction API constructs a fenced frame config whose underlying URL is opaque to the
embedding context. The fenced frame config is also constructed with restrictions on what the container size and content size of the frame must
be and what the permissions policy of the
frame must be, as those can be used as fingerprinting vectors.
Displaying a personalized payment button:
An e-commerce site embeds a fencedframe
that has a "Pay now" button. The e-commerce site stores
information about the user’s credit card on the browser as first-party storage. At first, the Document
hosted in the fencedframe
has no first-party cookie/storage access, so information
can freely flow in and out without risk of the credit card information being joined with cross-site
data. Because of that, the fenced frame can be constructed directly from the web platform using the FencedFrameConfig
constructor without compromising privacy. The button at this point has no
personalized data in it since it can’t access the credit card data yet. The Document
can only
read that credit card data once it turns off all network access, preventing the data from flowing
out of the fenced frame and preventing it from being joined with cross-site data to build a user
profile. Once it does that, the button will then display the last 4 digits of the user’s credit card
number, as it is saved in the browser, inside the first-party storage partition for the ecommerce
platform’s origin.
2.3.3. The fenced frame config struct
We now establish some preliminary types:
A visibility is either "opaque
" or "transparent
".
A size is a struct with the following items:
- width
-
a non-negative integer
- height
-
a non-negative integer
TODO: Consider different numeric types for these members.
An interest group descriptor is a struct with the following items:
A permissions policy behavior is either "fixed
" or "flexible
".
The default fenced frame effective sandboxing flags are a sandboxing flag set with the following flags:
A pending event is a struct with the following items:
- destination
- event
- request initiator
-
an origin
- initiator referrer policy
A reporting destination info is a struct with the following items:
- reporting url declarer origin
-
an origin
- reporting url map
- reporting macro map
-
null, or a map whose keys are strings and whose values are strings
A fenced frame reporting map is a map whose keys are FenceReportingDestination
s and whose values are either:
-
lists of pending events (which are used to represent events that need to be reported asynchronously, because the metadata has not been finalized yet); or
-
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 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.
FenceReportingDestination
destination, an origin reporting url declarer origin, a map destination map whose keys are strings and whose values are urls, and macro map, which is either null or a map whose keys are strings and whose values are strings, run these
steps:
-
Assert that reporting map[destination] is a list (i.e., that destination’s metadata has not yet been finalized).
-
Let pending event list be reporting map[destination].
-
Set reporting map[destination] to a struct with the following items:
- reporting url declarer origin
-
reporting url declarer origin
- reporting url map
-
destination map
- reporting macro map
-
macro map
-
For each pending event of pending event list:
-
Send a beacon with destination map, pending event’s event, pending event’s request initiator, and pending event’s initiator referrer policy.
-
A fenced frame reporting metadata is a struct with the following items:
- fenced frame reporting map
- direct seller is seller
-
a boolean, initially true
- allowed reporting origins
-
null or a list of origins. An origin must be present in this list to be the destination of a destination URL event report.
- attempted custom url report to disallowed origin
-
a boolean, initially false
An automatic beacon event type is either "reserved.top_navigation_start
", "reserved.top_navigation_commit
", or "reserved.top_navigation
".
reserved.top_navigation
is an earlier
naming of reserved.top_navigation_commit
. While they
both do the same thing, reserved.top_navigation
will be
removed in the future and should not be used for new code.
A fenced frame reporter is a struct with the following items:
- fenced frame reporting metadata reference
-
a mutable reference to a fenced frame reporting metadata TODO: Handle pointers/references in a more spec-y way
A destination enum event is a struct with the following items:
- type
-
a string
- data
-
a string
- attributionReportingEnabled
-
a boolean
- attributionReportingContextOrigin
-
an origin
A destination URL event is a URL.
An automatic beacon event is a struct with the following items:
- type
- data
-
a string
- attributionReportingEnabled
-
a boolean
- attributionReportingContextOrigin
-
an origin
A destination event is either a destination enum event, a destination URL event, or a automatic beacon event.
-
Let destination url be an empty string.
-
Let attributionReportingEligibility be "
unset
". -
Let processResponse be null.
-
Let useParallelQueue be false.
-
If event is either a destination enum event or an automatic beacon event, then:
-
Let destination map be destination info’s reporting url map.
-
Let eventType be either event’s destination type, or automatic type, depending on which variant event is.
-
If destination map[eventType] does not exist, return.
-
Set destination url to destination map[eventType].
-
If event’s attributionReportingEnabled is true and event’s attributionReportingContextOrigin is suitable:
-
If event’s
eventType
matches one of the automatic beacon event type values, set attributionReportingEligibility to "navigation-source
". -
Otherwise, set attributionReportingEligibility to "
event-source
". -
Set processResponse to these steps given a response response:
-
Let fenced be true.
-
Run process an attribution eligible response with event’s attributionReportingContextOrigin, attributionReportingEligibility, fenced, and response.
-
-
Set useParallelQueue to true.
-
-
-
Otherwise:
-
Assert: event is a destination URL event.
-
Let macro map be destination info’s reporting macro map.
-
If macro map is null, return.
-
Set destination url to event.
-
Let destination url be the result of substituting macros with macro map into destination url.
-
-
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 enrolled.
-
Let request be a new request with the following properties:
- method
-
if event is a destination enum event, otherwisePOST
.GET
- URL
-
destination url
- header list
-
A new header list containing a header whose name is
"Content-Type"
and value is"text/plain"
. - body
-
If event is a destination enum event, a body whose source is event’s data, otherwise null.
- client
-
null
- service-workers mode
-
"all"
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. - origin
-
request initiator if event is a destination URL event, and destination info’s reporting url declarer origin otherwise.
Note: The reporting destination for a destination URL event is determined by the
Document
that callsreportEvent()
, as opposed to a destination enum event or automatic beacon event whose reporting destinations are determined in the worklet that created the fenced frame config that loaded thisDocument
. We set the origin to the origin of theDocument
or worklet that determined the reporting destination to prevent cross-site request forgery. - referrer
-
request initiator
- referrer policy
-
initiator referrer policy
- mode
-
"cors"
- credentials mode
-
"omit"
- Attribution Reporting eligibility
-
attributionReportingEligibility
-
Fetch request with processResponse being processResponse if it is not null and useParallelQueue being useParallelQueue.
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, we invoke fetch with useParallelQueue set to true when the optional response-handling algorithm is used, otherwise there is no need to do this even when this algorithm is running in parallel in other instances.
FenceReportingDestination
destination, an origin request initiator,
a referrer policy initiator referrer policy, and a destination event event, run these steps:
-
Let metadata be reporter’s fenced frame reporting metadata reference.
-
If destination is
"direct-seller"
:-
If metadata’s direct seller is seller is true, set destination to
"seller"
. -
Otherwise, set destination to
"component-seller"
.
-
-
If event is a destination URL event:
-
If event’s origin is not same origin with any of the entries in metadata’s allowed reporting origins:
-
Set metadata’s attempted custom url report to disallowed origin to true.
-
-
If metadata’s attempted custom url report to disallowed origin is true, return.
-
-
Let reporting map be a reference to metadata’s fenced frame reporting map.
-
If reporting map[destination] does not exist, return.
-
If reporting map[destination] is a list:
-
Let newEvent be a new pending event with the following:
- destination
-
destination
- event
-
event
- request initiator
-
request initiator
- initiator referrer policy
-
initiator referrer policy
-
Append newEvent to reporting map[destination].
-
Return.
Note: The pending event will be sent asynchronously.
-
-
Assert that reporting map[destination] is a map (i.e., that destination’s metadata has been finalized).
-
Send a beacon with reporting map[destination], event, request initiator, and initiator referrer policy.
-
If event’s
eventType
starts with "reserved.
", then return. -
reporter event TODO: Fill this in
An exfiltration budget metadata is a struct with the following items:
- origin
-
an origin
- amount to debit
-
a non-negative valid floating point number
An exfiltration budget metadata reference is a struct with the following items:
- origin
-
an origin
- amount to debit reference
-
a mutable reference to a non-negative valid floating point number TODO: Handle pointers/references in a more specy-y way
A partition nonce is an implementation-defined value.
Note: This is similar to the network partition key used by Fetch.
A fenced frame config is a struct with the following items:
- mapped url
-
a struct with the following items:
- value
-
a URL
- visibility
- container size
-
null, or a size
- content size
-
null, or a struct with the following items:
- value
-
a size
- visibility
- interest group descriptor
-
null, or a struct with the following items:
- value
- visibility
- on navigate callback
-
null, or a series of steps
- effective sandboxing flags
-
null, or a struct with the following items:
- value
- visibility
- effective enabled permissions
-
null, or a struct with the following items:
- value
- visibility
Note: When non-null, this is a list of policy-controlled features that the generator of this config relies on exclusively being enabled inside the
fencedframe
that navigates to this config. Specifically, each feature in this list must be enabled by thefencedframe
's fenced navigable's permissions policy's inherited policy when navigating to this config for the navigation to succeed. The features in this list are not force-enabled, but rather are used to check that the embedder environment that influences the aforementioned inherited policy is relaxed enough to support these essential features. If the inherited policy value for any of these features is "Disabled
", the navigation to this config will fail. Any policy-controlled feature not in this list will not be "Disabled
" in thefencedframe
that navigates to this config. - fenced frame reporting metadata
-
null, or a struct with the following items:
- value
- visibility
- exfiltration budget metadata
-
null, or a struct with the following items:
- value
- visibility
- nested configs
-
null, or a struct with the following items:
- value
-
a list of fenced frame configs
- visibility
- embedder shared storage context
-
null, or a string
- is ad component
-
A boolean, initially false.
- cross-origin reporting allowed
-
A boolean, initially false.
Note: When true, this fenced frame config represents an ad component. An ad component can be used to construct ads composed of multiple pieces. See the Protected Audience explainer. For an ad component, event reporting is handled differently. See the Fenced Frame Ads Reporting explainer that describes this.
2.3.4. The fenced frame config instance struct
A fenced frame config instance is a struct with the following items:
- mapped url
-
a URL
- container size
-
null, or a size
- content size
-
null, or a size
- interest group descriptor
-
null, or an interest group descriptor
- on navigate callback
-
null, or a series of steps
- effective sandboxing flags
-
null, or a sandboxing flag set
- permissions policy behavior
- effective enabled permissions
-
null, or a list of policy-controlled features
- fenced frame reporter
-
null, or a fenced frame reporter
- exfiltration budget metadata reference
-
null, or an exfiltration budget metadata reference
- nested configs
-
null, or an map whose keys are urn uuids and whose values are fenced frame configs
- partition nonce
- embedder shared storage context
-
null, or a string
- is ad component
-
A boolean
- has disabled untrusted network
-
A boolean, initially false.
- cross-origin reporting allowed
-
A boolean, initially false.
- mapped url
-
config’s mapped url's value
- container size
-
config’s container size
- content size
-
config’s content size if null, otherwise config’s content size's value
- interest group descriptor
-
config’s interest group descriptor if null, otherwise config’s interest group descriptor's value
- on navigate callback
-
config’s on navigate callback
- effective sandboxing flags
-
config’s effective sandboxing flags if null, otherwise config’s effective sandboxing flags's value
- permissions policy behavior
-
flexible if config’s effective enabled permissions is null, fixed otherwise.
- effective enabled permissions
-
config’s effective enabled permissions if null, otherwise config’s effective enabled permissions's value
- fenced frame reporter
-
-
If config’s fenced frame reporting metadata's value is null, set to null.
-
Otherwise, set to a fenced frame reporter with the following members:
- fenced frame reporting metadata reference
-
a reference to config’s fenced frame reporting metadata's value
-
- exfiltration budget metadata reference
-
-
If config’s exfiltration budget metadata is null, set to null.
-
Otherwise, set to a exfiltration budget metadata reference:
- origin
-
config’s exfiltration budget metadata's value's origin
- amount to debit reference
-
a reference to config’s exfiltration budget metadata's value's amount to debit
-
- nested configs
-
-
If config’s nested configs is null, set to null.
-
Otherwise:
-
Let results be a new map.
-
For each nested config of config’s nested configs's value:
-
Set nested configs to results.
-
-
- partition nonce
-
a random, unique partition nonce
- embedder shared storage context
-
config’s embedder shared storage context
- is ad component
-
config’s is ad component
- cross-origin reporting allowed
-
config’s cross-origin reporting allowed
- has disabled untrusted network
-
false
Each browsing context has a fenced frame config instance, which is a fenced frame config instance or null, initially null.
This fenced frame config instance should really exist on browsing context group, however until third-party cookies are deprecated, this
specification supports many of the fencedframe
concepts on the iframe
element. This requires
that for the short term, a normal content navigable be able to load a fenced frame config, and therefore have access to the navigation’s corresponding fenced frame
config instance.
2.3.5. The FencedFrameConfig
interface
One major input to the fencedframe
element is the FencedFrameConfig
interface, which
maps to an internal fenced frame config struct.
enum {
OpaqueProperty }; [
"opaque" Exposed =Window ,Serializable ]interface {
FencedFrameConfig constructor (USVString );
url undefined setSharedStorageContext (DOMString ); };
contextString
Each FencedFrameConfig
has:
Note: A config’s url is only null if a urn is supplied.
FencedFrameConfig(url)
constructor method steps
are:
-
Let config be a new
FencedFrameConfig
object. -
Set config’s url to the result of running the URL parser on url.
-
Return config.
setSharedStorageContext(contextString)
method steps
are to set this's sharedStorageContext to contextString. FencedFrameConfig
objects are serializable objects. Their serialization steps, given value, serialized, and forStorage are:
-
If forStorage is true, then throw a
DataCloneError
DOMException
. -
Set serialized.[[Url]] to value’s url.
-
Set serialized.[[Urn]] to value’s urn.
-
Set serialized.[[SharedStorageContext]] to value’s sharedStorageContext.
-
Initialize value’s url to serialized.[[Url]].
-
Initialize value’s urn to serialized.[[Urn]].
-
Initialize value’s sharedStorageContext to serialized.[[SharedStorageContext]].
Note: To help with ease of adoption, until 2026 we will support
the API navigator
.deprecatedReplaceInURN()
, which allows you to substitute
macros into the mapped url corresponding to a given urn uuid or FencedFrameConfig
.
Note: To help with ease of adoption, until third party cookie deprecation we will support the API navigator
.deprecatedURNtoURL()
, which returns
the mapped url corresponding to a given urn uuid or FencedFrameConfig
.
typedef (USVString or FencedFrameConfig );
UrnOrConfig partial interface Navigator {Promise <undefined >deprecatedReplaceInURN (UrnOrConfig ,
urnOrConfig record <USVString ,USVString >);
replacements Promise <USVString >deprecatedURNtoURL (UrnOrConfig ,
urnOrConfig optional boolean =
send_reports false );sequence <USVString >adAuctionComponents (unsigned short ); };
numAdComponents
-
TODO: Spec this. Substitute the keys from macros with the corresponding values into string, and return the new string. There is no recursive substitution.
deprecatedReplaceInURN(urnOrConfig, replacements)
method steps are:
-
Let urn be null.
-
If urnOrConfig is a
USVString
, set urn to urnOrConfig. -
Otherwise, set urn to urnOrConfig’s urn.
-
If urn is not a valid urn uuid (i.e., won’t pass the ABNF in Section 3 of urn uuid), throw a
TypeError
. -
For each key → _ of replacements:
-
Let p be a new promise.
-
Let global be this's relevant global object.
-
Run the following steps in parallel:
-
Let mapping be global’s navigable's traversable navigable's fenced frame config mapping.
-
Let config be the result of finding a config in mapping with urn.
-
If config is failure, queue a global task on the DOM manipulation task source given global, to resolve p with
undefined
, and abort these steps. -
Let substitutedUrl be the result of substituting macros with replacements into config’s mapped url's value.
-
Set config’s mapped url's value to substitutedUrl.
-
Queue a global task on the DOM manipulation task source given global, to resolve p with
undefined
.
-
-
Return p.
deprecatedURNtoURL(urnOrConfig, send_reports)
method
steps are:
-
Let urn be null.
-
If urnOrConfig is a
USVString
, set urn to urnOrConfig. -
Otherwise, set urn to urnOrConfig’s urn.
-
If urn is not a valid urn uuid (i.e., won’t pass the ABNF in Section 3 of urn uuid), throw a
TypeError
. -
Let p be a new promise.
-
Let global be this's relevant global object.
-
Run the following steps in parallel:
-
Let mapping be global’s navigable's traversable navigable's fenced frame config mapping.
-
If mapping’s finalized config mapping[urn], does not exist, then queue a global task on the DOM manipulation task source given global, to resolve p with
undefined
, and abort these steps. -
Let config be mapping’s finalized config mapping[urn].
-
Queue a global task on the DOM manipulation task source given global, to resolve p with config’s mapped url's value.
-
If send_reports is true, then run the steps in config’s on navigate callback.
-
-
Return p.
adAuctionComponents(numAdComponents)
-
Let instance be this's relevant global object's browsing context's fenced frame config instance.
-
If instance is null, then throw a
DOMException
. -
If this's relevant settings object's origin and instance’s mapped url's origin are not same origin, then then throw a
DOMException
. -
Let maxAdComponents be 40.
-
If numAdComponents > maxAdComponents, then set numAdComponents to maxAdComponents.
-
For each urn → config of instance’s nested configs:
-
Return adComponentsURNs.
2.4. The Fence
interface
Several APIs specific to fenced frames are defined on the Fence
interface.
enum {
FenceReportingDestination ,
"buyer" ,
"seller" ,
"component-seller" ,
"direct-seller" , };
"shared-storage-select-url" dictionary { // This dictionary has two mutually exclusive modes that aren’t represented as // distinct IDL types due to distinguishability issues: // // When reporting to a preregistered destination (specified by enum), the following // properties are used:
FenceEvent DOMString ;
eventType DOMString ;
eventData sequence <FenceReportingDestination >; // Determines if this data can be sent in a reportEvent() beacon or automatic // beacon that originates from a document that is cross-origin to the mapped // URL of the fenced frame config that loaded this frame tree. // Note that automatic beacon data can only be set from documents that are // same-origin to the fenced frame config’s mapped URL, so this effectively // opts in the data to being used in a cross-origin subframe.
destination boolean =
crossOriginExposed false ; // When setting event data to be used later in an automatic beacon, the // following properties are used:boolean =
once false ; // When reporting to a custom destination URL (with substitution of macros defined by // the Protected Audience buyer), the following property is used:USVString ; };
destinationURL typedef (FenceEvent or DOMString ); [
ReportEventType Exposed =Window ]interface {
Fence undefined reportEvent (optional ReportEventType = {});
event undefined setReportEventDataForAutomaticBeacons (optional FenceEvent = {});
event sequence <FencedFrameConfig >getNestedConfigs ();Promise <undefined >disableUntrustedNetwork ();undefined notifyEvent (Event ); };
event
reportEvent(event)
method steps are:
-
Let instance be this's relevant global object's browsing context's fenced frame config instance.
-
If instance is null, then return.
-
If instance’s is ad component is true, then return.
-
If instance’s fenced frame reporter is null, then return.
-
Let document be this's relevant global object's associated Document.
-
Let request initiator be this's relevant settings object's origin.
-
Let initiator referrer policy be document’s policy container's referrer policy.
-
If event is a
DOMString
:-
If this's relevant settings object's origin and instance’s mapped url's origin are not same origin, then return.
-
Run report a private aggregation event using instance’s fenced frame reporter with event.
-
-
If event is a
FenceEvent
:-
If event’s
eventType
starts with "reserved.
", then return. -
If all of the following conditions are true:
-
this's relevant settings object's origin and instance’s mapped url's origin are not same origin;
-
either event’s
crossOriginExposed
is false or instance’s cross-origin reporting allowed is false;
then return.
-
-
If event has a
destinationURL
:-
If event has a
destination
or aeventType
or aeventData
: -
Let destinationURL be the result of running the URL parser on
destinationURL
. -
Throw a
TypeError
if any of the following conditions hold:-
destinationURL is failure;
-
destinationURL scheme is not "
https
";
-
-
Run report an event using instance’s fenced frame reporter with
buyer
, request initiator, initiator referrer policy and a destination URL event that is event’sdestinationURL
.
-
-
Otherwise:
-
If event does not have a
destination
or event does not have aeventType
: -
Let attributionReportingEnabled be the result of determining whether document is allowed to use the "
" feature.attribution-reporting
-
Let attributionReportingContextOrigin be document’s context origin.
-
For each destination of event’s
destination
:-
Run report an event using instance’s fenced frame reporter with destination, request initiator, initiator referrer policy, and a destination enum event with the following items:
- attributionReportingEnabled
-
attributionReportingEnabled
- attributionReportingContextOrigin
-
attributionReportingContextOrigin
-
-
-
Tests
- fence-report-event.https.html (live test) (source)
- fence-report-event-destination-url.https.html (live test) (source)
- fence-report-event-cross-origin-content-initiated.https.html (live test) (source)
- fence-report-event-cross-origin-nested-urn-iframe.https.html (live test) (source)
- fence-report-event-cross-origin-nested.https.html (live test) (source)
- fence-report-event-cross-origin-no-embedder-opt-in.https.html (live test) (source)
- fence-report-event-cross-origin-no-subframe-opt-in.https.html (live test) (source)
- fence-report-event-cross-origin-urn-iframe-content-initiated.https.html (live test) (source)
- fence-report-event-cross-origin-urn-iframe-no-embedder-opt-in.https.html (live test) (source)
- fence-report-event-cross-origin-urn-iframe-no-subframe-opt-in.https.html (live test) (source)
- fence-report-event-cross-origin-urn-iframe.https.html (live test) (source)
- fence-report-event-cross-origin.sub.https.html (live test) (source)
- fence-report-event-sub-fencedframe.https.html (live test) (source)
setReportEventDataForAutomaticBeacons(event)
method steps are:
-
If event does not have a
destination
or event does not have aeventType
: -
If event’s
eventType
does not match one of the automatic beacon event type values, return. -
Let instance be this's relevant global object's browsing context's fenced frame config instance.
-
If instance is null, then return.
-
If this's relevant settings object's origin and instance’s mapped url's origin are not same origin, then return.
-
If instance’s fenced frame reporter is null, then return.
-
Set this's relevant global object's associated Document's automatic beacon data map[event’s
eventType
] to an automatic beacon data with the following items:- eventData
-
event’s
eventData
if defined and instance’s is ad component is false, otherwise empty string. - destination
-
event’s
destination
- once
-
event’s
once
- crossOriginExposed
-
event’s
crossOriginExposed
getNestedConfigs()
method steps are:
-
Let instance be this's relevant global object's browsing context's fenced frame config instance.
-
If instance is null, then return.
-
If this's relevant settings object's origin and instance’s mapped url's origin are not same origin, then return.
-
If instance’s nested configs is null, then return.
-
Let results be an empty list of
FencedFrameConfig
s. -
For each urn → config of instance’s nested configs:
-
Let newConfig be a new
FencedFrameConfig
object created in this's relevant realm, with the following:- urn
-
urn
- sharedStorageContext
-
config’s embedder shared storage context
-
Append newConfig to results.
-
-
Return results.
notifyEvent(event)
method steps are:
-
If this's
Document
is not fully active, then return. -
Let navigable be this's relevant global object's navigable.
-
If any of the following conditions are met, then throw a
SecurityError
DOMException
:-
navigable is not a fenced navigable;
-
event’s
isTrusted
is false; -
event’s dispatch flag is unset;
-
event’s
type
is not "click
"
-
-
If this's relevant global object does not have transient activation, then return.
-
Let parentNavigable be navigable’s unfenced parent.
-
Queue a global task on the DOM manipulation task source given parentNavigable’s active window to run these steps:
-
Perform the activation notification steps.
-
Fire an event named "
fencedtreeclick
" at navigable’s fenced navigable container. Initialize the event’sbubbles
andcancelable
attributes totrue
. When running the inner event creation steps, set the time to an implementation-defined value that is consistent across all invocations of this method.
-
Tests
disableUntrustedNetwork()
method steps are:
-
Let p be a new promise.
-
Let instance be this's relevant global object's browsing context's fenced frame config instance.
-
If the relevant settings object's origin and instance’s mapped url's origin are not same origin, then reject p with a
TypeError
. -
If this's relevant global object's navigable's traversable navigable is not a fenced navigable, then resolve p with
undefined
and return p. -
Let global be this's relevant global object.
-
Run the following steps in parallel:
-
Let fencedFrameNonce be instance’s partition nonce.
-
Let credentiallessNonce be
the page credentialless nonce (WICG/fenced-frame#191)
-
Invoke revoke network for a partition nonce on fencedFrameNonce.
-
Invoke revoke network for a partition nonce on credentiallessNonce.
-
Set instance’s has disabled untrusted network to true.
-
Wait on all nested fenced frames to disable network too.
Spec this waiting more formally. (WICG/fenced-frame#151)
-
Queue a global task on the DOM manipulation task source given global, to resolve p with
undefined
.
-
-
Return p.
A user agent has an associated network revocation nonce set, which is a set of partition nonces, and a network revocation exemption map, which is a map whose keys are partition nonces and values are sets of URLs.
Note: The network revocation exemption map is used only for web platform tests; in normal usage it is always empty. This list is modified directly in web platform tests by a function call to exempt specific URLs from network revocation.
This will require a RFC to add a test-only function to the WPT web driver. (WICG/fenced-frame#192)
-
Append nonce to the user agent’s network revocation nonce set.
-
If the user agent’s network revocation exemption map[nonce] exists, and if requestURL exists in it, return allowed.
-
If the user agent’s network revocation nonce set contains nonce, return blocked.
-
Return allowed.
2.5. Fetch monkeypatches for network revocation
The network revocation mechanism requires the following monkeypatches to the [FETCH] Standard.
If should request be blocked due to a bad port, should fetching request be blocked as mixed content, or should request be blocked by Content Security Policy returns blocked, then set response to a network error.
Add "must be blocked due to a revoked partition nonce" to the conditions after "should request be blocked by Content Security Policy".
2.6. New request destination
The processing model of a fencedframe
's navigation request deviates from that of the normal navigation request in enough ways to justify a new request destination value.
This specification updates the request destination enumeration to include a new
entry, "fencedframe
". Perform the following monkeypatches to the [FETCH] Standard.
Add "fencedframe
" to the non-subresource request list and to the navigation
request list.
Add "fencedframe
" to the RequestDestination
enum.
A user agent should set value to the first matching statement, if any, switching on request’s destination:
Add "fencedframe
" to the switch cases alongside "document
",
"frame
", and "iframe
".
Non-normatively, update the DOM intro destination
table to illustrate that fencedframe
navigation requests have the following properties:
-
destination of "
fencedframe
" -
initiator ""
-
CSP directive of
fenced-frame-src
-
Features as HTML’s
<fencedframe>
2.7. Automatic Reporting
This first introductory paragraph is non-normative.
A side effect of the fenced boundary model is that ads will lose the ability to know if a click
resulted in a successful navigation. This is because the page loaded from a top-level navigation originating from a fenced frame will not be allowed to report to the fenced frame that
it loaded (through something like window.opener
). Instead, we introduce
special event-level reporting types, reserved.top_navigation_start
and reserved.top_navigation_commit
, which automatically sends an event-level beacon when a fenced frame initiates a successful navigation to a top-level traversable.
Document
targetDocument, and an automatic beacon event type eventType, run these steps:
-
If targetDocument’s node navigable's traversable navigable is not a top-level traversable, abort these steps.
-
If sourceSnapshotParams’s has transient activation is set to false, abort these steps.
-
Let config be sourceSnapshotParams’s initiator fenced frame config instance.
-
If config is null, abort these steps.
Note: Since this algorithm is called unconditionally for all navigations, this is used to catch cases where a navigation to a top-level traversable does not originate from a
fencedframe
. -
Let request initiator be sourceOrigin if config’s is ad component is false, and sourceSnapshotParams’s initiator ancestor root origin otherwise.
-
Let initiator referrer policy be sourceSnapshotParams’s source policy container's referrer policy if config’s is ad component is false, and sourceSnapshotParams’s initiator ancestor root referrer policy otherwise.
-
Let beacon data be sourceSnapshotParams’s automatic beacon data map[eventType].
-
Let has header opt in be sourceSnapshotParams’s automatic beacons allowed.
-
If beacon data is null and has header opt in is false, abort these steps.
-
Let is cross origin be true if sourceOrigin is not same origin with config’s mapped url's origin, false otherwise.
-
If is cross origin is true and has header opt in is false, abort these steps.
-
Let should send beacon with data be true if beacon data is not null and either is cross origin is false or beacon data’s crossOriginExposed is true, false otherwise.
-
For each destination of config’s fenced frame reporter's fenced frame reporting metadata reference's fenced frame reporting map's keys:
-
Run report an event using config’s fenced frame reporter with destination, request initiator, initiator referrer policy, and an automatic beacon event with the following items:
- type
-
eventType
- data
-
beacon data’s eventData if should send beacon with data is true, beacon data’s destinations contains destination, and config’s is ad component is false, the empty string otherwise.
- attributionReportingEnabled
-
sourceSnapshotParams’s attribution reporting enabled
- attributionReportingContextOrigin
-
sourceSnapshotParams’s attribution reporting context origin
-
-
If beacon data’s once is true, set sourceSnapshotParams’s automatic beacon data map[eventType] to null.
Tests
- automatic-beacon-anchor-click-handler.https.html (live test) (source)
- automatic-beacon-click-handler.https.html (live test) (source)
- automatic-beacon-two-events-clear.https.html (live test) (source)
- automatic-beacon-two-events-persist.https.html (live test) (source)
- automatic-beacon-unfenced-top.https.html (live test) (source)
- automatic-beacon-no-destination.https.html (live test) (source)
- automatic-beacon-no-opt-in.https.html (live test) (source)
- automatic-beacon-shared-storage.https.html (live test) (source)
- automatic-beacon-cross-origin-false.https.html (live test) (source)
- automatic-beacon-cross-origin-navigation.https.html (live test) (source)
- automatic-beacon-cross-origin-no-data.https.html (live test) (source)
- automatic-beacon-cross-origin-no-opt-in.https.html (live test) (source)
- automatic-beacon-use-ancestor-data.https.html (live test) (source)
-
Attempt to send an automatic beacon given sourceSnapshotParams, initiatorOriginSnapshot, navigable’s associated
Document
, andreserved.top_navigation_start
.
-
If failure is false, then:
-
Attempt to send an automatic beacon given sourceSnapshotParams, entry’s document state's initiator origin, document, and
reserved.top_navigation_commit
. -
Attempt to send an automatic beacon given sourceSnapshotParams, entry’s document state's initiator origin, document, and
reserved.top_navigation
.
-
3. HTML Integration
3.1. Extensions to the Window
interface
partial interface Window { // Collection of fenced frame APIsreadonly attribute Fence ?fence ; };
Each Window
object has an associated fence, which is a Fence
instance
created alongside the Window
.
fence
getter steps are:
-
If this's browsing context's fenced frame config instance is not null, then return this's fence.
-
Return null.
3.2. Document
supporting concepts
We first establish some preliminary types:
An automatic beacon data is a struct with the following items:
Each Document
object has an associated automatic beacon data map, which
is a map whose keys are automatic beacon event types and whose values are null or an automatic beacon data
Each Document
object has an associated automatic beacons allowed, which
is a boolean, initially false.
3.3. Modifications to creating browsing contexts
-
If creator is non-null, then:
to instead use the tighter condition:
-
If creator is non-null and embedder is not a
fencedframe
element, then:
Note: This is because we need to ensure that we do not leak creator’s referrer, origin, document base url, policy container, across the fenced frame boundary.
Add a substep to step 4 of this algorithm (that was modified above) that reads:
-
Set browsingContext’s fenced frame config instance to creator’s browsing context's fenced frame config instance.
3.4. Policy container inheritance
When making a navigation request to a local URL, iframe
s clone their policy container from the navigation request's initiator Document
. If fencedframe
s were to do the same thing, that would allow information about the initiator’s policy container to leak across a fenced frame boundary. This section patches policy container inheritance to close that leak.
Rewrite step 3 to read:
-
If responseURL is local, initiatorPolicyContainer is not null, and fenced false, then return a clone of initiatorPolicyContainer.
Note: We do not need to modify the case where responseURL is about:srcdoc
,
because navigations to about:srcdoc
are not supported in fenced frames.
-
Let fenced be true if navigable is a fenced navigable, false otherwise.
Note: This ensures fenced is true regardless of whether the initiator
Document
is navigable’s active document or its unfenced parent.
Rewrite step 23 (now step 24) to read:
-
Let resultPolicyContainer be the result of determining navigation params policy container given response’s URL, entry’s document state's history policy container, sourceSnapshotParams’s source policy container, null, responsePolicyContainer, and fenced.
Note: fencedframe
policy container inheritance upon initial Document
creation is handled
in the § 3.3 Modifications to creating browsing contexts section.
3.5. Nested traversables
3.5.1. Introduction
This section is non-normative.
The [HTML] Standard organizes navigables into two categories: child navigables and traversable navigables (also known as top-level traversables). The introduction of features
like fenced frames, and to a lesser extent portals,
complicates this model by adding a new type of traversable navigable that is sometimes like a child navigable. Because these new frame types are housed in a separate browsing context
group from their embedder, some concrete level of isolation is expected and required; on the other
hand since they are composed visually inside of other browsing context groups, sometimes they
need to behave like the normal child navigables that we see in e.g., iframe
s.
The complexity here is in deciding when terms like navigable container, navigable parent, and descendant navigables need to cross the traversable navigable/browsing context group boundary, versus when doing so would be unsafe or incorrect. The examples below illustrate this point.
When a user activates content inside
of a Document
, ordinarily the activation notification steps give user activation to all ancestor navigables and all same origin descendant navigables. But
because a fencedframe
can host sensitive content that needs to be isolated from its embedder,
and because user activation and consumption offer a communication
vector between these two parties, for the purpose of user activation a fencedframe
's fenced navigable cannot not be considered a descendant of its
embedder, nor can its embedder be considered an ancestor of the fencedframe
's fenced navigable, in the way that the user activation algorithms currently use those
terms. In other words, we consider user activation to be fenced, to denote that it never crosses
the fenced navigable boundary; if it were unfenced, it would behave
as it would with iframe
s, allowing user activation to flow freely across the frame
boundary.
Unlike user activation, when a fencedframe
's fenced navigable gets created or navigated, it must inherit its embedder Document
's active sandboxing flag set as is standard for Document
s in normal child navigables. If we did not do this, then the fencedframe
element would be a trivial
sandbox bypass. Because fencedframe
sandbox flag inheritance behaves similarly to how it does in iframe
elements, we consider sandbox inheritance to be unfenced.
To provide the isolation mentioned above, and its conditional relaxation, this specification defines a new kind of parent for traversable navigables called an unfenced parent, which provides a link to its embedder that algorithms can intentionally use when they need to be unfenced, as described above.
Note: Introducing a new kind of parent (unfenced parent) is an intentional
design decision. It means that by default, the fencedframe
boundary is private and isolated,
since by default nothing in the web platform traverses from a fencedframe
's fenced navigable to its embedder. Care must be taken when
modifying algorithms to make them capable of traversing across the fencedframe
fenced navigable boundary, and each modification of this sort will be evaluated
independently and appear in this specification.
The rest of this section provides patches to various [HTML] definitions (and their uses) that deal with collections of related navigables, with the intention of fencing and unfencing various parts of the web platform appropriately.
3.5.2. Traversable navigables
In [HTML]'s Traversable navigables section, add the following:
In addition to the properties of a navigable, a traversable navigable has:
-
An unfenced parent, a navigable or null, initially null.
Note: The unfenced parent link is what gives a fencedframe
's fenced navigable a link to its embedder, which is used carefully for
things that need to be "unfenced", like some algorithms in the focus processing model.
-
If navigable is a child navigable, return navigable’s parent.
-
Assert: navigable is a fenced navigable.
-
Return navigable’s unfenced parent.
Note: This algorithm is different from the traversable navigable's unfenced parent getter in that this algorithm first tries to get the navigable's normal parent if navigable is a normal child navigable.
-
Let parentNavigable be navigable’s unfenced parent.
-
Return parentNavigable’s active document.
3.5.3. Nested traversables
In [HTML]'s Navigables section, add a new subsection titled "Nested traversables" with the following text, definitions, and algorithms.
Similar to navigable containers and their respective content navigables,
other elements (so far, only the fencedframe
element) present a more isolated navigable to
the user. These elements are called fenced navigable containers.
A fenced navigable container has a fenced navigable, which is either a traversable navigable with a non-null unfenced parent, or null. It is initially null.
-
Initialize the navigable traversable given documentState.
-
Set traversable’s unfenced parent to parent.
-
Let group be a new browsing context group.
Note: There doesn’t seem to be a reason to append group to the user agent’s browsing context group set like create a new browsing context group and document does.
-
Let document be the second return value of creating a new browsing context and document given element node document, element, and group.
-
Let documentState be a new document state, whose document is document.
-
Let traversable be a new traversable navigable.
-
Let parentNavigable be element’s node navigable.
-
Initialize the nested traversable traversable given documentState and parentNavigable.
-
Set element’s fenced navigable to traversable.
-
Let initialHistoryEntry be traversable’s active session history entry.
-
Set initialHistoryEntry’s step to 0.
-
Append initialHistoryEntry to traversable’s session history entries.
-
Return traversable.
Note: The create a new nested traversable algorithm creates the first kind of traversable navigable that is not a top-level traversable. This will require removing the note about nested traversables in [HTML]'s Top-level traversables section.
3.5.4. Top-level traversables
The [HTML] Standard currently defines a top-level traversable as a traversable navigable whose parent is null, however this is an insufficient definition that this specification changes. [HTML] mentions that outside of this specification, all traversable navigables are top-level traversables, but "envisions" future specifications that may want to create a kind of traversable that is nested, and achieves the nesting through a non-null parent; hence the distinction between top-level traversables and traversable navigables relies on the parent null-ness.
The fenced navigable this specification proposes is precisely what [HTML] envisioned when carving out space for the distinction between top-level traversables and traversable navigables, however this specification does not make use of the parent pointer for fenced navigables, for reasons described above (instead they use the unfenced parent pointer). That means by default, both top-level traversables and fenced navigables both have null parents, which renders the distinction meaningless.
To mend the intended distinction between top-level traversables and fenced navigables, patch the following definitions like so:
-
Let navigable be inputNavigable.
-
-
If navigable’s parent and unfenced parent are both null, then break.
-
Set navigable to navigable’s parent or unfenced parent, whichever is non-null.
Note: Exactly one of navigable’s parent or unfenced parent will be non-null here.
-
-
Return navigable.
Note: With these new definitions, a top-level traversable is essentially "unfenced" as described in the § 3.5.1 Introduction.
3.6. Modifications to navigable-traversing algorithms
Further rewrite step 2 of this algorithm to:
-
Extend navigables with document’s descendant navigables with unfenced set to unfenced.
-
Let navigables be a new list.
-
Let navigableContainers be a list of all shadow-including descendants of document that are navigable containers (or fenced navigable containers, if unfenced is true), in shadow-including tree order.
-
For each navigableContainer of navigableContainers:
-
If navigableContainer’s content navigable and fenced navigable are both null, then continue.
-
Let descendantNavigable be either navigableContainer’s content navigable or fenced navigable, whichever is non-null.
-
Extend navigables with descendantNavigable’s active document's inclusive descendant navigables with unfenced set to unfenced.
-
-
Return navigables.
-
Let navigable be document’s node navigable's parent.
-
If navigable is null and unfenced is true, set navigable to document’s node navigable's traversable navigable's unfenced parent.
-
Let ancestors be an empty list.
-
While navigable is not null:
-
Prepend navigable to ancestors.
-
Set navigable to navigable’s parent.
-
If navigable is null and unfenced is true, set navigable to navigable’s traversable navigable's unfenced parent.
-
-
Return ancestors.
3.7. Modifications to the focusing algorithms
The [HTML] standard defines how to handle focusing elements and Window
s, both by user gesture
and through script-initiated APIs. Since fenced frames are designed to prevent communication across
a fenced frame boundary, we need to handle focusing carefully. This is because when focus crosses a fencedframe
boundary, contexts on both sides of the boundary can detect that change, which can
be used to open a communication channel between a fencedframe
and its embedder.
We do this by not allowing the focusing steps to move script-initiated focus across a fenced frame boundary.
When a user clicks on an element like a button
inside a fencedframe
while another element outside of the fencedframe
is focused, the focusing steps will allow the button
to gain focus, because this is specifically a
user-initiated action. Without allowing that, no element inside of a fencedframe
would never be
able gain focus.
If we were to continue allowing all elements to be focused via the focus()
method as is the status quo before this
specification, a fenced navigable container and its fenced
navigable could use a sequence of focus()
calls to send arbitrary data across
the fenced frame boundary, which is a privacy leak. To avoid this, we effectively "fence" the focus()
method, which sacrifices some functionality for privacy.
Add a new step after step 3 of the algorithm (that changes new focus target) that reads:
-
If new focus target is a fenced navigable container with non-null fenced navigable, then set new focus target to the fenced navigable's active document.
Add a new step after the step that defines the new chain variable, that reads:
-
If unfenced is false, new chain contains a
Document
document whose node navigable's traversable navigable is a fenced navigable, and old chain does not also contain document, then return.Note: This is how we bail-out early just before calling the focus update steps, in the case where focus is trying to cross the fence.
Modify the user agent sentence after the algorithm steps in focusing steps to read:
User agents must immediately run the focusing steps for a focusable area or navigable candidate with unfenced set to true whenever the user attempts to move the focus to candidate.
-
Run the focusing steps for the element with unfenced set to true.
-
Fire a
click
event at the element.
When a user activates a click focusable focusable area, the user agent must
run the focusing steps on the focusable area with focus trigger set
to "click
" and unfenced set to true.
-
If previouslyFocusedElement is not null, then:
-
Set element’s previously focused element to null.
-
If focusPreviousElement is true, then run the focusing steps for previouslyFocusedElement with unfenced set to true; the viewport should not be scrolled by doing this step.
-
Note: Although dismissing a popover manually is a user-initiated gesture, the focusing steps will be called with unfenced set to false regardless of whether this was called from user gesture or via a script call.
-
User agents may focus one of those elements in the process, by running the focusing steps for that element, and may change the scrolling position of the document, or perform some other action that brings the element to the user’s attention. If these steps were invoked by user gesture, focusing steps can be called with unfenced set to true. For elements that are form-associated custom elements, user agents should use their face validation anchor instead, for the purposes of these actions.
-
If the focused area of candidate is a fenced navigable container with a non-null fenced navigable, then set candidate to the active document of that fenced navigable container's fenced navigable.
-
If currentObject is a focusable area, then set currentObject to currentObject’s DOM anchor's node document.
Otherwise, if currentObject is a
Document
whose node navigable's parent is non-null, then set currentObject to currentObject’s node navigable's parent.Otherwise, if currentObject is a
Document
whose node navigable is a traversable navigable whose unfenced parent is non-null, then set currentObject to currentObject’s node navigable's unfenced parent.Otherwise, break.
- If focus target is a fenced navigable container with a non-null fenced navigable
-
Return the fenced navigable container's fenced navigable's active document.
Note: This algorithm can unconditionally "jump the fence" boundary because its return value always feeds into an algorithm that does carefully consider the fence boundary.
-
While candidate’s focused area is either a navigable container with a non-null content navigable or a fenced navigable container with a non-null fenced navigable: set candidate to the active document of either that navigable container's content navigable or that fenced navigable container's fenced navigable, whichever is non-null.
-
If candidate is not null, then run the focusing steps for candidate with unfenced set to true and return.
Modify step 9 of the sequential focus navigation algorithm to read:
-
Otherwise, starting point is a focusable area whose node document's node navigable is a child navigable or fenced navigable. Set starting point to that node navigable's unfenced parent and return to the step labeled loop.
-
If candidate is a navigable container with a non-null content navigable, then let new candidate be the result of running the sequential navigation search algorithm with candidate’s content navigable as the first argument, direction as the second, and sequential as the third.
If candidate is a fenced navigable container with a non-null fenced navigable, then let new candidate be the result of running the sequential navigation search algorithm with candidate’s fenced navigable as the first argument, direction as the second, and sequential as the third.
If new candidate is null, then let starting point be candidate, and return to the top of this algorithm. Otherwise, let candidate be new candidate.
Tests
3.8. Navigation
This section describes how the fencedframe
element interacts with the ever-complicated process
of navigation, which includes integration with various headers, isolation mechanisms, and policies.
3.8.1. The `Supports-Loading-Mode
` HTTP response header
This section is intended to monkeypatch the [HTML] Standard, however since the `Supports-Loading-Mode
` header has not been merged into [HTML] yet,
and instead lives in the [Prerendering-Revamped] specification, this section effectively
monkeypatches that monkeypatch specification.
Add the new token below to the list of valid tokens for the `Supports-Loading-Mode
` response header:
The `fenced-frame
` token indicates that
the response can be used to create a Document
inside of a fenced
navigable. Without this explicit opt-in, all navigations inside of a fenced navigable will fail, as outlined in § 3.8 Navigation.
-
Otherwise, if all of the following conditions are true:
-
navigationParams’s navigable's traversable navigable is a fenced navigable;
-
the result of getting the supported loading modes for navigationParams’s response does not contain `
fenced-frame
`
then set failure to true.
-
3.8.2. The
`Allow-Fenced-Frame-Automatic-Beacons
` HTTP response header
Serving a document resource that gets loaded into a Document
that is not same origin with
its browsing context's fenced frame config instance's mapped url with the Allow-Fenced-Frame-Automatic-Beacons
HTTP response header opts in the Document
to having automatic beacon events trigger when it performs navigations. This header is
a structured header whose value must be a boolean.
3.8.3. The
`Allow-Cross-Origin-Event-Reporting
` HTTP response header
Serving a document resource that gets loaded into a fencedframe
by a fenced frame config
instance with the Allow-Cross-Origin-Event-Reporting
HTTP
response header opts in the Document
's cross-origin child navigables to be able to send reportEvent()
beacons. This header is a structured header whose value must be a boolean.
3.8.4. COOP, COEP, and cross-origin isolation
Outside of this specification, the `Cross-Origin-Opener-Policy
`
header only applies to top-level traversables instead of all navigables, and this specification continues this
intention insofar as this header does not have an impact on fenced
navigables, nor is it inherited from its embedder. Consequently, the browsing context group hosted inside of a fenced traversable navigable will
always have its cross-origin isolation mode set to "none
".
Nevertheless, a fenced navigable respects its unfenced parent's embedder policy, which is accomplished below:
-
navigable’s container document
with:
-
navigable’s unfenced container document
Note: This causes navigations inside of a fencedframe
to fail if they are not served with a
suitable `Cross-Origin-Embedder-Policy
` header, just as iframe
s behave.
Determine if we need to fence or unfence the queue a cross-origin embedder policy inheritance violation algorithm, as leaving it unfenced may cause a privacy leak.
-
If response is not a network error, navigable is a child navigable or fenced navigable, and the result of performing a cross-origin resource policy check with navigable’s unfenced container document's origin, navigable’s unfenced container document's relevant settings object, request’s destination, response, and true is blocked, then set response to a network error and break.
Note: Here we’re running the cross-origin resource policy check against the unfenced parent navigable rather than navigable itself. This is because we care about the same-originness of the embedded content against the embedder’s context (ignoring the "fence"), not the navigation source.
Determine if we need to fence or unfence the queue a cross-origin embedder policy CORP violation report algorithm, as leaving it unfenced may cause a privacy leak.
Tests
3.8.5. Actual navigation changes
- initiator fenced frame config instance
-
a fenced frame config instance or null, initially null.
- initiator ancestor root origin
-
an origin or null, initially null.
- initiator ancestor root referrer policy
-
an referrer policy or null, initially null.
- target fenced frame config
-
a fenced frame config or null, initially null.
Note: The initiator fenced frame config instance is the fenced frame
config instance that’s loaded into a navigation initiator’s browsing context, if any exists.
The initiator ancestor root origin, for component ads, is the origin of
the top-level ad container, if any exists. The initiator ancestor root
referrer policy, for component ads, is the referrer policy of the top-level ad container, if any
exists. They are used by the attempt to send an automatic beacon algorithm to compare origins and determine which FenceReportingDestination
s to send beacons and with what
information, if the fencedframe
-initiated navigation succeeds. The target fenced frame config on the other hand, is the non-instantiated fenced frame config that will be loaded into a fencedframe
element
for navigations targeting fenced frames. These fields do not interact together in any meaningful
way.
- attribution reporting enabled
-
a boolean.
- attribution reporting context origin
-
an origin.
- automatic beacons allowed
-
an boolean.
- automatic beacon data map
-
a map whose keys are automatic beacon event types and whose values are null or an automatic beacon data
Document
sourceDocument:
-
Assert these steps are running on sourceDocument’s event loop.
-
Let automatic beacon data map be a new empty automatic beacon data map.
-
Let current navigable be sourceDocument’s node navigable.
-
While current navigable is not null:
-
For each type → data of current navigable’s active document's automatic beacon data map:
-
If automatic beacon data map[type] does not exist, set automatic beacon data map[type] to data.
Note: This guarantees that the first ancestor that contains automatic beacon data for a specific type will be usable by the document initiating the navigation. This will also prevent an ancestor blocking a document from using data set in a higher ancestor.
-
-
Set current navigable to current navigable’s parent.
-
-
Return automatic beacon data map.
Note: The returned map is meant to hold references to the original Document
's automatic beacon data maps that were used to build automatic beacon data map. These
are later modified in attempt to send an automatic beacon to clear out any beacon data with once set to true.
Document
sourceDocument:
-
Let navigable be sourceDocument’s node navigable.
-
While navigable is not null and navigable is not a fenced navigable:
-
Set navigable to navigable’s parent.
-
-
If navigable is null, return null.
-
Assert: navigable is a fenced navigable.
-
Set navigable to navigable’s unfenced parent.
-
While navigable is not null and navigable is not a fenced navigable:
-
Set navigable to navigable’s parent.
-
-
Return navigable.
Document
embedded inside of a fencedframe
, this algorithm gets the navigable of
the document’s nearest fenced frame ancestor’s nearest fenced frame ancestor. If no such "fenced
frame grand-ancestor" exists, the algorithm returns null. Therefore, this algorithm only returns
a navigable when given a Document that is, at a minimum, in a fenced frame which is itself in a
fenced frame. For example, for the given frame tree structure:
Main frame (origin A) <fencedframe> (origin B) <iframe> (origin C) <fencedframe> (origin D) <iframe> (origin E) <fencedframe> (origin F)
The algorithm will return the following given each document:
-
Main frame (origin A)
will returnnull
. -
<fencedframe> (origin B)
will returnnull
. -
<iframe> (origin C)
will returnnull
. -
<fencedframe> (origin D)
will return<fencedframe> (origin B)
. -
<iframe> (origin E)
will return<fencedframe> (origin B)
. -
<fencedframe> (origin F)
will return<fencedframe> (origin D)
.
- initiator fenced frame config instance
-
sourceDocument’s browsing context's fenced frame config instance
- initiator ancestor root origin
-
null if the result of running get the initiator’s fenced grand-ancestor’s navigable on sourceDocument is null. Otherwise, sourceDocument’s initiator’s fenced grand-ancestor’s navigable's active document's origin.
- initiator ancestor root referrer policy
-
null if the result of running get the initiator’s fenced grand-ancestor’s navigable on sourceDocument is null. Otherwise, sourceDocument’s initiator’s fenced grand-ancestor’s navigable's active document's policy container's referrer policy.
- attribution reporting enabled
-
The result of determining whether sourceDocument is allowed to use the "
" featureattribution-reporting
- attribution reporting context origin
-
sourceDocument’s context origin
- automatic beacons allowed
-
sourceDocument’s automatic beacons allowed
- automatic beacon data map
-
The result of running get the automatic beacon data mapping to use on sourceDocument.
-
document’s relevant global object's navigable is a fenced navigable;
Note: This ensures that all navigations inside of a
fencedframe
are made with the "replace
" mode, regardless of the initiator.
Modify step 13 of [HTML]'s navigate algorithm ("If all of the following are true:") to include the following condition:
-
sourceDocument’s node navigable is not a fenced navigable container while at the same time navigable is a fenced navigable.
Note: This ensures that embedder-initiated navigations can never trigger a fragment navigation inside of a
fencedframe
.
Insert these steps immediately after step 22, the step that goes in parallel, so that what follows are the first steps that run in parallel in the patched algorithm:
-
If url is a urn uuid and navigable is a fenced navigable:
The above condition is not as tight as it needs to be. For example, if a
fencedframe
generates aFencedFrameConfig
using a config-generating API, and then correctly guesses the config’s urn:uuid, it can theoretically navigate itself to that config by passing the guessed urn into the navigate algorithm as a URL, via something like thelocation
API. This is bad, because the purpose of aFencedFrameConfig
is to ensure that only an embedder can navigate afencedframe
to the resource represented by the config, by using the config object directly. See #194 for thoughts on fixing this.-
Let config be the result of finding a config in sourceDocument’s node navigable's traversable navigable's fenced frame config mapping.
Note: This might "wait" for an arbitrary period of time for the config associated with the urn uuid url to be "finalized" in the fenced frame config mapping. This is why this step runs in parallel. This navigation will be canceled by any subsequent embedder-initiated navigations, should they occur, by the usual mechanism that tracks the ongoing navigation.
-
Set config’s embedder shared storage context to sharedStorageContext.
-
Assert: sourceSnapshotParams’s target fenced frame config is null.
-
Set sourceSnapshotParams’s target fenced frame config to config.
-
Assert config’s mapped url's value is a URL whose scheme is "
https
". -
Set url to config’s mapped url's value.
-
Run steps in config’s on navigate callback.
-
-
If navigable is a fenced navigable and sourceDocument’s node navigable is in navigable’s active document's ancestor navigables with unfenced set to true:
-
Let config be a new fenced frame config with the following items:
-
Assert: sourceSnapshotParams’s target fenced frame config is null.
-
Set sourceSnapshotParams’s target fenced frame config to config.
-
Rewrite the step starting with "Let unloadPromptCanceled be the result of" to:
-
Let unloadPromptCanceled be false if navigable is a fenced navigable, or the result of checking if unloading is user-canceled for navigable’s active document's inclusive descendant navigables otherwise.
Add a step after step 22.8.2 (Let finalSandboxFlags be the union...) that reads:
-
If sourceSnapshotParams’s target fenced frame config is not null, and if sourceSnapshotParams’s target fenced frame config's effective sandboxing flags is not null, then set finalSandboxFlags to the union of finalSandboxFlags and sourceSnapshotParams’s target fenced frame config's effective sandboxing flags' value.
Note: This ensures that the finalSandboxFlags are at least as restrictive as the effective sandboxing flags defined in the target fenced frame config. A separate check in the blocked by sandboxing flags? algorithm will make sure that finalSandboxFlags is not more restrictive than the effective sandboxing flags.
The below patches make use of the previously-assigned target fenced frame config, instantiating it in preparation for use when the navigation is finalized.
- fenced frame config instance
-
A fenced frame config instance or null, initially null.
Note: This is only set for embedder-initiated
fencedframe
navigations, and if a newDocument
is created as a result of such a navigation, this member is transferred to the new fenced navigable's active browsing context's fenced frame config instance member.
- fenced frame config instance
-
If sourceSnapshotParams’s target fenced frame config is null, then null; otherwise, the result of instantiating sourceSnapshotParams’s target fenced frame config.
Finally, the below patches make use of the navigation params's fenced frame config instance, and handle the assignment of a browsing context's fenced frame config instance that is initiated by a navigation.
Note: A browsing context's fenced frame config instance is assigned in two
different ways: (1) during embedder-initiated fencedframe
navigation, as described by the rest
of this section, and (2) inherited during initial Document
creation for Document
s in child
navigables whose traversable navigable is a fenced
navigable, as handled in the § 3.3 Modifications to creating browsing contexts section.
For any successful navigation inside of a fencedframe
, regardless of whether it was initiated by
content in the fencedframe
or its embedder, exactly one of two things will happen:
-
Embedder-initiated navigations: The navigation params's fenced frame config instance will be unconditionally assigned to the
fencedframe
's fenced navigable container's fenced navigable's active browsing context's fenced frame config instance. -
Inner-content-initiated navigations: The fenced frame config instance referenced in the immediately-preceding point persists through this kind of cross-
Document
navigation.
-
If navigationParams’s fenced frame config instance is not null:
-
Assert: browsingContext does not equal navigationParams’s navigable's active browsing context.
Note: This is because embedder-initiated navigations (indicated by navigationParams’s fenced frame config instance being non-null) always cause a § 3.8.6 Browsing context group swap.
-
Set navigationParams’s fenced frame config instance's cross-origin reporting allowed to the result of running get a structured field value on navigationParams’s response's header list given `
Allow-Cross-Origin-Event-Reporting
` and "item
". -
Set browsingContext’s fenced frame config instance to navigationParams’s fenced frame config instance.
-
Add a new step after step 9 that reads:
-
Let automaticBeaconsAllowed be the result of running get a structured field value on navigationParams’s response's header list given `
Allow-Fenced-Frame-Automatic-Beacons
` and "item
".
Further rewrite step 10 (now step 12) to return a new Document
with an additional parameter:
- automatic beacons allowed
-
automaticBeaconsAllowed.
3.8.6. Browsing context group swap
When the embedder of a fencedframe
initiates navigations inside the frame, we must perform a browsing context group swap to entirely reset the context inside the frame, to ensure nothing is
left over to be leaked to the next Document
.
-
If all of the following conditions are true:
-
navigable is a fenced navigable;
-
sourceSnapshotParams’s fetch client is not navigable’s active document's relevant settings object;
-
navigationParams is non-null
then set navigationParams’s COOP enforcement result's needs a browsing context group switch boolean to true.
This indeed works, but we should consider using a separate mechanism to carry this out, instead of piggybacking off of the COOP mechanism which was designed without fenced frames in mind, and could evolve in ways that give this specification unwanted side-effects.
-
3.8.7. The "_unfencedTop
" navigation target
Fenced frames use an additional reserved navigation target "_unfencedTop
" to navigate.
This section patches the relevant portions of the [HTML] spec to add support for this new
reserved keyword.
_unfencedTop
".
Modify the below paragraph to replace the following text:
-
"top" means the top-level traversable of the navigable that the link or script is in,
with:
-
"top" means the traversable navigable of the navigable that the link or script is in, "outermost top" means the top-level traversable of the navigable that the link or script is in,
Note: This change is necessary because this spec adds a distinction between traversable navigable and top-level traversable, which were previously functionally equivalent.
In the table below, add a column named "Effect in a fenced frame". The value for all existing rows in this column is the same as "ordinary effect". Then, add two rows which read:
Keyword | Ordinary effect | Effect in an iframe with...
| Effect in a fencedframe >
| |
---|---|---|---|---|
sandbox=""
| sandbox="allow-top-navigation"
| |||
_unfencedTop if outermost top is current
| new | maybe new | maybe new | current |
_unfencedTop if outermost top is not current
| new | maybe new | maybe new | outermost top |
6.5. Otherwise, if name is an ASCII case-insensitive match for "_unfencedTop"
and currentNavigable’s traversable navigable is a fenced
navigable, set chosen to currentNavigable’s top-level traversable.
3.9. Page visibility
The Page visibility section of [HTML] is modified such that the first step of the algorithm that runs when a user-agent changes a traversable navigable's system visibility state calls the inclusive descendant navigables algorithm with unfenced set to true.
3.10. Events
3.10.1. onfencedtreeclick
event handler
The table in the event handlers on elements, Document objects, and Window objects section of [HTML] is modified to include a new row.
Event handler | Event handler event type |
---|---|
onfencedtreeclick
| fencedtreeclick
|
The GlobalEventHandlers
interface is modified as follows:
partial interface mixin GlobalEventHandlers {attribute EventHandler ; };
onfencedtreeclick
Additionally, the list of event handler content attributes which may be specified on any HTML element in [HTML] is modified to include a new row:
3.10.2. fencedtreeclick
event type
The Events table in the Index section of [HTML] is
modified to include a new row.
Event | Interface | Interesting targets | Description |
---|---|---|---|
fencedtreeclick
| Event
| Elements | Fired at a fencedframe element asynchronously after its fenced navigable's Document calls notifyEvent()
|
4. Interactions with other specifications
Due to the necessarily cross-cutting nature of the fencedframe
element and its interactions with
core concepts like navigable and browsing context group, there are a number of
specifications that rely on terms whose usages must be re-evaluated in light of this specification;
this section houses the various changes that we propose to other specifications.
4.1. Prerendering
The Prerendering Revamped specification defines navigable's loading mode and the values it can take on. Our specification adds another value for fenced frames:
- "
fencedframe
" -
This navigable is displaying a
fencedframe
's content
Specify the behavior that leads to the following:
4.2. Content Security Policy
This introductory section is non-normative.
Content Security Policy [CSP] can ordinarily be used by web content associated with a Document
that hosts a navigable container to limit the source of navigations in a child
navigable.
In order to prevent [CSP] from being used a communication side-channel exposing the URL of
navigations inside a fencedframe
to the site operating its embedder, the only source
expressions that can influence a fencedframe
navigation are:
-
The scheme-source "
https:
" -
The host-source "
https://*:*
" -
The string "
*
"
See our CSP explainer that describes this.
4.2.1. Algorithms
-
If request’s destination is "
fencedframe
", and this directive’s value does not contain either "https:
", "https://*:*
", or "*
", return "Blocked
".
-
If request destination is "
fencedframe
", and this directive’s value does not contain either "https:
", "https://*:*
", or "*
", return "Blocked
".
Next, we modify the behavior of the [CSPEE] specification. If the embedding frame specifies a required CSP, fenced frames will not load. This is done to prevent arbitrary data flow from the embedder to the fenced frame.
-
If context’s required csp is not
null
, and request destination is "fencedframe
", return "Blocked
".
4.2.2. New fenced-frame-src [CSP] directive
Since fencedframe
is a different element than iframe
, using the frame-src directive wouldn’t give web sites enough control over their CSP rules. Introduce a new [CSP] directive: fenced-frame-src. The monkey-patched specification is printed below:
fencedframe
's fenced navigable. The syntax for the directive’s
name and value is described by the following ABNF:
directive-name = "fenced-frame-src" directive-value = serialized-source-list
Content-Security-Policy: fenced-frame-src https://example.com/
Fetches for the following code will return a network error, as the URL provided does not
match fenced-frame-src
’s source list:
< fencedframe src = "https://example.org/" > </ fencedframe >
The Pre-request check and Post-request check will be the same as the frame-src’s check.
Content-Security-Policy: connect-src 'self'; ... worker-src 'self'
It will now say:
Content-Security-Policy: connect-src 'self'; ... fenced-frame-src 'self'; ... worker-src 'self'
- "
fenced-frame-src
" -
-
Return
<< "fenced-frame-src", "frame-src", "child-src", "default-src" >>
.
-
- "
fencedframe
" -
-
Return
fenced-frame-src
.
-
Tests
- ancestor-throttle.https.html (live test) (source)
- csp-allowed.https.html (live test) (source)
- csp-blocked.https.html (live test) (source)
- csp-fenced-frame-src-allowed.https.html (live test) (source)
- csp-fenced-frame-src-blocked.https.html (live test) (source)
- csp-frame-src-allowed.https.html (live test) (source)
- csp-frame-src-blocked.https.html (live test) (source)
- csp-allowed-transparent.https.html (live test) (source)
- csp-blocked-transparent.https.html (live test) (source)
- csp.https.html (live test) (source)
- cspee.https.html (live test) (source)
- embedder-csp-not-propagate.https.html (live test) (source)
4.3. Permissions Policies
This introductory sub-section is non-normative.
The policy-controlled features available to Document
s inside of a fencedframe
, as well
as the manner in which they are calculated, vary depending on how the fenced frame config that
the fencedframe
navigates to is constructed.
A fenced frame config instance created via the FencedFrameConfig
constructor on the web
platform will have a flexible permissions policy
behavior, and the inner Document
of the fencedframe
it navigates will be allowed to
inherit permissions as long as they are part of the fenced frame allowed permissions list. All
other policy-controlled features will be disabled.
A fenced frame config instance created via a config-generating API that sets its effective enabled permissions will have a fixed permissions policy behavior, and the inner Document
of the fencedframe
it navigates to will have the effective enabled permissions be the exclusive
list of policy-controlled features that will be enabled in the Document
(all others will be
disabled).
During a fencedframe
navigation to a fenced frame config instance with a fixed permissions policy behavior, it compares the effective enabled permissions of the fenced frame config instance being
navigated to against the resulting Document
's permissions policy's inherited policy. The navigation only succeeds if each inherited feature whose inherited policy value is "Enabled
" also appears in the effective enabled permissions fenced frame config instance. Otherwise, the
environment the fencedframe
is embedded in is deemed unsuitable for the fenced frame config,
and the navigation is blocked.
At the same time, to make sure that a fencedframe
's embedder does not directly influence content
in the frame based on that navigation’s origin (since the origin is derived
from cross-site data), this specification modifies various [PERMISSIONS-POLICY] algorithms such
that a fencedframe
Document
's inherited policy is computed without
consideration of whether its origin is same origin with its embedder’s.
Therefore a feature can only be enabled inside of a fencedframe
if its embedder explicitly delegates it via the special value * allowlist.
Considering all of the above, we get the following interesting implications for fixed permissions policy behavior navigations:
-
If a feature that exists in the effective enabled permissions has a default allowlist of the special value *, and no `
Permissions-Policy
` header is served on thefencedframe
embedder, and theallow
attribute is empty, the navigation inside thefencedframe
will succeed, and the resultingDocument
will be allowed to use the feature (i.e., it will be enabled). -
If a feature that exists in the effective enabled permissions has a default allowlist of
'self'
, and no `Permissions-Policy
` header is served on thefencedframe
embedder, and theallow
attribute is empty, the navigation inside thefencedframe
will be blocked.Note: This is because ordinarily this feature would only be enabled if the subframe’s
Document
was same origin with its embedder, a check this specification avoids for fenced frames, since thefencedframe
sDocument
's origin is derived from cross-site data. Therefore, we simply "fail close". -
If a feature that exists in the effective enabled permissions has a default allowlist of
'self'
, and thefencedframe
'sallow
attribute contains the feature but no allowlist, the rules described in Theallow
attribute section, the default allowlist for the feature will be'src'
which is meant to represent the embedder-supplied navigation URL, for which there is none when navigating afencedframe
, as the navigation URL is determined by the fenced frame config. The navigation will be blocked. -
If a feature that exists in the effective enabled permissions has a default allowlist of
'self'
but either the `Permissions-Policy
` header served on thefencedframe
's embedder OR theallow
attribute sets that feature's allowlist to the special value *, then the navigation inside thefencedframe
will succeed, and the resultingDocument
is allowed to use the feature. -
If a navigation inside a
fencedframe
would otherwise succeed, but the response on the navigation inside thefencedframe
is served with a `Permissions-Policy
` header that sets the allowlist to "none
" or an otherwise incompatible origin for a feature in the effective enabled permissions, the navigation still succeeds, but theDocument
in thefencedframe
is not allowed to use the feature.Note: This is OK because it is the
fencedframe
's content itself that is making the decision to disable a particular feature, not its embedder environment.
The patches in the below section "fence" the appropriate [PERMISSIONS-POLICY] and [HTML] algorithms to achieve the outcomes described in the above explanatory content.
4.3.1. Definitions
The fenced frame allowed permissions are either "private-aggregation
",
"shared-storage
", or "shared-storage-select-url
".
4.3.2. Algorithm patches
allow
attribute of the iframe
element section to "The allow
attribute of the iframe
and fencedframe
element", and rewrite the section to read:
iframe
and fencedframe
elements have an respective allow
attributes (iframe
: allow
; fencedframe
: allow
), which contain an ASCII-serialized
policy directive.
The allowlist for the features named in the attribute may be empty; in that case, the default
value for the allowlist is "src
", which represents the origin of the URL in the iframe’s src
attribute, or the fencedframe’s fenced frame config.
When not empty, the iframe
's allow
or fencedframe
's allow
attribute will result in adding an allowlist for each supported feature to the iframe
or fencedframe
's container policy, when it is constructed.
Given a fenced navigable container (container) and an origin (origin), this algorithm returns a new Permissions Policy.
-
Let fencedFrameConfig be container’s node document's active browsing context's fenced frame config instance.
-
Let inheritedPolicy be a new ordered map.
-
If fencedFrameConfig is not null and fencedFrameConfig’s permissions policy behavior is fixed, then:
-
-
If fencedFrameConfig’s effective enabled permissions contains feature, then set inheritedPolicy[feature] to "
Enabled
".Otherwise, set inheritedPolicy[feature] to "
Disabled
".
Note: While this doesn’t take the
allow
attribute into consideration, it will have already been checked by the time this is called because of Should navigation response to navigation request be blocked by Permissions Policy?. Any policy specified inallow
that is too restrictive would have cause the fenced frame to not load, and any policy that is more permissive than what is specified in the effective enabled permissions will be ignored. -
-
-
Otherwise:
-
-
If feature matches one of the fenced frame allowed permissions, then set inheritedPolicy[feature] to the result of running Define an inherited policy for feature in container at origin given feature, container, and origin.
Otherwise, set inheritedPolicy[feature] to "
Disabled
".
-
-
-
Let policy be a new permissions policy, with inherited policy inheritedPolicy and declared policy initialized to two new ordered maps.
-
Return policy.
Given null or an element (container), an origin (origin), and an optional boolean matchAll that defaults to false, this algorithm returns a new permissions policy.
Rewrite step 1 to read:
-
Assert: if not null, container is either a navigable container or a fenced navigable container.
Rewrite step 3 to read:
-
-
Let isInherited be the result of running Define an inherited policy for feature in container at origin on feature, container, origin, and matchAll.
-
Set inherited policy[feature] to isInherited.
-
Given null, a navigable container-or-fenced navigable container (container), an origin (origin), and a response (response), this algorithm returns a new permissions policy.
Rewrite step 1 to read:
-
If container is a fenced navigable container, then let policy be the result of running create a permissions policy for a fenced navigable given container and origin.
Otherwise, Let policy be the result of running Create a Permissions Policy for a navigable given container and origin.
-
If element is not an
iframe
element or afencedframe
element, then return an empty policy directive.
-
The result of should navigation response to navigation request be blocked by Permissions Policy? given navigationParams is "
Blocked
"; -
The result of should navigation response to navigation request be blocked by sandboxing flags? given navigationParams and sourceSnapshotParams is "
Blocked
";
Note: If any of these algorithms returns "Blocked
", the pre-existing Document
in the fencedframe
does not stick around; an error page will be loaded.
Given a navigation params (navigationParams), this algorithm returns "Blocked
" or
"Allowed
":
-
Let navigable be navigationParams’s navigable.
-
If navigable is not a fenced navigable, then return "
Allowed
". -
Let origin be navigationParams’s origin.
-
Let effective permissions be the navigable’s active browsing context's fenced frame config instance's effective enabled permissions.
Per work omitted in pull request #84, the config instance has not yet been assigned to the browsing context. We should consider storing the instance inside navigationParams and reference it from here instead.
-
Let permissionsPolicy be the result of creating a permissions policy given navigable’s fenced navigable container, origin, and true.
Note: This is almost identical to the permissions policy that will be created when the navigation constructs the ultimate
Document
for this pending navigation. The difference is that this algorithm, just like when it is called on iframes, will include all of the permissions specified in theallow
attribute, even if that permission isn’t specified in the fenced frame config's effective enabled permissions. We create it now and run tests on it since this is the appropriate time to determine if a navigation will fail, and then throw it away. If the navigation succeeds, it will be recreated and unconditionally installed on theDocument
. However, the recreation will not include any additional enabled permissions that are not included in the effective enabled permissions, effectively locking the enabled permissions to only what is specified in effective enabled permissions. -
Let inheritedPolicy be permissionsPolicy’s inherited policy.
-
For each effective permission of effective permissions:
-
If inheritedPolicy[effective permission] is "Disabled", return "
Blocked
".
-
-
Return "
Allowed
."
Given a navigation params (navigationParams) and a source snapshot params (sourceSnapshotParams), this algorithm returns "Blocked
" or "Allowed
":
-
Let navigable be navigationParams’s navigable.
-
If navigable is not a fenced navigable, then return "
Allowed
". -
Let effectiveSandboxingFlags be the sourceSnapshotParams’s target fenced frame config's effective sandboxing flags.
-
If navigationParams’s final sandboxing flag set is not a subset of effectiveSandboxingFlags, then return "
Blocked
".Note: This means that the final sandboxing flag set cannot restrict a feature that isn’t already restricted in the effective sandboxing flags, as the extra restrictions can be used as a communication channel. By this point, the final sandboxing flag set will already have been set to something at least as restrictive as the effective sandboxing flags.
-
Otherwise, return "
Allowed
".
Given a feature (feature), null or a navigable container (container), an origin for a document in that container (origin), and an optional boolean matchAll that defaults to false, this algorithm returns the inherited policy for that feature.
Rewrite step 3 to read:
-
If the result of executing Is feature enabled in document for origin? on feature, container’s node document, origin, and matchAll is "Disabled", return "Disabled".
Note: We don’t have to rewrite step 2, which also delegates to the same algorithm, to pass in the matchAll boolean because step 2 has to do with checking to see if feature is enabled container’s node document, not the Document
hosted inside container.
Rewrite step 7 to read:
-
If matchAll is false, feature’s default allowlist is
'self'
, and origin is same origin with container’s node document's origin, return"Enabled"
.
Given a feature (feature), a Document
object (document), an origin (origin), and
an optional boolean matchAll that defaults to false, this algorithm returns "Disabled
" if feature should be considered disabled, and "Enabled
" otherwise.
Rewrite step 3 to read:
-
If feature is present in policy’s declared policy,
-
If matchAll is false, and the allowlist for feature in policy’s declared policy matches origin, then return "
Enabled
". -
Otherwise, if matchAll is true, and the allowlist for feature in policy’s declared policy is the special value *, then return "
Enabled
". -
Otherwise, return "
Disabled
".
-
Rewrite step 5 to read:
-
If matchAll is false, feature’s default allowlist is
'self'
, and origin is same origin with document’s origin, return "Enabled".
-
If node’s node document's browsing context's fenced frame config instance is not null, then return node’s node document's browsing context's fenced frame config instance's mapped url.
Note: This ensures that the 'src'
allowlist that can be set in the allow
attribute works when using a fenced frame config to navigate a fencedframe
(or a urn that
maps to a fenced frame config to navigate an iframe
).
Tests
- allow-attribute-src.https.html (live test) (source)
- default-enabled-features-allow-all.https.html (live test) (source)
- default-enabled-features-allow-none.https.html (live test) (source)
- default-enabled-features-allow-self.https.html (live test) (source)
- default-enabled-features-attribute-allow.https.html (live test) (source)
- default-enabled-features-attribute-change.https.html (live test) (source)
- default-enabled-features-attribute-disallow.https.html (live test) (source)
- default-enabled-features-attribution-disabled.https.html (live test) (source)
- default-enabled-features-subframe.https.html (live test) (source)
- default-enabled-features-unset.https.html (live test) (source)
- permission-api-denied-non-standard.https.html (live test) (source)
- permission-api-denied.https.html (live test) (source)
- permission-geolocation.https.html (live test) (source)
- permission-notification.https.html (live test) (source)
4.4. CSSOM View
The [CSSOM-VIEW] specification defines the scrollIntoView()
method that calls the scroll a target into view algorithm. This will not only scroll the Element
or viewport to make the target visible, but will also scroll ancestors if necessary
to make the target visible, essentially causing the scroll to "bubble up". This means that scrollIntoView()
performed in a child navigable or fenced navigable can be observed by its embedder, allowing for collusion across a fenced frame
boundary. This section patches the scroll a target into view algorithm to prevent that collusion
at the expense of some utility.
-
If scrolling box’s associated
Element
's associatedDocument
's node navigable's traversable navigable is a fenced navigable, or if scrolling box’s associated viewport's associatedDocument
's node navigable's traversable navigable is a fenced navigable, then let this be the last instance of this algorithm that stops any further recursive instances that would otherwise follow.
Note: This allows scrolling to "bubble up" to a fenced frame boundary, but not cross it.
4.5. WebRTC
The [WEBRTC] specification defines "ECMAScript APIs in WebIDL to allow media and generic
application data to be sent to and received from another browser or device implementing the
appropriate set of real-time protocols." The interface which facilitates connections to peers is RTCPeerConnection
. Construction of this interface, and therefore connection to peers via
WebRTC, is disallowed in fenced frames.
RTCPeerConnection
constructor
algorithm to add new first and
second steps that read:
-
Let navigable be this's relevant global object's navigable.
-
If navigable is not null and navigable’s traversable navigable is a fenced navigable, throw a
NotAllowedError
DOMException
.
5. Security & Privacy Considerations
This material is being upstreamed from our explainer into this specification, and in the meantime you can consult the following resources: