1. Introduction
This specification describes a content embedding API that satisfies some
critical use cases for IWAs that iframe
does not support. This embedding
environment should allow embedding all content without express permission from
the embedded site, including content which iframe
cannot embed, and provide
embedding sites more control over that embedded content.
Since this is a particularly powerful API, its use and availability makes an app a target of various types of hacking. As a result, this API is limited to use in Isolated Web Applications (IWAs) which have addtional safeguards in place to protect users and developers. IWAs are not a normal web application and can exist only at a special 'isolated-app:' scheme. This means by design that this API will not be available to normal web pages.
Note: This API is not intended to be a replacement or substitute for iframe
.
All iframe
use cases are still valid and should continue to use iframe
,
including IWAs where possible.
2. The Fenced Frame specification
For convenience, the Controlled Frame specification assumes that the Fenced Frame specification is in place. There are concepts introduced in the Fenced Frame specification, such as nested top-level traversables, that are broadly useful to refer to in the context of Controlled Frame.
The Fenced Frame specification achieves defining these concepts via monkey patching some specifications, such as HTML. We will also require monkey patching specifications for some parts of this Controlled Frame specification.
3. The controlledframe
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
src
— Content source URL to embedpartition
— Partition name to hold data related to this content - Accessibility considerations:
- For authors.
- For implementers.
Note: These link to the accessibility definitions of the
iframe
element. From an accessibility perspective, acontrolledframe
should behave the same as aniframe
. - For implementers.
- DOM interface:
-
[
Exposed =Window ,IsolatedContext ]interface
:HTMLControlledFrameElement HTMLElement { [HTMLConstructor ]constructor (); [CEReactions ]attribute USVString src ;attribute DOMString partition ;readonly attribute WindowProxy ?contentWindow ;readonly attribute ContextMenus contextMenus ;readonly attribute WebRequest request ; // Navigation methods.Promise <boolean >back ();boolean canGoBack ();boolean canGoForward ();Promise <boolean >forward ();Promise <boolean >go (long
);relativeIndex undefined reload ();undefined stop (); // Scripting methods.Promise <undefined >addContentScripts (sequence <ContentScriptDetails >
);contentScriptList Promise <any >executeScript (optional InjectDetails
= {});details Promise <undefined >insertCSS (optional InjectDetails
= {});details Promise <undefined >removeContentScripts (optional sequence <DOMString >
); // Configuration methods.scriptNameList Promise <undefined >clearData (optional ClearDataOptions
= {},options optional ClearDataTypeSet
= {});types Promise <boolean >getAudioState ();Promise <long >getZoom ();Promise <DOMString >getZoomMode ();Promise <boolean >isAudioMuted ();undefined setAudioMuted (boolean
);mute Promise <undefined >setZoom (long
);zoomFactor Promise <undefined >setZoomMode (DOMString
); // Capture methods.zoomMode Promise <undefined >captureVisibleRegion (optional ImageDetails
= {});options undefined print (); // Events.attribute EventHandler onconsolemessage ;attribute EventHandler oncontentload ;attribute EventHandler ondialog ;attribute EventHandler onloadabort ;attribute EventHandler onloadcommit ;attribute EventHandler onloadstart ;attribute EventHandler onloadstop ;attribute EventHandler onnewwindow ;attribute EventHandler onpermissionrequest ;attribute EventHandler onsizechanged ;attribute EventHandler onzoomchange ; };
The controlledframe
element represents its embedded navigable.
Descendents of controlledframe
elements represent nothing.
The Controlled Frame element is exposed to any Document
with the
"controlled-frame
" policy-controlled feature whose environment settings object is an isolated context.
The IDL attributes src
and partition
must reflect the respective content attributes of the same name.
Each controlledframe
has an associated:
-
embedded navigable, a traversable navigable with a non-null embedderParent, or null. It is initially null.
Note: The embedded navigable appears as a top-level traversable with a null parent. Content within the embedded navigable cannot detect that it is embedded.
-
content script map, a map whose keys are
DOMString
s and whose values are content script configs. -
contentWindow, a
WindowProxy
or null. -
request, a
WebRequest
. -
contextMenus, a
ContextMenus
.
The contentWindow
getter
steps are to return this’s contentWindow.
The request
getter steps
are to return this’s request.
The contextMenus
getter
steps are to return this’s contextMenus.
controlledframe
element element is inserted into a document whose browsing context is non-null, run the following steps:
-
If element’s
src
is not empty, then:-
Initialize a controlledframe given element.
-
controlledframe
element element is removed from a document,
run the following steps:
-
Destroy a top-level traversable given element’s embedded navigable.
-
Set element’s embedded navigable to null.
controlledframe
element element, run the
following steps:
-
Assert that element’s embedded navigable is null.
-
Let group be a new browsing context group.
-
Let document be the second return value of creating a new browsing context and document given element’s node document, element, and group.
-
Let documentState be a new document state, whose document is document.
-
Let traversable be a new traversable navigable.
-
Initialize the navigable traversable given documentState.
-
Set traversable’s embedderParent to element.
-
Set element’s embedded 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.
These steps are needed to initialize
History
.length
in the new navigable. This is an existing issue in the HTML Standard. -
Set element’s contentWindow to document’s
WindowProxy
. -
Navigate a controlledframe given element and element’s
src
.
controlledframe
element element given a USVString
urlString, run the following steps:
-
If urlString is not an absolute-URL string, return.
-
Let url be the result of parsing a URL given urlString and element’s node document.
-
Let historyHandling be "
auto
". -
If element’s embedded navigable’s active document is not completely loaded, then set historyHandling to "
replace
". -
Navigate element’s embedded navigable to url using element’s node document, with a
NavigationHistoryBehavior
of historyHandling.
HTMLControlledFrameElement()
constructor steps are:
-
Let webRequest be a new
WebRequest
. -
Let onBeforeRequest be a new
WebRequestEvent
with the following fields:- eventName
-
"
beforeRequest
" - webRequest
-
webRequest
-
Set webRequest’s onBeforeRequest to onBeforeRequest.
-
Let onBeforeSendHeaders be a new
WebRequestEvent
with the following fields:- eventName
-
"
beforeSendHeaders
" - webRequest
-
webRequest
-
Set webRequest’s onBeforeSendHeaders to onBeforeSendHeaders.
-
Let onSendHeaders be a new
WebRequestEvent
with the following fields:- eventName
-
"
sendHeaders
" - webRequest
-
webRequest
-
Set webRequest’s onSendHeaders to onSendHeaders.
-
Let onHeadersReceived be a new
WebRequestEvent
with the following fields:- eventName
-
"
headersReceived
" - webRequest
-
webRequest
-
Set webRequest’s onHeadersReceived to onHeadersReceived.
-
Let onAuthRequired be a new
WebRequestEvent
with the following fields:- eventName
-
"
authRequired
" - webRequest
-
webRequest
-
Set webRequest’s onAuthRequired to onAuthRequired.
-
Let onBeforeRedirect be a new
WebRequestEvent
with the following fields:- eventName
-
"
beforeRedirect
" - webRequest
-
webRequest
-
Set webRequest’s onBeforeRedirect to onBeforeRedirect.
-
Let onResponseStarted be a new
WebRequestEvent
with the following fields:- eventName
-
"
responseStarted
" - webRequest
-
webRequest
-
Set webRequest’s onResponseStarted to onResponseStarted.
-
Let onCompleted be a new
WebRequestEvent
with the following fields:- eventName
-
"
completed
" - webRequest
-
webRequest
-
Set webRequest’s onCompleted to onCompleted.
-
Let onErrorOccurred be a new
WebRequestEvent
with the following fields:- eventName
-
"
errorOccurred
" - webRequest
-
webRequest
-
Set webRequest’s onErrorOccurred to onErrorOccurred.
-
Let contextMenus be a new
ContextMenus
. -
Let onClicked be a new
OnClickedEvent
. -
Set contextMenus’s onClicked to onClicked.
-
Let onShow be a new
OnShowEvent
. -
Set contextMenus’s onShow to onShow.
-
Set this’s contextMenus to contextMenus.
3.1. Common infrastructure
controlledframe
controlledframe, a promise promise, and an optional value,
run the following steps:
-
Queue a global task on the DOM manipulation task source of controlledframe’s relevant global object to resolve promise with value.
Note: The relevant global object of controlledframe is the embedder’s
Window
object.
controlledframe
controlledframe, a promise promise, and an optional value,
run the following steps:
-
Queue a global task on the DOM manipulation task source of controlledframe’s relevant global object to reject promise with value.
Note: The relevant global object of controlledframe is the embedder’s
Window
object.
A match pattern is a USVString
that represents a group of URLs.
It follows the structure of a URL with wildcards ("*"
) in supported
locations.
USVString
url matches a match pattern pattern if the following steps return true
:
Match patterns should have a formal specification. Documentation exists on MDN, and all browsers that support Web Extensions will already have a Match Pattern implementation that can be reused here.
3.2. Attributes
The partition
attribute
takes an identifier specifying where data related to the Controlled Frame’s
instance should be stored. The identifier is composed of a string of
alphanumeric characters. All data for the embedded navigable must be stored
in a storage shelf keyed by this partition string along with the origin
that created the data.
By default, all data stored must be held in an in-memory storage partition so
that when the last Controlled Frame element with a given partition
value is destroyed, the data is also
destroyed. While the data is held in this partition, no data from the
Controlled Frame’s embedded navigable shall persist.
If the partition attribute identifier contains the prefix "persist:", the user agent must use a disk-based storage environment rather than an in-memory storage partition. Embedded content should not be able to detect whether its storage is in-memory or persistent.
If multiple Controlled Frames share the same partition identifier, all of their embedded navigable instances must share the same storage partition.
Note: The [STORAGE] specification is monkey patched below to partition
storage based on the value of the partition
attribute.
partition
IDL attribute setter steps are:
-
If this’s embedded navigable is not null, then:
The src
attribute reflects the Controlled
Frame’s embedded navigable’s current session history entry’s URL.
src
IDL attribute setter steps are:
-
If this is not in a document tree, then return.
-
If this’s embedded navigable is null, then:
-
Initialize a controlledframe given this.
-
-
Otherwise:
-
Navigate a controlledframe given this and the given value.
-
3.3. Navigation methods
back
()-
Goes back one step in the overall session history entries list for the traversable navigable in the Controlled Frame.
Returns a promise that resolves to
true
if the page was successfully navigated back, orfalse
if the navigation failed or there was no previous step. canGoBack
()-
Returns
true
if the current session history entry is not the first one in the embedded navigable’s session history entries. This means that there is a previous session history entry for the navigable. forward
()-
Goes forward one step in the overall session history entries list for the traversable navigable in the Controlled Frame.
Returns a promise that resolves to
true
if the page was successfully navigated forward, orfalse
if the navigation failed or there was no next step. canGoForward
()-
Returns
true
if the current session history entry is not the last one in the embedded navigable’s session history entries. This means that there is a next session history entry for the navigable. go
()-
Reloads the current page.
go
(relativeIndex)-
Goes back or forward relativeIndex number of steps in the overall session history entries list for the current traversable navigable.
A zero relative index will reload the current page.
Returns a promise that resolves to
true
if the page was successfully navigated, orfalse
if the navigation failed or the provided relative index was out of range. reload
()-
Reloads the current page.
stop
()-
Cancels the document load.
controlledframe
controlledframe and an integer delta, run the
following steps:
-
Let resultPromise be a new promise.
-
Return resultPromise and run the remaining steps in parallel.
-
Let embeddedNavigable be controlledframe’s embedded navigable.
-
If embeddedNavigable is null, then resolve an embedder promise given controlledframe, resultPromise, and
false
, and abort these steps. -
If embeddedNavigable’s active document is not fully active, then resolve an embedder promise given controlledframe, resultPromise, and
false
, and abort these steps. -
Append the following session history traversal steps to embeddedNavigable:
-
Let allSteps be the result of getting all used history steps for embeddedNavigable.
-
Let currentStepIndex be the index of embeddedNavigable’s current session history step within allSteps.
-
Let targetStepIndex be currentStepIndex + delta.
-
If allSteps[targetStepIndex] does not exist, then resolve an embedder promise given controlledframe, resultPromise, and
false
, and abort these steps. -
Let result be the result of applying the traverse history step allSteps[targetStepIndex] to embeddedNavigable given a user navigation involvement of "none".
-
If result is not equal to "
applied
", then resolve an embedder promise given controlledframe, resultPromise, andfalse
. -
Otherwise, resolve an embedder promise given controlledframe, resultPromise, and
true
.
-
canGoBack()
method steps are:
We can’t actually synchronously access the embedded navigable’s history state. In the future we should update this method to return a Promise.
-
If this’s embedded navigable is null, then return
false
. -
If this’s embedded navigable’s current session history step is > 0, return
true
. -
Return
false
.
canGoForward()
method steps are:
-
If this’s embedded navigable is null, then return
false
. -
Let step be this’s embedded navigable’s current session history step.
-
Let steps be the result of getting all used history steps given this’s embedded navigable.
-
If step + 1 < the size of steps, then return
true
. -
Return
false
.
back()
method steps are:
-
Return the result of delta traverse an embedded navigable’s history given this and -1.
forward()
method steps
are:
-
Return the result of delta traverse an embedded navigable’s history given this and 1.
go(relativeIndex)
method steps are:
-
Return the result of delta traverse an embedded navigable’s history given this and relativeIndex.
reload()
steps are:
-
Let embeddedNavigable be this’s embedded navigable.
-
If embeddedNavigable is null, return.
-
Queue a global task on the navigation and traversal task source of embeddedNavigable’s node document’s relevant global object that will reload embeddedNavigable given a user navigation involvement of "none".
stop()
steps are:
-
Let embeddedNavigable be this’s embedded navigable.
-
If embeddedNavigable is null, return.
-
Queue a global task on the navigation and traversal task source of embeddedNavigable’s node document’s relevant global object that will stop loading embeddedNavigable.
3.4. Scripting methods
// One of |code| or |file| must be specified but not both.dictionary {
InjectDetails DOMString ;
code USVString ; };
file dictionary {
InjectionItems DOMString ;
code sequence <USVString >; };
files enum {
RunAt ,
"document-start" ,
"document-end" , };
"document-idle" dictionary {
ContentScriptDetails required DOMString ;
name InjectionItems ;
js InjectionItems ;
css required sequence <DOMString >;
matches sequence <DOMString >;
excludeMatches boolean ;
allFrames boolean ;
matchAboutBlank RunAt ; };
runAt
A content script config is a struct with the following items:
- pendingFetchCount
-
a
long
representing the number of pending script/style fetches. - js
-
a list of
DOMString
s containing JavaScript that will be injected into a document. - css
-
a list of
DOMString
s containing CSS that will be injected into a document. - matches
-
a list of
USVString
s containing match patterns.Note: Content may be injected into a document if its URL matches any of these patterns.
- excludeMatches
-
a list of
USVString
s containing match patterns.Note: Content will not be injected into a document if its URL matches any of these patterns. This overrides matches; if both lists have entries that a document’s URL matches, the content will not be injected into the document.
- allFrames
-
a boolean indicating whether content should be injected into all frames in a page, or just the top-level frame.
- matchAboutBlank
-
a boolean indicating whether content should be injected into about:blank pages.
- runAt
-
a
RunAt
indicating when JavaScript content should be executed in a document’s lifecycle.
controlledframe
controlledframe, a USVString
urlString, a boolean isCss, a long
index, and an algorithm completionSteps that takes a long
,
a boolean
, and a DOMString
, run the following steps:
Note: Fetch a classic script cannot be used here because the fetch needs to use controlledframe’s relevant settings object, but the classic script is executed using the embedded navigable’s active document’s relevant settings object.
-
If urlString is not an valid URL string, then:
-
Run completionSteps given 0,
false
, and "". -
Return.
-
-
Let request be a new request with the following fields:
- URL
-
The result of parsing a URL given urlString and controlledframe’s node document.
- method
-
"
GET
" - destination
-
"
style
" if isCss istrue
, "script
" otherwise - client
-
controlledframe’s relevant settings object
- mode
-
"
cors
"
-
Fetch request, with processResponseConsumeBody set to the following steps given a response response and a null, failure, or byte sequence contents:
-
If response’s status is not 200, or contents is null or failure, then run completionSteps given 0,
false
, and "" -
Otherwise, run completionSteps given index,
true
, and contents.
-
ContentScriptDetails
given a controlledframe
controlledframe and a ContentScriptDetails
details, run the following steps:
-
Let result be a new promise.
-
If details["
js
"] and details["css
"] are both defined, or both undefined, then reject result with aTypeError
and return it. -
If details["
matches
"] is empty, then reject result with aTypeError
and return it. -
Let isCss be a boolean equal to
true
if details["css
"] is defined,false
otherwise. -
If isCss is
true
and details["runAt
"] does not equal "document-start
", then reject result with aTypeError
and return it. -
Let injectionItems be details["
css
"] if isCss istrue
, details["js
"] otherwise. -
If injectionItems["
code
"] and injectionItems["files
"] are both defined, or both undefined, reject result with aTypeError
and return it. -
Return result and run the remaining steps in parallel.
-
Let config be a new content script config with the following values:
- pendingFetchCount
-
0
- matches
-
details["
matches
"] - excludeMatches
-
details["
excludeMatches
"] if defined, otherwise an empty list - allFrames
-
details["
allFrames
"] if defined, otherwisefalse
- matchAboutBlank
-
details["
matchAboutBlank
"] if defined, otherwisefalse
- runAt
-
details["
runAt
"] if defined, otherwisedocument-idle
-
Let completionSteps be the following algorithm, which takes a
long
index, a boolean success, and aDOMString
source:-
If success is
false
, then reject an embedder promise given controlledframe, result, andTypeError
, and abort these steps. -
If isCss, then:
-
Set config’s css[index] to source.
-
-
Otherwise:
-
Set config’s js[index] to source.
-
-
Decrement config’s pendingFetchCount.
-
If config’s pendingFetchCount is greater than 0, then return.
-
Set controlledframe’s content script map[details[
name
]] to config. -
Resolve an embedder promise given controlledframe and result.
-
-
If injectionItems["
code
"] is defined, then:-
Run completionSteps given 0,
true
, and injectionItems ["code
"].
-
-
Otherwise:
-
If injectionItems["
files
"] is empty, then reject an embedder promise given controlledframe, result, andTypeError
, and abort these steps. -
For each urlString of injectionItems ["
files
"]:-
Run fetch an injection item given controlledframe, urlString, isCss, config’s pendingFetchCount, and completionSteps.
-
Increment config’s pendingFetchCount.
-
-
-
If isTopLevel is
false
, and config’s allFrames isfalse
, then returnfalse
. -
If url matches about:blank and config’s matchAboutBlank is
false
, then returnfalse
. -
Let urlString be the result of serializing url.
-
Let match be
false
. -
For each pattern of config’s matches:
-
If urlString matches a match pattern pattern, then set match to
true
.
-
-
For each pattern of config’s excludeMatches:
-
If urlString matches a match pattern pattern, then set match to
false
.
-
-
Return match.
Document
document, and a RunAt
currentPhase, run the following steps:
-
Let embeddedNavigable be document’s node navigable’s traversable navigable.
-
If embeddedNavigable is null or its embedderParent is null, then return.
-
Let controlledframe be embeddedNavigable’s embedderParent.
-
Let url be document’s URL.
-
Let isTopLevel be
true
if document’s node navigable’s parent is null,false
otherwise. -
For each config of controlledframe’s content script map:
-
If the result of determining whether a content script config applies to a document given config, url, and isTopLevel equals
false
, then continue. -
If currentPhase is equal to
document-start
and config’s css is not empty, then:-
For each styleSource of config’s css, run inject a stylesheet into a document given document and styleSource.
-
-
Otherwise, if currentPhase equals config’s runAt, then:
-
For each scriptSource of config’s js, run inject a script into a document given document, scriptSource, and an empty algorithm.
-
-
Document
document and a DOMString
styleSource, run the following steps:
-
Let styleSheet be a new CSS style sheet object.
-
Synchronously replace the rules of a CSSStyleSheet given styleSheet and styleSource.
-
Queue a global task on the DOM manipulation task source of document’s global object to add a CSS style sheet given document and styleSheet.
The following algorithm executes script in a Document’s environment, but that isn’t the desired behavior. The goal, which cannot be specced with the current HTML specification infrastructure, is for this algorithm to execute script in an environment that is isolated from the Document’s environment with a different global object, but with shared access to the DOM. This execution environment is called an Isolated World in Blink, which uses it to execute content scripts in extensions. See this diagram for additional details about their execution model. Gecko uses a similar approach called Xray vision. This algorithm should eventually describe a speccable implementation of this isolation that can be implemented by all browsers.
Document
document,
a DOMString
scriptSource, and an algorithm completionSteps that takes
a completion record, run the following steps:
Note: document.currentScript
is intentionally not set while executing scriptSource.
-
Let script be the result of creating a classic script given scriptSource, document’s relevant settings object, document’s URL, and the default script fetch options.
-
Queue a global task on the DOM manipulation task source of document’s global object that will run the following steps:
-
Let completionRecord be the result of running a classic script given script.
-
Let controlledframe be document’s node navigable’s traversable navigable’s embedderParent.
-
Queue a global task on the DOM manipulation task source of controlledframe’s relevant global object that will run completionSteps with completionRecord.
-
addContentScripts(contentScriptList)
method steps are:
-
If contentScriptList is empty, return a new promise that is rejected with a
TypeError
. -
Let promises be an empty list.
-
For each contentScript in contentScriptList:
-
Let promise be the result of calling validate and resolve ContentScriptDetails given contentScript.
-
Append promise to promises.
-
-
Return the result of getting a promise for waiting for all promises given promises.
removeContentScripts(scriptNameList)
method steps are:
-
Let result be a new promise.
-
Let controlledframe be this.
-
Return result and run the remaining steps in parallel.
-
If scriptNameList is undefined, then:
-
Clear controlledframe’s content script map.
-
-
Otherwise, for each name of scriptNameList:
-
Remove controlledframe’s content script map[name].
-
-
Resolve an embedder promise given controlledframe and result.
executeScript(details)
method steps are:
-
Let result be a new promise.
-
Let controlledframe be this.
-
Return result and run the remaining steps in parallel.
-
If controlledframe’s embedded navigable is null, then reject an embedder promise given controlledframe, result, and a
TypeError
, and abort these steps. -
If details["
code
"] and details"[file
"] are either both defined or both undefined, then reject an embedder promise given controlledframe, result, and aTypeError
, and abort these steps. -
Let executionSteps be the following algorithm that takes a
long
and aDOMString
or boolean scriptString:-
If scriptString is not a
DOMString
, then reject an embedder promise given controlledframe, result, and aTypeError
, and abort these steps. -
Let document be controlledframe’s embedded navigable’s active document.
-
Inject a script into a document given document, scriptString, and the following algorithm that accepts a completion record completionRecord:
-
If completionRecord is a normal completion, then:
-
Resolve an embedder promise given controlledframe, result, and completionRecord.
[[Value]]
.
-
-
Otherwise:
-
Reject an embedder promise given controlledframe, result, and completionRecord.
[[Value]]
.
-
-
-
-
If details["
code
"] is defined, then run executionSteps given 0 and details["code
"]. -
Otherwise, fetch an injection item given controlledframe, details["
file
"],false
, 0, and executionSteps.
insertCSS(details)
method steps are:
-
Let result be a new promise.
-
Let controlledframe be this.
-
Return result and run the remaining steps in parallel.
-
If controlledframe’s embedded navigable is null, then reject an embedder promise given controlledframe, result, and a
TypeError
, and abort these steps. -
If details["
code
"] and details["file
"] are either both defined or both undefined, then reject an embedder promise given controlledframe, result, and aTypeError
, and abort these steps. -
Let executionSteps be the following algorithm that takes a
long
, a boolean success, and aDOMString
styleString:-
If success is
false
, then reject an embedder promise given controlledframe, result, and aTypeError
, and abort these steps. -
Let document be controlledframe’s embedded navigable’s active document.
-
Inject a stylesheet into a document given document and styleString.
-
Resolve an embedder promise given controlledframe and result.
-
-
If details["
code
"] is defined, then run executionSteps given 0,true
, and details["code
"]. -
Otherwise, fetch an injection item given controlledframe, details["
file
"],false
, 0, and executionSteps.
3.5. Configuration methods
dictionary {
ClearDataOptions long ; };
since dictionary {
ClearDataTypeSet boolean ;
cache boolean ;
cookies boolean ;
fileSystems boolean ;
indexedDB boolean ;
localStorage boolean ;
persistentCookies boolean ; };
sessionCookies
long
since, run the
following steps:
Note: If possible, the user agent should only remove data that has been last used after since, which represents a timestamp in milliseconds since epoch. Not all user agents track write or access time for all browsing data. Implementations should respect since to the best of their ability, but the API does not guarantee its availability.
-
Let bottle be bucket[identifier].
-
Set bottle’s proxy map reference set to a new set.
clearData(options, types)
method steps are:
-
Let resultPromise be a new promise.
-
Let controlledframe be this.
-
Return resultPromise and run the remaining steps in parallel.
-
Let clearSince be 0.
-
If options["
since
"] is defined, set clearSince to options|["since
"]. -
Let embeddingOrigin be the top-level origin of controlledframe’s relevant settings object.
-
Let partition be controlledframe’s
partition
. -
For each storageKey → shelf of the user agent’s storage shed:
-
If storageKey’s embedding origin is not equal to embeddingOrigin or storageKey’s partition is not equal to partition, then continue.
-
Let bucket be shelf["
default
"]. -
If types["
fileSystems
"] istrue
:-
Empty a storage bottle given bucket, "
fileSystem
", and clearSince.
-
-
If types["
indexedDB
"] istrue
:-
Empty a storage bottle given bucket, "
indexedDB
", and clearSince.
-
-
If types["
localStorage
"] istrue
:-
Empty a storage bottle given bucket, "
localStorage
", and clearSince.
-
-
-
If types["
cookies
"], types["persistentCookies
"], or types["sessionCookies
"] aretrue
, then:The [COOKIES] specification does not support partitioning cookies through a mechanism like storage keys. The following steps will clear all cookies, but the intention is to only delete cookies created by content within a Controlled Frame with this Controlled Frame’s current
partition
.-
For each cookie in the user agent’s cookie store:
-
If cookie’s persistent-flag is set, then:
-
If types["
cookies
"] and types["persistentCookies
"] arefalse
, then continue.
-
-
Otherwise:
-
If types["
cookies
"] and types["sessionCookies
"] arefalse
, then continue.
-
-
If cookie’s last-access-time represented as milliseconds since the epoch is less than clearSince, then continue.
-
Remove cookie from the user agent’s cookie store.
-
-
-
If types["
cache
"] istrue
, then:-
For each storageKey → cache that the user agent manages: [HTTP-CACHING]
-
If storageKey’s embedding origin is not equal to embeddingOrigin or storageKey’s partition is not equal to partition, then continue.
-
Clear cache.
-
-
-
Resolve an embedder promise given controlledframe and resultPromise.
Each embedded navigable holds a muted boolean, which defaults to false
. When muted is true
, the user agent must
mute all audio streams originating from within the embedded navigable.
The muted state should not be exposed to content
within the embedded navigable; when muted is true
, volume state should not be changed in any script-visible way, but the
underlying audio streams should not be audible to users.
getAudioState()
method steps are:
-
Let resultPromise be a new promise.
-
Let controlledframe be this.
-
Return resultPromise and run the remaining steps in parallel.
-
If controlledframe’s embedded navigable is null, then reject an embedder promise given controlledframe, resultPromise, and a
TypeError
, and abort these steps. -
Let playingAudio be
true
if any content, including in nested frames, within controlledframe’s embedded navigable is currently playing audio,false
otherwise. -
Resolve an embedder promise given controlledframe, resultPromise, and playingAudio.
isAudioMuted()
method steps are:
-
Let resultPromise be a new promise.
-
Let controlledframe be this.
-
Return resultPromise and run the remaining steps in parallel.
-
If controlledframe’s embedded navigable is null, then reject an embedder promise given controlledframe, resultPromise, and a
TypeError
, and abort these steps. -
Resolve an embedder promise given controlledframe, resultPromise, and controlledframe’s embedded navigable’s muted flag.
setAudioMuted(mute)
method steps are:
-
If this’s embedded navigable is null, then throw a
TypeError
. -
Set this’s embedded navigable’s muted flag to mute.
3.5.1. Zoom
enum {
ZoomMode ,
"per-origin" ,
"per-view" };
"disabled"
The user agent holds a Controlled Frame zoom map which is a map whose keys are tuples, and values are floats.
Each HTMLControlledFrameElement
holds a ZoomMode
zoomMode, which is defaulted to per-origin
.
Each HTMLControlledFrameElement
holds a float number currentZoom, initially set to 1.0f.
How zoom level is applied to a document given float zoomLevel is specific to the implementation.
This section is non-normative.
The valid ZoomMode
values behave as follows:
per-origin
-
Zoom changes will persist in the embedded document’s origin, i.e. all other
HTMLControlledFrameElement
in the samepartition
that are navigated to that same origin will be zoomed as well. per-view
-
Zoom changes only take effect in this
HTMLControlledFrameElement
, and zoom changes in otherHTMLControlledFrameElement
will not affect the zooming of thisHTMLControlledFrameElement
. disabled
-
Disables all zooming in the
HTMLControlledFrameElement
. The content will revert to the default zoom level, and all attempted zoom changes will be ignored.
To get the per-origin zoom level, given HTMLControlledFrameElement
e, run the following steps:
-
Let result be a float initially set to 1.0f.
-
Let key be the result of obtaining a Controlled Frame storage key given the environment associated e’s embedded navigable’s active document’s current settings object.
-
If Controlled Frame zoom map[key] exists, set result to the result of get the value of Controlled Frame zoom map given key key.
-
Return result.
To set the per-origin zoom level, given HTMLControlledFrameElement
e, and a float zoomLevel, run the following steps:
-
Let key be the result of obtaining a Controlled Frame storage key given the environment associated e’s embedded navigable’s active document’s current settings object.
-
Set the value of Controlled Frame zoom map given key key and value zoomLevel.
To determine whether current document has a per-origin zoom level, given HTMLControlledFrameElement
e, run the following steps:
-
Let key be the result of obtaining a Controlled Frame storage key given the environment associated e’s embedded navigable’s active document’s current settings object.
-
If Controlled Frame zoom map[key] exist, return
true
. -
Return
false
.
The getZoomMode()
method steps are:
-
Let p be a new promise.
-
Let controlledframe be this.
-
Return p and run the remaining steps in parallel.
-
Resolve an embedder promise given controlledframe, p, and controlledframe’s zoomMode.
The setZoomMode(zoomMode)
method steps are:
-
Let p be a new promise.
-
Let controlledframe be this.
-
Return p and run the remaining steps in parallel.
-
Let currentZoomMode be the result of
getZoomMode
given controlledframe. -
If currentZoomMode equals zoomMode, resolve an embedder promise given controlledframe and p.
-
Set controlledframe’s zoomMode to zoomMode.
-
If zoomMode is
per-origin
:-
If current document has a per-origin zoom level given controlledframe is
true
:-
Let oldZoomFactor be controlledframe’s currentZoom.
-
Set controlledframe’s currentZoom to the result of get the per-origin zoom level given controlledframe.
-
If oldZoomFactor does not equal to controlledframe’s currentZoom:
-
Apply zoom level to controlledframe’s embedded document given controlledframe’s currentZoom.
-
Fire a "zoomchange" event with controlledframe, oldZoomFactor, controlledframe’s currentZoom.
-
-
-
-
If zoomMode is
disabled
:-
Let oldZoomFactor be controlledframe’s currentZoom.
-
Set controlledframe’s currentZoom to 1.0f.
-
If oldZoomFactor does not equal to controlledframe’s currentZoom:
-
Apply zoom level to controlledframe’s embedded document given controlledframe’s currentZoom.
-
Fire a "zoomchange" event with controlledframe, oldZoomFactor, controlledframe’s currentZoom.
-
-
-
Resolve an embedder promise given controlledframe and p.
The getZoom()
method steps are:
-
Let p be a new promise.
-
Let controlledframe be this.
-
Return p and run the remaining steps in parallel.
-
Let embeddedNavigable be controlledframe’s embedded navigable.
-
If embeddedNavigable is null, then reject an embedder promise given controlledframe, p, and a
TypeError
, and abort these steps. -
Resolve an embedder promise given controlledframe, p, and controlledframe’s currentZoom.
The setZoom(zoomFactor)
method steps are:
-
Let p be a new promise.
-
Let controlledframe be this.
-
Return p and run the remaining steps in parallel.
-
Let embeddedNavigable be controlledframe’s embedded navigable.
-
If embeddedNavigable is null, then reject an embedder promise given controlledframe, p, and a
TypeError
, and abort these steps. -
If controlledframe’s ZoomMode is
disabled
:-
Reject an embedder promise given controlledframe, p, and a
TypeError
, and abort these steps.
-
-
If controlledframe’s ZoomMode is
per-origin
:-
Let oldZoomFactor be controlledframe’s currentZoom.
-
Set the per-origin zoom level given controlledframe and zoomFactor.
-
For each browsing context group group in the user agent’s browsing context group set:
-
For each top-level browsing context browsingContext in group:
-
Let embeddedDocument be browsingContext’s active document.
-
Let embedder be embeddedDocument’s node navigable’s embedderParent.
-
If embedder is null, then continue.
-
Let match be
true
if all of the following conditions aretrue
:-
embedder’s ZoomMode is
per-origin
-
embeddedDocument’s origin equals controlledframe’s embedded navigable’s active document’s origin
-
embedder’s currentZoom does not equal zoomFactor
-
-
If match is
true
, then:-
Set embedder’s currentZoom to zoomFactor.
-
Apply zoom level to embeddedDocument given zoomFactor.
-
Fire a "zoomchange" event with embedder, oldZoomFactor, and zoomFactor.
-
-
-
-
-
If controlledframe’s ZoomMode is
per-view
:-
Let oldZoomFactor be controlledframe’s currentZoom.
-
Set controlledframe’s currentZoom to zoomFactor.
-
If oldZoomFactor does not equal to controlledframe’s currentZoom:
-
Apply zoom level to controlledframe’s embedded document given controlledframe’s currentZoom.
-
Fire a "zoomchange" event with controlledframe, oldZoomFactor, controlledframe’s currentZoom.
-
-
-
Resolve an embedder promise given controlledframe and p.
3.6. Capture methods
// One of |code| or |file| must be specified but not both.dictionary {
ImageDetails DOMString ;
format DOMString ; };
quality
captureVisibleRegion(options)
method steps are:
-
Let resultPromise be a new promise.
-
Let controlledframe be this.
-
Return resultPromise and run the remaining steps in parallel.
-
If controlledframe’s embedded navigable is null, then reject an embedder promise given controlledframe, resultPromise, and a
TypeError
, and abort these steps. -
Let optionsFormat be "JPEG" by default.
-
Let optionsQuality be 100 by default.
-
If options has field "format":
-
Let optionsFormat be options["format"].
-
-
If optionsFormat is an unrecognized format, then reject an embedder promise given controlledframe, resultPromise, and a
TypeError
, and abort these steps. -
If options has field "quality":
-
Let optionsQuality be options["quality"].
-
-
If optionsQuality is not an integer or is not between 0 and 100 inclusive, then reject an embedder promise given controlledframe, resultPromise, and a
TypeError
, and abort these steps. -
Let imageData be a an image showing the visible region of the embedded content encoded in optionsFormat at quality optionsQuality.
Note: The set of supported image formats is implementation-defined, but it is recommended to support at least "JPEG" and "PNG".
-
Resolve an embedder promise given controlledframe, resultPromise, and a
data:
URL that contains imageData.
print()
method steps are:
-
If this’s embedded navigable is null, then throw a
TypeError
. -
Initiate the browser print page feature for embedded content.
3.7. Events
HTMLControlledFrameElement
implements EventTarget
and supports the following event handlers (and their corresponding event handler event types).
Event handlers | Event handler event types |
---|---|
onconsolemessage
| consolemessage |
oncontentload
| contentload |
ondialog
| dialog |
onloadabort
| loadabort |
onloadcommit
| loadcommit |
onloadstart
| loadstart |
onloadstop
| loadstop |
onnewwindow
| newwindow |
onpermissionrequest
| permissionrequest |
onsizechanged
| sizechanged |
onzoomchange
| zoomchange |
The interactive events:
The UI-change events:
-
onsizechanged
- fired when the embedded web content has been resized via autosize. Only fires if autosize is enabled.
The navigation events:
-
oncontentload
- fired when theWindow
associated with embedded navigable fires a load event. -
onloadabort
- fired when navigation has exited before completion. -
onloadcommit
- fired when navigation has been completed. -
onloadstart
- fired when navigation (including reloads and traversals) starts, for every navigable of the embedded document, but not same document navigation. -
onloadstop
- fired when all pending navigations finish(either commit or abort). If a new navigation starts after, loadstop may fire again.
Each HTMLControlledFrameElement
has a load counter which is a number that is initially zero.
Each time a onloadstart
event fires, load counter increases by 1.
Each time a onloadabort
event fires, load counter decreses by 1.
Each time a onloadcommit
event fires, load counter decreses by 1.
When load counter changes from a non-zero number to 0, fire a "loadstop" event.
3.7.1. consolemessage
[Exposed =Window ,IsolatedContext ]interface {
ConsoleMessage readonly attribute long ;
level readonly attribute DOMString ; }; [
message Exposed =Window ,IsolatedContext ]interface :
ConsoleMessageEvent Event {(
constructor DOMString ,
type optional ConsoleMessageEventInit = {});
eventInitDict readonly attribute ConsoleMessage ; };
consoleMessage dictionary :
ConsoleMessageEventInit EventInit {ConsoleMessage ?; };
consoleMessage
To fire a ConsoleMessageEvent
e given controlledframe
element target, a long logLevel and a DOMString message, run the following steps:
-
Let consoleMessage be a new
ConsoleMessage
object. -
Set the following fields of consoleMessage:
-
Set e’s
consoleMessage
to consoleMessage. -
Queue a global task on the DOM manipulation task source of target’s relevant global object to dispatch e at target.
3.7.2. dialog
enum {
DialogType ,
"alert" ,
"confirm" }; [
"prompt" Exposed =Window ,IsolatedContext ]interface {
DialogController undefined okay (optional DOMString );
response undefined cancel (); }; [Exposed =Window ,IsolatedContext ]interface {
DialogMessage readonly attribute DialogType ;
messageType readonly attribute DOMString ;
messageText readonly attribute DialogController ; }; [
dialog Exposed =Window ,IsolatedContext ]interface :
DialogEvent Event {(
constructor DOMString ,
type optional DialogEventInit = {});
eventInitDict readonly attribute DialogMessage ; };
dialogMessage dictionary :
DialogEventInit EventInit {DialogMessage ?; };
dialogMessage
Each DialogController
has:
-
A boolean accept, initially set to
false
. -
A DOMString response, initally an empty string.
The cancel()
method steps are:
-
Set accept to
false
.
To fire a DialogEvent
e given controlledframe
element target, simple-dialogs type dialogType, and
message message, run the following steps:
-
Assert that e["
dialogMessage
"]["dialog
"]["accept"] equalsfalse
. -
Let dialogMessage be a new
DialogMessage
object. -
Let dialog be a new
DialogController
object. -
Set the following fields of dialogMessage:
messageType
-
dialogType.
messageText
-
message.
dialog
-
dialog.
-
Set e’s
dialogMessage
to dialogMessage. -
Let complete be
false
. -
Queue a global task on the DOM manipulation task source of target’s relevant global object to run the following steps:
-
Dispatch e at target.
-
Set complete to
true
.
-
-
Synchronously wait for complete to be
true
.Note: Blocking here is intentional as the alert, confirm, and prompt dialogs represented by "dialog" events block the main thread, and the event handlers we’re calling here can affect the return values.
-
Return e["
dialogMessage
"]["dialog
"]["accept"] and e["dialogMessage
"]["dialog
"]["response"].
3.7.3. newwindow
enum {
WindowOpenDisposition ,
"ignore" ,
"save_to_disk" ,
"current_tab" ,
"new_background_tab" ,
"new_foreground_tab" ,
"new_window" }; [
"new_popup" Exposed =Window ,IsolatedContext ]interface {
NewWindowController undefined attach (HTMLControlledFrameElement );
newControlledFrame undefined discard (); }; [Exposed =Window ,IsolatedContext ]interface {
NewWindow readonly attribute NewWindowController ;
window readonly attribute USVString ;
targetUrl readonly attribute DOMString ;
name readonly attribute WindowOpenDisposition ; }; [
windowOpenDisposition Exposed =Window ,IsolatedContext ]interface :
NewWindowEvent Event {(
constructor DOMString ,
type optional NewWindowEventInit = {});
eventInitDict readonly attribute NewWindow ; };
newWindow dictionary :
NewWindowEventInit EventInit {NewWindow ?; };
newWindow
Each NewWindowController
has reference to a target navigable, which is initially null.
The attach(newControlledFrame)
method steps are:
-
Set newControlledFrame’s embedded navigable to this’s target navigable.
The discard()
method steps are:
-
If this’s target navigable is not null, then close a top-level traversable given this’s target navigable.
To fire a NewWindowEvent
e given controlledframe
element controlledFrame, USVString
url, DOMString
target, navigable targetNavigable, and WindowOpenDisposition
windowOpenDisposition, run the following steps:
-
Let controller be a new
NewWindowController
object. -
Set controller’s target navigable to targetNavigable.
-
Set the following fields of newWindow:
window
-
controller
targetUrl
-
url
name
-
target.
windowOpenDisposition
-
windowOpenDisposition
-
Set e’s
newWindow
to newWindow. -
Queue a global task on the DOM manipulation task source of controlledFrame’s relevant global object to dispatch e at controlledFrame.
3.7.4. permissionrequest
enum {
PermissionType ,
"media" ,
"geolocation" ,
"pointerLock" ,
"download" ,
"filesystem" ,
"fullscreen" , }; [
"hid" Exposed =Window ,IsolatedContext ]interface {
PermissionRequestControllerBase undefined allow ();undefined cancel (); }; [Exposed =Window ,IsolatedContext ]interface :
MediaPermissionRequestController PermissionRequestControllerBase {readonly attribute USVString ; }; [
url Exposed =Window ,IsolatedContext ]interface :
GeolocationPermissionRequestController PermissionRequestControllerBase {readonly attribute USVString ; }; [
url Exposed =Window ,IsolatedContext ]interface :
PointerLockPermissionRequestController PermissionRequestControllerBase {readonly attribute boolean ;
lastUnlockedBySelf readonly attribute boolean ;
userGesture readonly attribute USVString ; }; [
url Exposed =Window ,IsolatedContext ]interface :
DownloadPermissionRequestController PermissionRequestControllerBase {readonly attribute DOMString ;
requestMethod readonly attribute USVString ; }; [
url Exposed =Window ,IsolatedContext ]interface :
FileSystemPermissionRequestController PermissionRequestControllerBase {readonly attribute USVString ; }; [
url Exposed =Window ,IsolatedContext ]interface :
FullscreenPermissionRequestController PermissionRequestControllerBase {readonly attribute USVString ; }; [
origin Exposed =Window ,IsolatedContext ]interface :
HidPermissionRequestController PermissionRequestControllerBase {readonly attribute USVString ; }; [
url Exposed =Window ,IsolatedContext ]interface {
PermissionRequest readonly attribute PermissionType ;
permission readonly attribute PermissionRequestControllerBase ; }; [
request Exposed =Window ,IsolatedContext ]interface :
PermissionRequestEvent Event {(
constructor DOMString ,
type optional PermissionRequestEventInit = {});
eventInitDict readonly attribute PermissionRequest ; };
permissionRequest dictionary :
PermissionRequestEventInit EventInit {PermissionRequest ?; };
permissionRequest
Each PermissionRequestControllerBase
has a boolean value allow, which is initially false
.
The allow()
method steps are:
-
Set allow to
true
.
The cancel()
method steps are:
-
Set allow to
false
.
To fire a PermissionRequestEvent
e given a document embeddedDocument, controlledframe
element target, DOMString type, USVString url, an
optional dictionary options, and an algorithm completionSteps that takes
a boolean, run the following steps:
-
Let permissionRequest be a new
PermissionRequest
object. -
If type is "media":
-
Let requestController be a new
MediaPermissionRequestController
with the following attributes:url
-
url
-
-
If type is "geolocation":
-
Let requestController be a new
GeolocationPermissionRequestController
with the following attributes:url
-
url
-
-
If type is "pointerLock":
-
Let requestController be a new
PointerLockPermissionRequestController
with the following attributes:lastUnlockedBySelf
-
options["lastUnlockedBySelf"]
userGesture
-
options["userGesture"]
url
-
url
-
-
If type is "download":
-
Let requestController be a new
DownloadPermissionRequestController
with the following attributes:requestMethod
-
options["requestMethod"]
url
-
url
-
-
If type is "filesystem":
-
Let requestController be a new
FileSystemPermissionRequestController
with the following attributes:url
-
url
-
-
If type is "fullscreen":
-
Let requestController be a new
FullscreenPermissionRequestController
with the following attributes:origin
-
origin of url
-
-
If type is "hid":
-
Let requestController be a new
HidPermissionRequestController
with the following attributes:url
-
url
-
-
Set the following fields of permissionRequest:
request
-
requestController
permission
-
type.
-
Set e’s
permissionRequest
to permissionRequest. -
Queue a global task on the DOM manipulation task source of target’s relevant global object to run the following steps:
-
Dispatch e at target.
-
Queue a global task on the DOM manipulation task source of embeddedDocument’s relevant global object that runs completionSteps with e["
permissionRequest
"]["permission
"]["allow"].
-
3.7.5. sizechanged
[Exposed =Window ,IsolatedContext ]interface {
SizeChange readonly attribute unsigned long ;
oldWidth readonly attribute unsigned long ;
oldHeight readonly attribute unsigned long ;
newWidth readonly attribute unsigned long ; }; [
newHeight Exposed =Window ,IsolatedContext ]interface :
SizeChangedEvent Event {(
constructor DOMString ,
type optional SizeChangedEventInit = {});
eventInitDict readonly attribute SizeChange ; };
sizeChange dictionary :
SizeChangedEventInit EventInit {SizeChange ?; };
sizeChange
To fire a SizeChangedEvent
e given controlledframe
element target, 4 non-negative numbers oldWidth, oldHeight, newWidth, newHeight:
-
Let sizeChange be a new
SizeChange
object. -
Set the following fields of sizeChange:
-
Set e’s
sizeChange
to sizeChange. -
Queue a global task on the DOM manipulation task source of target’s relevant global object to dispatch e at target.
3.7.6. zoomchange
[Exposed =Window ,IsolatedContext ]interface {
ZoomChange readonly attribute float ;
oldZoomFactor readonly attribute float ; }; [
newZoomFactor Exposed =Window ,IsolatedContext ]interface :
ZoomChangeEvent Event {(
constructor DOMString ,
type optional ZoomChangeEventInit = {});
eventInitDict readonly attribute ZoomChange ; };
zoomChange dictionary :
ZoomChangeEventInit EventInit {ZoomChange ?; };
zoomChange
To fire a ZoomChangeEvent
e given controlledframe
element target, 2 float numbers oldZoomFactor, newZoomFactor:
-
Let zoomChange be a new
ZoomChange
object. -
Set the following fields of zoomChange:
oldZoomFactor
-
oldZoomFactor.
newZoomFactor
-
newZoomFactor.
-
Set e’s
zoomChange
to zoomChange. -
Queue a global task on the DOM manipulation task source of target’s relevant global object to dispatch e at target.
3.7.7. contentload
[Exposed =Window ,IsolatedContext ]interface :
ContentLoadEvent Event {(
constructor DOMString ,
type optional EventInit = {}); };
eventInitDict
To fire a ContentLoadEvent
e given controlledframe
element target, run the following steps:
-
Queue a global task on the DOM manipulation task source of target’s relevant global object to dispatch e at target.
3.7.8. loadabort
[Exposed =Window ,IsolatedContext ]interface {
LoadInfo readonly attribute USVString ;
url readonly attribute boolean ; }; [
isTopLevel Exposed =Window ,IsolatedContext ]interface :
LoadAbortInfo LoadInfo {readonly attribute long ;
code readonly attribute DOMString ; }; [
reason Exposed =Window ,IsolatedContext ]interface {
LoadRedirectInfo readonly attribute USVString ;
oldUrl readonly attribute USVString ;
newUrl readonly attribute boolean ; }; [
isTopLevel Exposed =Window ,IsolatedContext ]interface :
LoadAbortEvent Event {(
constructor DOMString ,
type optional LoadAbortEventInit = {});
eventInitDict readonly attribute LoadAbortInfo ; };
loadAbortInfo dictionary :
LoadAbortEventInit EventInit {LoadAbortInfo ?; };
loadAbortInfo
To fire a LoadAbortEvent
e given controlledframe
element target,
a USVString url, a boolean isTopLevel, a long code, and a DOMString reason, run the following steps:
-
Let info be a new
LoadAbortInfo
with the following attributes:url
-
url
isTopLevel
-
isTopLevel
code
-
code
reason
-
reason
-
Set e’s
loadAbortInfo
to info. -
Queue a global task on the DOM manipulation task source of target’s relevant global object to dispatch e at target.
3.7.9. loadcommit
[Exposed =Window ,IsolatedContext ]interface :
LoadCommitEvent Event {(
constructor DOMString ,
type optional LoadCommitEventInit = {});
eventInitDict readonly attribute LoadInfo ; };
loadInfo dictionary :
LoadCommitEventInit EventInit {LoadInfo ?; };
loadInfo
To fire a LoadCommitEvent
e given controlledframe
element target,
a USVString url, and a boolean isTopLevel, run the following steps:
-
Let info be a new
LoadInfo
with the following attributes:url
-
url
isTopLevel
-
isTopLevel
-
Set e’s
loadInfo
to info. -
Queue a global task on the DOM manipulation task source of target’s relevant global object to dispatch e at target.
3.7.10. loadstart
[Exposed =Window ,IsolatedContext ]interface :
LoadStartEvent Event {(
constructor DOMString ,
type optional LoadStartEventInit = {});
eventInitDict readonly attribute LoadInfo ; };
loadInfo dictionary :
LoadStartEventInit EventInit {LoadInfo ?; };
loadInfo
To fire a LoadStartEvent
e given controlledframe
element target,
a USVString url, and a boolean isTopLevel, run the following steps:
-
Let info be a new
LoadInfo
with the following attributes:url
-
url
isTopLevel
-
isTopLevel
-
Set e’s
loadInfo
to info. -
Queue a global task on the DOM manipulation task source of target’s relevant global object to dispatch e at target.
3.7.11. loadstop
[Exposed =Window ,IsolatedContext ]interface :
LoadStopEvent Event {(
constructor DOMString ,
type optional LoadStopEventInit = {}); };
eventInitDict dictionary :
LoadStopEventInit EventInit { };
To fire a LoadStopEvent
e given controlledframe
element target, run the following steps:
-
Queue a global task on the DOM manipulation task source of target’s relevant global object to dispatch e at target.
3.7.12. loadredirect
[Exposed =Window ,IsolatedContext ]interface :
LoadRedirectEvent Event {(
constructor DOMString ,
type optional LoadRedirectEventInit = {});
eventInitDict readonly attribute LoadRedirectInfo ; };
loadRedirectInfo dictionary :
LoadRedirectEventInit EventInit {LoadRedirectInfo ?; };
loadRedirectInfo
To fire a LoadRedirectEvent
e given controlledframe
element target, an URL oldUrl, an URL newUrl, and a boolean isTopLevel, run the following steps:
-
Let info be a new
LoadInfo
with the following attributes:oldUrl
-
The result of serializing an URL given oldUrl
newUrl
-
The result of serializing an URL given newUrl
isTopLevel
-
isTopLevel
-
Set e’s
loadRedirectInfo
to info. -
Queue a global task on the DOM manipulation task source of target’s relevant global object to dispatch e at target.
3.7.13. Monkey Patches
3.7.13.1. [HTML]
For alert:
-
Set message to the result of optionally truncating message.
- Let embedderParent be window’s navigable’s embedderParent. .
-
If embedderParent is a
HTMLControlledFrameElement
, then fire a "dialog" event with embedderParent, "alert" and message, and return.
For confirm:
-
Set message to the result of optionally truncating message.
- Let embedderParent be window’s navigable’s embedderParent. .
-
If embedderParent is a
HTMLControlledFrameElement
, then return the result of firing a "dialog" event with embedderParent, "confirm", and message.
For prompt:
-
Set default to the result of optionally truncating default.
- Let embedderParent be window’s navigable’s embedderParent. .
-
If embedderParent is a
HTMLControlledFrameElement
, then:- Let accept and response be the results of firing a "dialog" event with embedderParent, "prompt" and message.
-
If accept equals
false
, return null. - Return response.
For window open steps:
-
Let windowOpenDisposition be "
ignore
". - Let embedderParent be sourceDocument’s node navigable’s embedderParent.
...
-
If targetNavigable is null:
-
If embedderParent is not null:
- Fire a "newwindow" event with embedderParent, url, target, targetNavigable, and windowOpenDisposition.
- Return null.
-
If embedderParent is not null:
-
If windowType is either "new and unrestricted" or "new with no opener", then:
-
Set windowOpenDisposition to one of
"
new_background_tab
", "new_foreground_tab
", or "new_window
".
Note: The value depends on the behavior support of the user agent and user settings.
-
Set targetNavigable’s active browsing context’s is popup to the result of checking if a popup window is requested, given tokenizedFeatures.
-
If targetNavigable’s active browsing context’s is popup is
true
, set windowOpenDisposition to "new_popup
".
...
-
Set windowOpenDisposition to one of
"
-
Otherwise:
-
Set windowOpenDisposition to
"
current_tab
".
...
-
Set windowOpenDisposition to
"
Note: Step 15 and 16 also navigate targetNavigable; during navigation, windowOpenDisposition may also be updated. For example, if navigation is
prevented, windowOpenDisposition may be set to
"ignore
". If the navigation response resulted in
download, then windowOpenDisposition may be set to
"save_to_disk
".
-
If embedderParent is not null:
- Fire a "newwindow" event with embedderParent, url, target, targetNavigable, and windowOpenDisposition.
For completely finish loading:
-
Otherwise, if container is non-null, then queue an element task on the DOM manipulation task source given container to fire an event named load at container.
- Let embedderParent be document’s node navigable’s embedderParent.
-
If embedderParent is
HTMLControlledFrameElement
, then Fire a "contentload" event with embedderParent.
Monkey-patch for loadstart, loadabort, and loadcommit which looks like the following:
-
loadstart -> at the navigation entry points: normal navigation, reloads, traversal.
-
loadcommit -> at the common navigation completion point.
-
loadabort -> at each early exist points of the algorithm between loadstart and loadcommit.
For each of these, check whether the top-level traversable of the navigable has an embedderParent of HTMLControlledFrameElement
, if so, then fire the corresponding event with input arguments.
3.7.13.2. [FETCH]
For HTTP fetch(loadredirect):
-
If internalResponse’s status is a redirect status:
-
If request’s window window is a environment settings object whose global object is a
Window
object:- Let currentNavigable be window’s associated navigable.
- Let embedderParent be currentNavigable’s top-level traversable’s embedderParent.
-
If embedderParent is a
HTMLControlledFrameElement
:1. Let oldUrl be request’s associated URL.
1. Let newUrl be response’s location url.
1. Let isTopLevel be
false
, if currentNavigable has a null parent set isTopLevel totrue
.1. Fire a "loadredirect" event with embedderParent, oldUrl, newUrl, and isTopLevel.
-
If request’s window window is a environment settings object whose global object is a
3.7.13.3. [Permissions]
Define new algorithm:
To determine if a Document document is allowed by embedder to use a permission given DOMString permission, an optional dictionary options, and an algorithm completionSteps that takes a boolean, run the following steps:
-
Let embedderParent be document’s node navigable’s embedderParent.
-
If embedderParent is not
HTMLControlledFrameElement
, returntrue
. -
Fire a "permissionrequest" event with document, embedderParent, permission, document’s URL, options, and completionSteps.
For request a position (geolocation):
-
If document is not allowed to use the "geolocation" feature:
-
If watchId was passed, remove watchId from watchIDs.
-
Call back with error passing errorCallback and PERMISSION_DENIED.
-
Terminate this algorithm.
-
-
Let blockedByEmbedder be
false
. - Check if document is allowed by embedder to use the "geolocation" feature given an algorithm that assigns its boolean argument to blockedByEmbedder and continues with the remainder of these steps.
-
If blockedByEmbedder is
true
, then:- If watchId was passed, remove watchId from watchIDs.
- Call back with error passing errorCallback and PERMISSION_DENIED.
- Terminate this algorithm.
- Let embedderParent be document’s node navigable’s embedderParent.
-
If embedderParent is
HTMLControlledFrameElement
:-
Let nodeDocument be embedderParent’s node document.
-
If nodeDocument is null:
- If watchId was passed, remove watchId from watchIDs.
- Call back with error passing errorCallback and PERMISSION_DENIED.
- Terminate this algorithm.
- Let embedderNavigator be the associated Navigator of nodeDocument’s global object.
-
Let embedderGeolocation be the
geolocation
of embedderNavigator. - Return the result of request a position with embedderGeolocation, successCallback, errorCallback, options, and whatchId.
-
Note: Other permissions will be monkey-patched similarly to geolocation. But the details are elided in this document for brevity.
3.7.13.4. [Console]
For Logger:
-
Otherwise, perform Printer(logLevel, Formatter(args)).
- Fire a "consolemessage" event with logLevel, Formatter(args).
Note: Console by default does not have association with document so we cannot track the associated HTMLControlledFrameElement
.
3.8. Integration with other specifications
This specification will make some modifications to specifications to accommodate the needs of Controlled Frame.
3.8.1. Monkey Patches
3.8.1.1. [HTML]
Each navigable has:
-
A frameId integer, initially 0.
-
A next frameId integer, initially 1.
-
An embedderParent, an
HTMLControlledFrameElement
or null.
The initialize the navigable algorithm given a navigable navigable and an optional navigable-or-null parent (default null) is monkey patched as follows:
-
Set navigable’s parent to parent.
-
If parent is not null (navigable is not a top-level traversable), then:
- Let topLevelTraversable be the top-level traversable that navigable is a descendant of.
- Set navigable’s frameId to topLevelTraversable’s next frameId.
- Increment topLevelTraversable’s next frameId.
The update the current document readiness for Document
document to readinessValue algorithm is monkey patched as follows:
-
Let runAt be the result of applying the following mapping to readinessValue:
- "
loading
" - "
interactive
" - "
complete
"
- "
- Inject content scripts into a document given document and runAt.
-
Fire an event named
readystatechange
at document.
3.8.1.2. [FETCH]
The determine the network partition key algorithm is monkey extended to require double-keying on network requests originating from a Controlled Frame’s embedded navigable.
-
Let topLevelSite be the result of obtaining a site, given topLevelOrigin.
-
Let secondKey be null
or an implementation-defined value. - Let embedderParent be the result of getting an environment’s embedderParent given environment.
-
If embedderParent is not null, then set secondKey to a tuple consisting of the top-level origin of embedderParent’s relevant settings object, and embedderParent’s
partition
. -
Return (topLevelSite, secondKey).
3.8.1.3. [STORAGE]
Storage keys are re-defined as follows:
A storage key is a tuple consisting of an embedding origin (an origin or null), a partition (a DOMString
or null), and an origin (an origin).
Note: This definition will need to be expanded to include the embedded content’s top-level origin in addition to origin in the future once storage partitioning is fully specified.
Note: Controlled Frame data is triple keyed with the origin of the document that owns the Controlled Frame element, not the top-level document that owns it.
The obtain a storage key for non-storage purposes algorithm is extended to
require double-keying on all storage belonging to a controlledframe
’s embedded navigable.
-
Let origin be environment’s origin if environment is an environment settings object; otherwise environment’s creation URL’s origin.
-
Return a tuple consisting of origin. - Let topLevelOrigin and partition be null.
- Let embedderParent be the result of getting an environment’s embedderParent given environment.
-
If embedderParent is not null, then:
- Set topLevelOrigin to the top-level origin of embedderParent’s relevant settings object.
-
Set partition to embedderParent’s
partition
.
- Return a tuple consisting of topLevelOrigin, partition, and origin.
-
If environment is an environment settings object whose global object is a
Window
object, then:This algorithm doesn’t work for Shared or Service Workers because embedderParent is only defined on a navigable, and it’s not always possible to go from a non-
Window
environment to a navigable.-
Let navigable be environment’s global object’s navigable.
-
Let top be the top-level traversable of navigable.
-
If top’s embedderParent is not null, then return top’s embedderParent.
-
-
Return null.
4. Web Request API
This API is based on the WebRequest API, which is available through the <webview> element in Chrome Apps. It is exposed to Controlled Frame with minimum modification to make efficient use of prior art. As a result, this API does not fully adhere to Web Platform best practices, particularly around naming conventions and event handling. If there is future cross-browser interest in Controlled Frame, this API should be revisited to align better with other Web APIs.
enum {
ResourceType ,
"main_frame" ,
"sub_frame" ,
"stylesheet" ,
"script" ,
"image" ,
"font" ,
"object" ,
"xmlhttprequest" ,
"ping" ,
"csp_report" ,
"media" ,
"websocket" , };
"other" callback interface {
WebRequestEventListener BlockingResponse ?(
handleEvent WebRequestEventDetails ); };
details dictionary {
RequestFilter sequence <ResourceType >;
types sequence <USVString >; };
urls enum {
ExtraInfoSpec ,
"asyncBlocking" ,
"blocking" ,
"extraHeaders" ,
"requestHeaders" , }; [
"responseHeaders" Exposed =Window ,IsolatedContext ]interface {
WebRequestEvent undefined addListener (WebRequestEventListener ,
listener optional RequestFilter = {},
filter optional sequence <ExtraInfoSpec >);
extraInfoSpec boolean hasListener (WebRequestEventListener );
listener boolean hasListeners ();undefined removeListener (WebRequestEventListener ); };
listener dictionary {
WebRequestAuthCredentials required DOMString ;
username required DOMString ; };
password dictionary {
BlockingResponse WebRequestAuthCredentials ;
authCredentials boolean ;
cancel USVString ;
redirectUrl sequence <HttpHeader >;
requestHeaders sequence <HttpHeader >; };
responseHeaders enum {
DocumentLifecycle ,
"prerender" ,
"active" ,
"cached" , };
"pending_deletion" enum {
FrameType ,
"outermost_frame" ,
"fenced_frame" , };
"sub_frame" dictionary {
WebRequestEventDetails DOMString ;
documentId DocumentLifecycle ;
documentLifecycle required long ;
frameId FrameType ;
frameType USVString ;
initiator required DOMString ;
method DOMString ;
parentDocumentId required long ;
parentFrameId required DOMString ;
requestId required long ;
timeStamp required ResourceType ;
type required USVString ; };
url dictionary {
UploadData ArrayBuffer ;
bytes DOMString ; };
file dictionary {
RequestBody DOMString ;
error any ;
formData sequence <UploadData >; };
raw dictionary :
WebRequestBeforeRequestDetails WebRequestEventDetails {RequestBody ; };
requestBody dictionary {
HttpHeader required DOMString ;
name DOMString ;
value sequence <byte >; };
binaryValue dictionary :
WebRequestBeforeSendHeadersDetails WebRequestEventDetails {sequence <HttpHeader >; };
requestHeaders dictionary :
WebRequestSendHeadersDetails WebRequestEventDetails {sequence <HttpHeader >; };
requestHeaders dictionary :
WebRequestResponseEventDetails WebRequestEventDetails {required long ;
statusCode required DOMString ;
statusLine sequence <HttpHeader >; };
responseHeaders dictionary :
WebRequestHeadersReceivedDetails WebRequestResponseEventDetails {};dictionary {
AuthChallenger DOMString ;
host long ; };
port dictionary :
WebRequestAuthRequiredDetails WebRequestResponseEventDetails {required AuthChallenger ;
challenger required boolean ;
isProxy required DOMString ;
scheme DOMString ; };
realm dictionary :
WebRequestResponseWithIpEventDetails WebRequestResponseEventDetails {required boolean ;
fromCache DOMString ; };
ip dictionary :
WebRequestBeforeRedirectDetails WebRequestResponseWithIpEventDetails {required USVString ; };
redirectUrl dictionary :
WebRequestResponseStartedDetails WebRequestResponseWithIpEventDetails {};dictionary :
WebRequestCompletedDetails WebRequestResponseWithIpEventDetails {};dictionary :
WebRequestErrorOccurredDetails WebRequestEventDetails {required DOMString ;
error required boolean ;
fromCache DOMString ; };
ip callback =
HandlerBehaviorChangedCallback undefined (); [Exposed =Window ,IsolatedContext ]interface {
WebRequest readonly attribute WebRequestEvent onBeforeRequest ;readonly attribute WebRequestEvent onBeforeSendHeaders ;readonly attribute WebRequestEvent onSendHeaders ;readonly attribute WebRequestEvent onHeadersReceived ;readonly attribute WebRequestEvent onAuthRequired ;readonly attribute WebRequestEvent onBeforeRedirect ;readonly attribute WebRequestEvent onResponseStarted ;readonly attribute WebRequestEvent onCompleted ;readonly attribute WebRequestEvent onErrorOccurred ;undefined handlerBehaviorChanged (optional HandlerBehaviorChangedCallback ); };
callback
Each WebRequest
has an associated:
-
handler map, which is a map whose keys are
DOMString
s and whose values are lists of WebRequest handler configs. -
onBeforeRequest, which is a
WebRequestEvent
. -
onBeforeSendHeaders, which is a
WebRequestEvent
. -
onSendHeaders, which is a
WebRequestEvent
. -
onHeadersReceived, which is a
WebRequestEvent
. -
onAuthRequired, which is a
WebRequestEvent
. -
onBeforeRedirect, which is a
WebRequestEvent
. -
onResponseStarted, which is a
WebRequestEvent
. -
onCompleted, which is a
WebRequestEvent
. -
onErrorOccurred, which is a
WebRequestEvent
.
The onBeforeRequest
getter steps
are to return this’s onBeforeRequest.
The onBeforeSendHeaders
getter steps
are to return this’s onBeforeSendHeaders.
The onSendHeaders
getter steps
are to return this’s onSendHeaders.
The onHeadersReceived
getter steps
are to return this’s onHeadersReceived.
The onAuthRequired
getter steps
are to return this’s onAuthRequired.
The onBeforeRedirect
getter steps
are to return this’s onBeforeRedirect.
The onResponseStarted
getter steps
are to return this’s onResponseStarted.
The onCompleted
getter steps
are to return this’s onCompleted.
The onErrorOccurred
getter steps
are to return this’s onErrorOccurred.
Each WebRequestEvent
has:
-
An eventName, a
DOMString
. -
A webRequest, a
WebRequest
instance that it is a member of.
addListener(listener, filter, extraInfoSpec)
method steps are:
-
Call
removeListener
with listener. -
Let handlerConfig be a new WebRequest handler config with the following items:
-
Let specSet be a set containing the items in extraInfoSpec.
-
If eventName equals "beforeRequest", then:
-
If specSet is not a subset of the set « "blocking", "requestBody", "extraHeaders" », then throw a
TypeError
. -
If specSet contains "blocking", then set handlerConfig’s blocking to
true
. -
If specSet contains "requestBody", then set handlerConfig’s requestsBody to
true
. -
If specSet contains "extraHeaders", then set handlerConfig’s requestsAllHeaders to
true
.
-
-
Otherwise, if eventName equals "beforeSendHeaders", then:
-
If specSet is not a subset of the set « "blocking", "requestHeaders", "extraHeaders" », then throw a
TypeError
. -
If specSet contains "blocking", then set handlerConfig’s blocking to
true
. -
If specSet contains "requestHeaders", then set handlerConfig’s requestsHeaders to
true
. -
If specSet contains "extraHeaders", then set handlerConfig’s requestsAllHeaders to
true
.
-
-
Otherwise, if eventName equals "sendHeaders", then:
-
If specSet is not a subset of the set « "requestHeaders", "extraHeaders" », then throw a
TypeError
. -
If specSet contains "requestHeaders", then set handlerConfig’s requestsHeaders to
true
. -
If specSet contains "extraHeaders", then set handlerConfig’s requestsAllHeaders to
true
.
-
-
Otherwise, if eventName equals "headersReceived", then:
-
If specSet is not a subset of the set « "blocking", "responseHeaders", "extraHeaders" », then throw a
TypeError
. -
If specSet contains "blocking", then set handlerConfig’s blocking to
true
. -
If specSet contains "responseHeaders", then set handlerConfig’s requestsHeaders to
true
. -
If specSet contains "extraHeaders", then set handlerConfig’s requestsAllHeaders to
true
.
-
-
Otherwise, if eventName equals "authRequired", then:
-
If specSet is not a subset of the set « "asyncBlocking", "blocking", "responseHeaders", "extraHeaders" », then throw a
TypeError
. -
If specSet contains "asyncBlocking", then set handlerConfig asyncBlocking to
true
. -
If specSet contains "blocking", then set handlerConfig’s blocking to
true
. -
If specSet contains "responseHeaders", then set handlerConfig’s requestsHeaders to
true
. -
If specSet contains "extraHeaders", then set handlerConfig’s requestsAllHeaders to
true
.
-
-
Otherwise, if eventName equals "beforeRedirect", then:
-
If specSet is not a subset of the set « "responseHeaders", "extraHeaders" », then throw a
TypeError
. -
If specSet contains "responseHeaders", then set handlerConfig’s requestsHeaders to
true
. -
If specSet contains "extraHeaders", then set handlerConfig’s requestsAllHeaders to
true
.
-
-
Otherwise, if eventName equals "responseStarted", then:
-
If specSet is not a subset of the set « "responseHeaders", "extraHeaders" », then throw a
TypeError
. -
If specSet contains "responseHeaders", then set handlerConfig’s requestsHeaders to
true
. -
If specSet contains "extraHeaders", then set handlerConfig’s requestsAllHeaders to
true
.
-
-
Otherwise, if eventName equals "completed", then:
-
If specSet is not a subset of the set « "responseHeaders", "extraHeaders" », then throw a
TypeError
. -
If specSet contains "responseHeaders", then set handlerConfig’s requestsHeaders to
true
. -
If specSet contains "extraHeaders", then set handlerConfig’s requestsAllHeaders to
true
.
-
-
Otherwise, if eventName equals "errorOccurred", then:
-
Let handlerMap be the handler map of this’s webRequest.
-
Append handlerConfig to handlerMap[eventName].
hasListener(listener)
method steps are:
-
Let handlerMap be the handler map of this’s webRequest.
-
For each handlerConfig in handlerMap[event name]:
-
If handlerConfig’s handler equals listener, return
true
.
-
-
Return
false
.
hasListeners()
method steps are:
-
Let handlerMap be the handler map of this’s webRequest.
-
If handlerMap[event name] is empty, return
false
, otherwise returntrue
.
removeListener(listener)
method steps are:
-
Let handlerMap be the handler map of this’s webRequest.
-
Let handlerConfigs be handlerMap[event name].
-
Remove all items from handlerConfigs whose handler equals listener.
handlerBehaviorChanged(callback)
method steps are:
-
Let controlledframe be this.
-
In parallel, clear the HTTP cache associated with the partition used by environments embedded within the controlledframe
HTMLControlledFrameElement
.Note: The behavior of event handlers registered through the WebRequest API will be reflected in the HTTP cache, which will no longer be valid if the behavior of the event handlers changed. The purpose of this method is to invalidate any cache entries that were affected by WebRequest event handlers.
-
Invoke callback when the HTTP cache has been cleared.
-
Let configs and blocking be the results of calling lookup registered WebRequest handler configs given "beforeRequest", and request.
-
Let combinedResults be an empty
BlockingResponse
. -
Let pendingHandlerCount be configs’s size.
-
Let embedderGlobal be the relevant global object of the result of getting an environment’s embedderParent given request’s client.
-
For each config in configs:
-
Let details be the result of calling create a WebRequestEventDetails object given request.
-
If config’s requestsBody is
true
and request’s body is not null, then:-
Let requestBody be an empty
RequestBody
. -
Let body be request’s body.
TODO: serialize stream if present.
-
Switch on body’s source:
- byte sequence
-
Append an
UploadData
withbytes
equal to the serialized body’s source to requestBody["raw
"]. Blob
-
Append an
UploadData
withbytes
equal to the serialized body’s source to requestBody["raw
"]. FormData
-
-
Let formData be «[]».
-
For each entry in body’s source’s entry list:
-
Switch on entry[1]:
-
-
Set details["
formData
"] to formData.
-
-
Set details["
requestBody
"] to requestBody.
-
-
Queue a global task on the DOM manipulation task source of embedderGlobal that will run the following steps:
-
Let result be the result of calling config’s handler given details.
Note: Any exceptions thrown by the handler are intentionally ignored and will not affect the request.
-
If all keys in result are contained in the set « "cancel", "redirect" », then:
-
If result["
cancel
"] istrue
, then set combinedResults["cancel
"] totrue
. -
If result["
redirectUrl
"] is a valid URL string and combinedResults["redirectUrl
"] is undefined, then set combinedResults["redirectUrl
"] to result["redirectUrl
"].
-
-
Decrement pendingHandlerCount.
-
-
-
If blocking is
true
, then wait in parallel for pendingHandlerCount to equal 0, then queue a global task on the networking task source of request’s client’s global object that will continue the remaining steps of this algorithm. -
Return combinedResults.
-
Let configs and blocking be the results of calling lookup registered WebRequest handler configs given "beforeSendHeaders", and request.
-
Let combinedResults be an empty
BlockingResponse
. -
Let pendingHandlerCount be configs’s size.
-
Let embedderGlobal be the relevant global object of the result of getting an environment’s embedderParent given request’s client.
-
For each config in configs:
-
Let details be the result of calling create a WebRequestEventDetails object given request.
-
If config’s requestsHeaders is
true
, then set details["requestHeaders
"] to the result of calling convert a header list to an HttpHeader sequence given request’s header list, config’s requestsAllHeaders, and isRequest equal totrue
. -
Queue a global task on the DOM manipulation task source of embedderGlobal that will run the following steps:
-
Let result be the result of calling config’s handler given details.
Note: Any exceptions thrown by the handler are intentionally ignored and will not affect the request.
-
If all keys in result are contained in the set « "cancel", "requestHeaders" », then:
-
If result["
cancel
"] istrue
, then set combinedResults["cancel
"] totrue
. -
If result["
requestHeaders
"] is a list whose size > 0, then:-
Set combinedResults["
requestHeaders
"] to [] if it is not defined. -
Append the contents of result["
requestHeaders
"] to combinedResults["requestHeaders
"].
-
-
-
Decrement pendingHandlerCount.
-
-
-
If blocking is
true
, then wait in parallel for pendingHandlerCount to equal 0, then queue a global task on the networking task source of request’s client’s global object that will continue the remaining steps of this algorithm. -
Return combinedResults.
-
Let configs be the result of calling lookup registered WebRequest handler configs given "sendHeaders", and request.
-
Let embedderGlobal be the relevant global object of the result of getting an environment’s embedderParent given request’s client.
-
For each config in configs:
-
Let details be the result of calling create a WebRequestEventDetails object given request.
-
If config’s requestsHeaders is
true
, then set details["requestHeaders
"] to the result of calling convert a header list to an HttpHeader sequence given request’s header list, config’s requestsAllHeaders, and isRequest equal totrue
. -
Queue a global task on the DOM manipulation task source of embedderGlobal that will call config’s handler given details.
-
-
Let configs and blocking be the results of calling lookup registered WebRequest handler configs given "headersReceived", and request.
-
Let combinedResults be an empty
BlockingResponse
. -
Let pendingHandlerCount be configs’s size.
-
Let embedderGlobal be the relevant global object of the result of getting an environment’s embedderParent given request’s client.
-
For each config in configs:
-
Let details be the result of calling create a WebRequestResponseEventDetails object given request and response.
-
If config’s requestsHeaders is
true
, then set details["responseHeaders
"] to the result of calling convert a header list to an HttpHeader sequence given response’s header list, config’s requestsAllHeaders, and isRequest equal tofalse
. -
Queue a global task on the DOM manipulation task source of embedderGlobal that will run the following steps:
-
Let result be the result of calling config’s handler given details.
Note: Any exceptions thrown by the handler are intentionally ignored and will not affect the request.
-
If all keys in result are contained in the set « "cancel", "redirectUrl", "responseHeaders" », then:
-
If result["
cancel
"] istrue
, then set combinedResults["cancel
"] totrue
. -
If result["
redirectUrl
"] is a valid URL string and combinedResults["redirectUrl
"] is undefined, then set combinedResults["redirectUrl
"] to result["redirectUrl
"]. -
If result["
responseHeaders
"] is a list whose size > 0, then:-
Set combinedResults["
responseHeaders
"] to [] if it is not defined. -
Append the contents of result["
responseHeaders
"] to combinedResults["responseHeaders
"].
-
-
-
Decrement pendingHandlerCount.
-
-
-
If blocking is
true
, then wait in parallel for pendingHandlerCount to equal 0, then queue a global task on the networking task source of request’s client’s global object that will continue the remaining steps of this algorithm. -
Return combinedResults.
-
Let configs and blocking be the results of calling lookup registered WebRequest handler configs given "authRequired", and request.
-
Let challenger be an
AuthChallenger
withhost
andport
equal to the host and port of response’s URL. -
If response’s status is 401, then:
-
Otherwise:
-
If scheme is null, then return null.
-
Let combinedResults be an empty
BlockingResponse
. -
Let pendingHandlerCount be configs’s size.
-
Let embedderGlobal be the relevant global object of the result of getting an environment’s embedderParent given request’s client.
-
For each config in configs:
-
Let details be the result of calling create a WebRequestResponseEventDetails object given request and response.
-
If config’s requestsHeaders is
true
, then set details["responseHeaders
"] to the result of calling convert a header list to an HttpHeader sequence given response’s header list, config’s requestsAllHeaders, and isRequest equal tofalse
. -
Set details["
challenger
"], details["isProxy
"], details["scheme
"], and details["realm
"] fields equal to challenger, isProxy, scheme, and realm respectively. -
Queue a global task on the DOM manipulation task source of embedderGlobal that will run the following steps:
-
Let result be null.
-
If config’s asyncBlocking flag is
true
, then:-
Let callback be a function that takes a
BlockingResponse
blockingResponse argument and when executed will set result to blockingResponse. -
Call config’s handler given details and callback.
-
Wait in parallel for callback to be invoked, and then continue executing these steps.
-
-
Otherwise:
-
Set result to the result of calling config’s handler given details.
Note: Any exceptions thrown by the handler are intentionally ignored and will not affect the request.
-
-
If all keys in result are contained in the set « "cancel", "authCredentials" » and result["
authCredentials
"] is either undefined or a dictionary containing two keys equal to "username" and "password", then:-
If result["
cancel
"] istrue
, then set combinedResults["cancel
"] totrue
. -
If result["
authCredentials
"] is defined and combinedResults["authCredentials
"] is undefined, then set combinedResults["authCredentials
"] to result["authCredentials
"].
-
-
Decrement pendingHandlerCount.
-
-
-
If blocking is
true
, then wait in parallel for pendingHandlerCount to equal 0, then queue a global task on the networking task source of request’s client’s global object that will continue the remaining steps of this algorithm. -
Return combinedResults.
-
Let configs be the result of calling lookup registered WebRequest handler configs given "beforeRedirect", and request.
-
Let embedderGlobal be the relevant global object of the result of getting an environment’s embedderParent given request’s client.
-
For each config in configs:
-
Let details be the result of calling create a WebRequestResponseWithIpEventDetails object given request and response.
-
If config’s requestsHeaders is
true
, then set details["responseHeaders
"] to the result of calling convert a header list to an HttpHeader sequence given response’s header list, config’s requestsAllHeaders, and isRequest equal tofalse
. -
Let internalResponse be response, if response is not a filtered response; otherwise response’s internal response.
-
Set details["
redirectUrl
"] to internalResponse’s location URL given request’s current URL’s fragment. -
Queue a global task on the DOM manipulation task source of embedderGlobal that will call config’s handler given details.
-
-
Let configs be the result of calling lookup registered WebRequest handler configs given "responseStarted", and request.
-
Let embedderGlobal be the relevant global object of the result of getting an environment’s embedderParent given request’s client.
-
For each config in configs:
-
Let details be the result of calling create a WebRequestResponseWithIpEventDetails object given request and response.
-
If config’s requestsHeaders is
true
, then set details["responseHeaders
"] to the result of calling convert a header list to an HttpHeader sequence given response’s header list, config’s requestsAllHeaders, and isRequest equal tofalse
. -
Queue a global task on the DOM manipulation task source of embedderGlobal that will call config’s handler given details.
-
-
Let configs be the result of calling lookup registered WebRequest handler configs given "completed", and request.
-
Let embedderGlobal be the relevant global object of the result of getting an environment’s embedderParent given request’s client.
-
For each config in configs:
-
Let details be the result of calling create a WebRequestResponseWithIpEventDetails object given request and response.
-
If config’s requestsHeaders is
true
, then set details["responseHeaders
"] to the result of calling convert a header list to an HttpHeader sequence given response’s header list, config’s requestsAllHeaders, and isRequest equal tofalse
. -
Queue a global task on the DOM manipulation task source of embedderGlobal that will call config’s handler given details.
-
-
Let configs be the result of calling lookup registered WebRequest handler configs given "errorOccurred", and request.
-
Let embedderGlobal be the relevant global object of the result of getting an environment’s embedderParent given request’s client.
-
For each config in configs:
-
Let details be the result of calling create a WebRequestResponseWithIpEventDetails object given request and response.
-
If config’s requestsHeaders is
true
, then set details["responseHeaders
"] to the result of calling convert a header list to an HttpHeader sequence given response’s header list, config’s requestsAllHeaders, and isRequest equal tofalse
. -
Set config’s
error
field to an implementation-defined error message describing the error in response. -
Queue a global task on the DOM manipulation task source of embedderGlobal that will call config’s handler given details.
-
WebRequestEventDetails
object given a request request, run the following steps:
-
Let environmentSettingsObject be request’s client.
-
Let details be a
WebRequestEventDetails
with the following fields:timeStamp
-
The current high resolution time given this’s relevant global object.
Note: This timestamp isn’t coarsened because Controlled Frames are only available within isolated contexts, which always have the cross-origin isolated capability.
url
-
The last element of request’s URL list.
method
-
request’s method.
initiator
-
The serialization of an origin given request’s origin.
Note: An opaque origin will result in
initiator
being set to theDOMString
"null". type
-
The result of calling get a request’s ResourceType given request.
requestId
-
request’s requestId.
frameId
-
-1
parentFrameId
-
-1
-
If environmentSettingsObject’s global object is a
Window
object, then:-
Let window be environmentSettingsObject’s global object.
-
Update the following fields of details:
documentId
-
environmentSettingsObject’s id.
documentLifecycle
-
The result of getting the DocumentLifecycle of a Document given window’s associated document.
frameId
frameType
-
"fenced_frame"
if window’s browsing context’s fenced frame config instance is non-null,"outermost_frame"
if parentNavigable is null,"sub_frame"
otherwise.
-
If parentNavigable is not null, then update the following values of details:
parentDocumentId
-
The id of parentNavigable’s active document’s relevant global object.
parentFrameId
-
The frameId of parentNavigable.
-
-
Return details.
DocumentLifecycle
of a Document
document,
run the following steps:
-
If document’s unload counter > 0, then return "
pending_deletion
". -
If document’s node navigable is non-null and is a prerendering navigable, then return "
prerender
". -
If document is salvageable and does not have its page showing, return "
cached
". -
Return "
active
".
WebRequestResponseEventDetails
object given a request request, a response response, a boolean requestsHeaders, and a boolean requestsAllHeaders,
run the following steps:
-
Let details be the result of creating a WebRequestEventDetails object given request.
-
Update the following fields in details:
statusCode
-
response’s status.
statusLine
-
response’s status message.
-
If requestsHeaders is
true
, then set details["responseHeaders
"] to the result of calling convert a header list to an HttpHeader sequence given response’s header list, requestsAllHeaders, and isRequest equal tofalse
. -
Return details.
WebRequestResponseWithIpEventDetails
object given a request request, a response response,
a boolean requestsHeaders, and a boolean requestsAllHeaders,
run the following steps:
-
Let details be the result of creating a WebRequestResponseEventDetails object given request, response, requestsHeaders, and requestsAllHeaders.
-
If response’s cache state is "local", then set details["
fromCache
"] totrue
. -
Set details["
ip
"] to the ip address from which response was received if the request involved a network request.The [FETCH] spec currently doesn’t specify storing the remote IP address used when sending request.
-
Return details.
HttpHeader
sequence given
a header list fetchHeaders, a boolean requestsAllHeaders, and
a boolean isRequest, run the following steps:
-
Let headers be a an empty list of
HttpHeader
objects. -
For each fetchHeader in fetchHeaders:
-
If all of the following conditions are met, then continue:
-
isRequest is
true
-
requestsAllHeaders is
false
-
fetchHeader is not a CORS-safelisted request-header
-
-
If all of the following conditions are met, then continue:
-
isRequest is
false
-
requestsAllHeaders is
false
-
fetchHeader[0] is not a CORS-safelisted response-header name
-
-
Let header be a new
HttpHeader
. -
Set header["
name
"] to the isomorphic decoding of fetchHeader[0]. -
Let value be the isomorphic decoding of fetchHeader[1] .
-
If value is a scalar value string, then set header["
value
"] to value. -
Otherwise, set header["
binaryValue
"] to fetchHeader[1]. -
Append header to headers.
-
-
Return headers.
HttpHeader
sequence to a header list given
a HttpHeader
headers, run the following steps:
-
Let headerList be a an empty header list.
-
For each header in headers:
-
If any of the following conditions are
true
, throw aTypeError
: -
Let value be header["value"] if it exists, or the isomorphic decoding of header["binaryValue"] otherwise.
-
Append a new tuple with values « header["name"], value » to headerList.
-
-
Return headerList.
ResourceType
given a request request, run the following steps:
-
If request’s url’s scheme equals
"ws"
or"wss"
, then return "websocket
". -
If request’s initiator equals
"fetch"
or"xmlhttprequest"
, then return "xmlhttprequest
". -
If request’s destination equals
"document"
, then return "main_frame
". -
If request’s destination equals
"frame"
or"iframe"
, then return "sub_frame
". -
If request’s destination equals
"style"
or"xslt"
, then return "stylesheet
". -
If request’s destination equals
"script"
,"json"
,"audioworklet"
,"paintworklet"
,"serviceworker"
,"sharedworker"
, or"worker"
, then return "script
". -
If request’s destination equals
"image"
, then return "image
". -
If request’s destination equals
"font"
, then return "font
". -
If request’s destination equals
"object"
or"embed"
, then return "object
". -
If request’s destination equals
"audio"
,"track"
, or"video"
, then return "media
". -
If request’s destination equals
"report"
, then return "csp_report
". -
If request’s destination equals
""
and request’s keepalive istrue
, then return "ping
". -
Return "
other
".
DOMString
redirectUrl,
return a response with the following fields:
- status
-
301
- header list
-
« ("Location", redirectUrl) »
4.1. WebRequest handler config
A WebRequest handler config is a struct with the following items:
- handler
- filter
- requestsBody
-
a boolean
- requestsHeaders
-
a boolean
- requestsAllHeaders
-
a boolean
- blocking
-
a boolean
- asyncBlocking
-
a boolean
DOMString
eventName, and a request request, run the
following steps:
-
Let client be request’s client.
-
If client is null, return an empty list and
false
. -
If client’s corresponding global object is not a
Window
, return an empty list andfalse
. -
Let navigable be the navigable that client’s global object is within.
-
If navigable’s embedderParent is null, return an empty list and
false
. -
Let controlledFrame be the
HTMLControlledFrameElement
corresponding to navigable’s embedderParent. -
Let validHandlers be an empty list.
-
Let blocking be
false
. -
Let handlerMap be controlledFrame’s
request
’s handler map. -
For each handlerConfig in handlerMap[eventName]:
-
Let filter be handlerConfig’s filter.
-
Let types be filter["
types
"]. -
If types is not empty and types does not contain the result of calling get a request’s ResourceType given request, then continue.
-
Let urls be filter["
urls
"]. -
Let isValidUrl be
true
if urls is empty,false
otherwise. -
For each urlPattern in urls:
-
If request’s URL matches a match pattern given urlPattern, set isValidUrl to
true
.
-
-
If isValidUrl is
false
, then continue. -
If handlerConfig’s blocking or asyncBlocking is
true
, then set blocking totrue
. -
Append handlerConfig to validHandlers.
-
-
Return validHandlers and blocking.
4.2. Monkey Patches
4.2.1. Fetch
A request has an associated requestId, which is an opaque string, randomly assigned at the request’s creation.
The main fetch algorithm is monkey patched as follows:
-
Let request be fetchParams’s request.
-
Let response be null.
- Let webRequestResult be the result of calling process beforeRequest events given request.
-
If webRequestResult is not null, then:
-
If webRequestResult["
cancel
"] istrue
, then set response to a network error. -
Otherwise, if webRequestResult ["
redirectUrl
"] is not an emptyDOMString
, then set response to the result of creating a redirect response given webRequestResult["redirectUrl
"].
-
If webRequestResult["
The fetch response handover algorithm is monkey patched as follows:
- If response is not a network error, then call process responseStarted events given fetchParams’s request and response.
-
Let timingInfo be fetchParams’s timing info.
⋮
-
If fetchParams’s process response consume body is non-null, then:
…
- If response is not a network error, then call process completed events given fetchParams’s request and response.
- Otherwise, call process errorOccurred events given fetchParams’s request and response.
The HTTP-network-or-cache fetch algorithm is monkey patched as follows:
-
Let the revalidatingFlag be unset.
- Set webRequestResult to the result of calling process beforeSendHeaders events given request.
-
If webRequestResult is not null, then:
-
If webRequestResult["
cancel
"] istrue
, then set response to a network error. -
Otherwise, if webRequestResult ["
requestHeaders
"] is a non-empty list, then set request’s header list to the result of converting an HttpHeader sequence to a header list given webRequestResult ["requestHeaders
"].
-
If webRequestResult["
-
If response is not null,
run these steps, but abort when fetchParams is canceled:
⋮
-
If aborted, then return the appropriate network error for fetchParams.
-
If response is null, then:
-
If httpRequest’s cache mode is "
only-if-cached
", then return a network error. - Call process sendHeaders events given request.
-
Let forwardResponse be the result of running HTTP-network fetch given httpFetchParams, includeCredentials, and isNewConnectionFetch.
- Let webRequestResult be the result of calling process headersReceived events given request and forwardResponse if forwardResponse is not a network error, null otherwise.
-
If webRequestResult is not null, then:
-
If webRequestResult["
cancel
"] istrue
, then set response to a network error. -
Otherwise, if webRequestResult ["
redirectUrl
"] is not an emptyDOMString
, then set forwardResponse to the result of creating a redirect response given webRequestResult["redirectUrl
"]. -
Otherwise, if webRequestResult ["
responseHeaders
"] is a non-empty list, then set forwardResponse’s header list to the result of converting an HttpHeader sequence to a header list given webRequestResult ["responseHeaders
"].
-
If webRequestResult["
-
⋮
-
If response’s status is 401, httpRequest’s response tainting is not "cors", includeCredentials is
true
, and request’s window is an environment settings object, then:⋮
-
If request’s use-URL-credentials flag is unset or isAuthenticationFetch is
true
, then:-
If fetchParams is canceled, then return the appropriate network error for fetchParams.
-
Let username and password be null.
- Let webRequestResult be the result of calling process authRequired events given request and response.
-
If webRequestResult is not null, then:
-
If webRequestResult["
cancel
"] istrue
, then set response to a network error. -
Otherwise, if webRequestResult["
authCredentials
"] is anobject
, then:-
Set username to webRequestResult["
authCredentials
"]["username
"]. -
Set password to webRequestResult["
authCredentials
"]["password
"].
-
-
If webRequestResult["
- If username and password are null, then set them to the result of prompting the end user for a username and password, respectively, in request’s window.
-
-
-
If response’s status is 407, then:
- Let webRequestResult be the result of calling process authRequired events given request and response.
-
If webRequestResult is not null, then:
-
If webRequestResult["
cancel
"] istrue
, then set response to a network error. -
Otherwise, if webRequestResult["
authCredentials
"] is anobject
, then:-
Store webRequestResult["
authCredentials
"] as a proxy-authentication entry.
-
-
If webRequestResult["
- Otherwise, prompt the end user as appropriate ...
The HTTP-redirect fetch algorithm is monkey patched as follows:
- Call process beforeRedirect events given request and response.
-
Let request be fetchParams’s request.
5. Context Menus API
This API is based on the ContextMenus API, which is available through the <webview> element in Chrome Apps. It is exposed to Controlled Frame with minimum modification to make efficient use of prior art. As a result, this API does not fully adhere to Web Platform best practices, particularly around naming conventions and event handling. If there is future cross-browser interest in Controlled Frame, this API should be revisited to align better with other Web APIs.
enum {
ContextType ,
"all" ,
"page" ,
"frame" ,
"selection" ,
"link" ,
"editable" ,
"image" ,
"video" , };
"audio" enum {
ItemType ,
"normal" ,
"checkbox" ,
"radio" , };
"separator" dictionary {
OnClickData boolean ;
checked boolean ;
editable long ;
frameId USVString ;
frameUrl USVString ;
linkUrl DOMString ; (
mediaType DOMString or long );
menuItemId USVString ; (
pageUrl DOMString or long );
parentMenuId DOMString ;
selectionText USVString ;
srcUrl boolean ; };
wasChecked callback =
ContextMenusCallback undefined (optional OnClickData ); [
info Exposed =Window ,IsolatedContext ]interface {
ContextMenusEvent undefined addListener (ContextMenusCallback );
callback undefined removeListener (ContextMenusCallback );
callback boolean hasListener (ContextMenusCallback );
callback boolean hasListeners (); }; [Exposed =Window ,IsolatedContext ]interface :
OnClickedEvent ContextMenusEvent {}; [Exposed =Window ,IsolatedContext ]interface :
OnShowEvent ContextMenusEvent {};dictionary {
ContextMenusProperties boolean ;
checked sequence <ContextType >;
contexts sequence <USVString >;
documentUrlPatterns boolean ; (
enabled DOMString or long );
parentId sequence <USVString >;
targetUrlPatterns DOMString ;
title ItemType ;
type ContextMenusCallback ; };
onclick dictionary :
ContextMenusCreateProperties ContextMenusProperties {required DOMString ; }; [
id Exposed =Window ,IsolatedContext ]interface {
ContextMenus attribute OnClickedEvent onClicked ;attribute OnShowEvent onShow ;Promise <undefined >create (ContextMenusCreateProperties );
properties Promise <undefined >remove (DOMString );
id Promise <undefined >removeAll ();Promise <undefined >update (DOMString ,
id optional ContextMenusProperties = {}); };
properties
Each controlledframe
has a contextMenus
member, which is a ContextMenus
that manages a context menu map whose keys are DOMString
s and whose values are ContextMenusProperties
.
Each entry of the context menu map has the value property which represents a context menu item. A context menu item will be shown on the context menu if it is opened within the controlledframe
controlledframe and the result of determining whether the context menu item will be shown given controlledframe, the context menu, and property equals true
.
Each ContextMenus
has an associated onClicked,
which is an OnClickedEvent
.
Each ContextMenus
has an associated onShow,
which is an OnShowEvent
.
The onClicked
getter steps are to return this’s onClicked.
The onShow
getter steps are to return this’s onShow.
The create(properties)
method steps are:
-
Let p be a new promise.
-
Let controlledframe be this.
-
Return p and run the following steps in parallel.
-
Let contextMenusMap be controlledframe’s context menu map.
-
Let id be the properties["
menuItemId
"]. -
If contextMenusMap[id] exists, reject p with a
TypeError
and abort these steps. -
Set contextMenusMap[id] to properties.
-
Resolve an embedder promise given controlledframe and p.
The remove(id)
method steps are:
-
Let p be a new promise.
-
Let controlledframe be this.
-
Return p and run the following steps in parallel.
-
Let contextMenusMap be controlledframe’s context menu map.
-
Remove contextMenusMap[id].
-
Resolve an embedder promise given controlledframe and p.
The removeAll()
method steps are:
-
Let p be a new promise.
-
Let controlledframe be this.
-
Return p and run the following steps in parallel.
-
Let contextMenusMap be controlledframe’s context menu map.
-
Clear contextMenusMap.
-
Resolve an embedder promise given controlledframe and p.
The update(id, properties)
method steps are:
-
Let p be a new promise.
-
Let controlledframe be this.
-
Return p and run the following steps in parallel.
-
Let contextMenusMap be controlledframe’s context menu map.
-
If contextMenusMap[id] does not exist, reject p with a
TypeError
and abort these steps. -
Set contextMenusMap[id] to properties.
-
Resolve an embedder promise given controlledframe and p.
The values of the context menu map, which are ContextMenusProperties
objects, control the conditions under which the context menu items are displayed, as well as the features and behaviors
of the items.
This section is non-normative.
ContextMenusProperties
has the following fields:
contexts
-
A list of different
ContextType
. If it is not empty, then the context menu item will not be shown unless the element that was clicked on to open the context menu equals one of the list items. If it is empty, then this check is ignored. documentUrlPatterns
-
A list of strings that are match patterns. If it is not empty, then the context menu item will not be shown unless the URL of the embedded document matches a match pattern with one of the list items. If it is empty, then this check is ignored.
targetUrlPatterns
-
A list of strings that are match patterns. If it is not empty, then the context menu item will not be shown unless the URL of the target of the context menu matches a match pattern with one of the list items. If it is empty, then this check is ignored.
Note: Target is the "src" attribute of img/audio/video tags and the "href" of anchor tags.
parentId
-
The ID of the parent context menu item. The context menu item may appear under a sub-menu of the parent.
title
-
The title of the menu item.
type
-
The type of the menu item.
onclick
-
A
ContextMenusCallback
that is invoked when the context menu item is clicked. checked
-
Whether the context menu item is initially checked, if the
type
ischeckbox
. enabled
-
Whether the context menu item is enabled.
To determine whether the context menu item will be shown given a controlledframe
element controlledframe, a context menu menu, and a ContextMenusProperties
properties:
-
Let element be the
HTMLElement
that menu is opened at or null if there is none. -
Let documentUrl be the URL of controlledframe’s embedded document.
-
Let targetUrl be an empty string.
-
If element is an instance of
HTMLImageElement
, then set targetUrl to thesrc
attribute of element. -
If element is an instance of
HTMLVideoElement
, then set targetUrl to thesrc
attribute of element. -
If element is an instance of
HTMLAudioElement
, then set targetUrl to thesrc
attribute of element. -
If element is an instance of
HTMLAnchorElement
, then set targetUrl to the href attribute of element.
-
-
If properties["
contexts
"] is not empty:-
Let matchesContext be a boolean value that is initially
false
. -
For each context in properties["
contexts
"]:-
If the context of menu matches context, set matchesContext to
true
and break;
-
-
If matchesContext is
false
, returnfalse
.
-
This section is non-normative.
ContextType
s represent the context of a context menu, can be following values:
frame
-
Applies when the user context-clicks in a nested frame, such as an
iframe
. selection
-
Applies when part of the document is selected.
link
-
Applies when the user context-clicks on a link.
editable
-
Applies when the user context-clicks an editable element, like a
textarea
. image
-
Applies when the user context-clicks an image.
video
-
Applies when the user context-clicks a
video
element. audio
-
Applies when the user context-clicks an
audio
element. page
-
Applies when the user context-clicks in the page, but none of the other page contexts apply (for example, the click is not on an image or a nested iframe or a link).
all
-
Specifying all is equivalent to the combination of all other contexts.
-
If properties["
documentUrlPatterns
"] is not empty:-
Let matchesDocumentUrl be a boolean value that is initially
false
. -
For each urlPattern in properties["
documentUrlPatterns
"]:-
If documentUrl matches a match pattern, given urlPattern, set matchesDocumentUrl to
true
and break;
-
-
If matchesDocumentUrl is
false
, returnfalse
.
-
-
If properties["
targetUrlPatterns
"] is not empty:-
Let matchesTargetUrl be a boolean value that is initially
false
. -
For each urlPattern in properties["
targetUrlPatterns
"]:-
If targetUrl matches a match pattern, given urlPattern, set matchesTargetUrl to
true
and break;
-
-
If matchesTargetUrl is
false
, returnfalse
.
-
-
Note: Different user agents may implement additional conditions.
-
Return
true
.
ContextMenusEvent
represents a target to which an event can be dispatched when a context menu interaction has occured.
Each ContextMenusEvent
has an event listener list which is a list of ContextMenusCallbacks. It is initially an empty list.
The addListener(callback)
method steps are:
-
Let callbackList be the event listener list of this.
-
Append callback to callbackList.
The removeListener(callback)
method steps are:
-
Let callbackList be the event listener list of this.
-
For each listItem in callbackList:
-
If listItem equals to callback, remove listItem from callbackList.
-
The hasListener(callback)
method steps are:
-
Let callbackList be the event listener list of this.
-
For each listItem in callbackList:
-
If listItem equals to callback, return
true
.
-
-
Return
false
.
The hasListeners()
method steps are:
-
Let callbackList be the event listener list of this.
-
If callbackList is empty, return
false
. -
Otherwise, return
true
.
ContextMenus
has the attribute onShow
, which is a ContextMenusEvent
that is associated with contextmenu events.
To dispatch an onShow
event event, given HTMLControlledFrameElement
controlledFrame:
-
Let callbackList be the event listener list of event.
-
For each callback in callbackList:
-
Queue a global task on the DOM manipulation task source of controlledFrame’s relevant global object to invoke callback.
ContextMenus
has the attribute onClicked
, which is a ContextMenusEvent
that is associated with click events on a context menu item.
To dispatch an onClicked
event event, given HTMLControlledFrameElement
controlledFrame, element as the HTMLElement
inside the embedded document where the context menu is opened at, menuItem as the context menu item that was clicked.
-
Let id be the key of the context menu map’s entry that is associated with menuItem.
-
Let properties be the result of getting the value of the entry in context menu map given the key id.
-
Let info be a new
OnClickData
.-
Update the following fields of info:
editable
-
Whether the element selected is editable, such as a text input.
frameId
-
The frameId of the navigable container from which the contextmenu event is dispatched.
frameUrl
-
The URL of the navigable container from which the contextmenu event is dispatched.
menuItemId
-
id.
pageUrl
-
The URL of the embedded navigable.
-
Update the following optional fields of info:
Note: Different user agents may set these fields differently.
checked
-
Whether the context menu item is checked.
linkUrl
-
If element is an instance of
HTMLAnchorElement
, element’s href attribute. mediaType
-
One of "image", "video", or "audio", if any, based on element.
parentMenuId
-
properties["
parentId
"]. selectionText
-
The text for the context selection, if any.
srcUrl
-
The "src" attribute of element, if it exists.
wasChecked
-
The state of a checkbox or radio item before it was clicked.
-
-
Let callbackList be the event listener list of event.
-
For each callback in callbackList:
-
Queue a global task on the DOM manipulation task source of controlledFrame’s relevant global object to invoke callback with info.
-
If the
onclick
field of properties is not null: -
Queue a global task on the DOM manipulation task source of controlledFrame’s relevant global object to invoke properties["
onclick
"] with info.
6. Usage Overview
Lorem ipsum. Insert basic info and example here.
7. Motivating Applications
This section is non-normative.
7.1. Latency-sensitive applications in virtualized sessions
In virtualized environments, users typically have a local thin client that renders a full virtual desktop. The actual desktop execution environment will be running on a remote virtualization server. If the user’s browser navigates to a latency-sensitive application (such as a video app), the rendered content will have additional latency ("lag") that makes the experience difficult or impossible for the user. This also applies for applications that record the user, such as video conferencing applications. In these latency-sensitive applications, the virtual desktop application can render the latency-sensitive content locally and overlay it on top of the rendered remote content to reduce this latency. This use case is also known as "browser content redirection."
7.2. Embedding third party web content without restriction
In a kiosk environment, applications must load content from third parties and
display that content on screens within their applications. A teacher may trigger
the navigation event, or it may be configured by an administrator such as a
shopping mall manager. The content may prohibit embedding by iframe
through
the use of X-Frame-Options and CSP. An controlled frame, however, should be able
to load all content, even content that prohibits embedding by iframe
.
7.3. Remote display and manipulation of web content
In a kiosk environment, applications must ensure that content continues to display on screens and may need to interrupt content with their own supplied behaviors. This behavior should work without local attendance by an administrator, and ideally can be managed remotely over the network. If content were to crash, for example, these applications should observe and respond to the crash by reloading the content in a fresh embedded view.
7.4. Clearing user content after each session
In some environments, someone only uses a single device for a brief time to complete their task, like ordering in a restaurant. When their task is complete, the embedder application should be able to clear all of the local user data associated with the task and then restart the embedded instance.
7.5. Monitor for idle sessions
While users interact with embedded content, the user may not explicitly end their session. This content may assume the user is present when they have actually finished or departed without completing the task. Embedder applications want to detect when users idle over their case’s threshold and begin a fresh session.
7.6. Arbitrarily blocking navigations
While displaying embedded web content that’s not authored by the embedder, pages may link to third party web content that’s disallowed. Allowing the embedder to edit elements in embedded content through arbitrary script injection into the web content can ensure navigation cannot occur to blocked pages. The embedder can also use the Controlled Frame API to capture navigation events and ensure that only pages to approved sites can be loaded within that controlled frame.
8. Security, Privacy, and Accessibility Considerations
This section is non-normative.
8.1. Security
Controlled Frame is based upon [Isolated-Web-Apps] (IWA) and integrates with core security specs
Since Controlled Frame is a particularly powerful API, using it or even having it available makes an app a target of various types of hacking. As a result, this API is limited to use in IWA which have additional safeguards in place to protect application developers and users. The Isolated Web App explainer has this to say:
"A user agent may also force an application to adopt this threat model if the developer needs access to APIs which would make the application an appealing target for XSS or server-side attacks."
Controlled Frame makes just such an appealing target, and to expose this with caution we’re opting into IWA to guard against certain attacks. Generally, IWAs provide strong security assurances that each of the resources in an application are secure both at rest and in-transit. You can read more about IWAs security and permissions in the IWA explainer and the IWAs [High-Watermark-Permissions] explainer.
Controlled Frame integrates with [Permissions-Policy] and [Permissions]. You can read more about Permissions Policy § 12. Privacy and Security and Permissions § E Security considerations (note the entry is currently sparse).
Attacking web sites could display content that doesn’t otherwise allow itself to be embedded and trick users on non-IWAs.
Planned mitigation:
-
Controlled Frame will only be available within IWAs
An IWA may embed another IWA (or itself) via Controlled Frame to manipulate our IWA policies somehow (e.g. an Controlled Frame embedded IWA may detect it’s being embedded due to the absence of the "controlled-frame" policy-controlled feature).
Planned mitigation:
-
Controlled Frame can only point to "https" schemes, excluding the "isolated-app" scheme used for IWAs
Controlled Frame could gain access to the powerful <controlledframe> element.
An IWA that’s not expected to use Controlled Frame may attempt to embed content.
Planned mitigation:
-
IWA APIs can never be delegated to cross-origin, so it will not be possible for any nested top-level navigable to access an IWA.
-
Secondly, only embedder applications and their same-origin IWA child navigables that have been granted the "controlled-frame" policy-controlled feature will have the Controlled Frame element available.
-
Same-origin child navigables without the "controlled-frame" policy-controlled feature will not be provided a Controlled Frame element. Their inner same-origin nested navigables will always not have it available.
An IWA may attempt to embed content from non-https schemes, such as 'http:' or 'isolated-app:'
Planned mitigation:
-
Controlled Frame will only work when the navigable’s "src" URL has an 'https:' scheme.
Malicious Controlled Frame could access the embedder’s running process (eg. Spectre attack)
Planned mitigation:
-
Controlled Frame will be executed in a separate process from the embedder’s process
Controlled Frame for a given "https origin" could interact or interfere with the user’s own storage data for that https origin
Planned mitigation:
-
We’re adding a Partition concept. Every Partition is a tuple of StorageKey and a separate object key.
-
Let there be a default partition with key=0 that stores "non-IWA" window and tab usage.
-
Controlled Frame will always store data in a certain StorageKey which is apart from the default partition.
-
Data written to by a given "https origin" while the user accesses that origin via an IWA Controlled Frame will be isolated from the default partition.
-
All usage will be separated between IWA and each partition will be fully isolated from each other and from default usage outside of IWA.
Malicious Controlled Frame could overwrite embedder’s stored data
-
The embedder and embedded storage user agent could overlap, and possibly multiple same-site IWA child navigables could be affected by activity in the Controlled Frame
-
if storage user agents were shared between the embedder and embedded sites, clearing data for either one could negatively impact the other
Planned mitigation:
-
IWA and Controlled Frame will always have separate storage user agents
-
A Controlled Frame should not have read or write access to other storage user agents besides its own
Malicious Controlled Frame may detect it is embedded and attempt to attack the embedder application
Planned mitigation:
-
The user agent will match the browser.
-
The Controlled Frame storage user agent will be separate from the IWA and the default storage user agents.
-
The Controlled Frame process will be separate from the IWA and the default renderer and browser processes.
-
The Controlled Frame environment will appear to be the top-most navigable:
-
window should match window.parent and window.top
-
List of policy-controlled features and their disable/enable status should match the default for a navigable
-
Ideas:
-
Investigate for potential interactions around filesystem, quota storage, and localStorage APIs
User may not be able to verify the origin of the page being viewed in the Controlled Frame
Ideas:
-
Expose the origin to the user somehow, such as adding UI at the top of a Controlled Frame that displays the origin?
-
Have the IWA specify in the manifest the origins that they expect to access?
Controlled Frame may exploit vulnerabilities in out-of-date browser engine
Already addressed with:
-
Existing browser engine auto-update mechanisms
8.2. Privacy
Controlled Frame integrates with Permissions Policy and Permissions. You can read more about Permissions Policy § 12. Privacy and Security. You can read more about Permissions § E Security considerations.
For Controlled Frame specifically, we’ve identified the following privacy considerations:
-
Users' browsing within Controlled Frame will be visible to the IWA
-
IWAs can access and exfiltrate the Controlled Frame’s session cookies (this only applies to the Controlled Frame’s session since they use a separate storage partition from the IWA and the third party origin when browsed in a tab)
-
User activity in Controlled Frame can be observed by the IWA (e.g. keyboard events can be monitored, password entry can be sniffed)
-
User file upload to Controlled Frame can be hijacked
-
User data held in the Controlled Frame’s remote server could be accessed by code implanted by the IWA
-
Users that wish to clear their session history must also do so via the IWA, which will then need to clear the associated storage user agents
-
This would be necessary since embedded storage user agents are separate from the non-embedded storage user agents for any given https origin
-
-
We plan to investigate browser UX to allow users to clear the Controlled Frame storage user agents, the following cases will be considered:
-
If a user wants to clear site data for an IWA, the associated embedded storage user agents will also be cleared
-
This is because if the IWA’s data is cleared, the app will no longer have any context for the associated embedded storage user agents and therefore will no longer be used or useful to the user or organization
-
As a result, we expect that clearing an IWA’s site data will require clearing all of the associated embedded storage user agents
-
-
A user may want to clear all site data for a given "https origin", even if that origin is stored within an IWA’s embedded storage user agent
-
We may choose to provide the ability to clear all IWA site data for that "https origin" even if that site data is held within an embedded storage user agent
-
If we chose to clear the "https origin" data, IWAs would need to prepare for the possibility that embedded storage user agents may be removed outside of their control, and this may be disruptive to the IWA and introduce complexity of implementation
-
Supporting this in the browser user agent exposes browser vendors, developers, and users to additional complexity, so we may choose not to support this approach and instead leave this up to IWA developers to implement
-
As a counter example to supporting clearing a single given "https origin"'s embedded storage user agent, consider that to our knowledge no operating system behaves that way
-
i.e. there’s no central "clear browsing data" option which clears storage for all installed browser engines, each application’s storage is treated as its own to manage
-
-
-
User wants to clear the site data for a given IWA’s Controlled Frame-embedded storage user agent for a given "https origin"
-
User wants to clear the site data for a given IWA’s Controlled Frame-embedded storage user agents for all "https origins"
-
-
An IWA will need the ability to clear the storage user agent’s Controlled Frame-embedded storage user agent for a given "https origin"
8.3. Accessibility
For Controlled Frame, we’ve identified the following accessibility considerations:
-
Browser user agents' accessibility tools and APIs should have visibility into Controlled Frame
-
IWAs should expect to provide their own accessibility tools for Controlled Frame content in order to properly integrate accessibility features for some use cases (such as "browser content redirection")
9. Acknowledgements
The following people contributed to the development of this document.