1. 简介
本规范描述了一种内容嵌入 API,它满足 IWA 的一些
关键用例,而这些用例是
iframe
不支持的。该嵌入
环境应允许在没有被嵌入站点明确许可的情况下嵌入所有内容,
包括
iframe
无法嵌入的内容,并让
嵌入站点对这些被嵌入内容拥有更多控制。
由于这是一个特别强大的 API,其使用和可用性会使应用 成为各种类型黑客攻击的目标。因此,该 API 仅限用于 已具备额外安全 保障以保护用户和开发者的隔离 Web 应用(IWA)。IWA 不是普通的 Web 应用,并且只能存在于特殊的 'isolated-app:' 方案下。这意味着 按设计,该 API 不会对普通网页可用。
注:该 API 并不打算作为
iframe
的替代品或
代用品。所有
iframe
用例仍然有效,并且应继续使用
iframe,
包括在可能的情况下用于 IWA。
2. Fenced Frame 规范
为方便起见,Controlled Frame 规范假定 Fenced Frame 规范已经存在。Fenced Frame 规范中引入了一些概念,例如嵌套的顶级 traversable,这些概念在 Controlled Frame 的上下文中被引用时非常有用。
Fenced Frame 规范通过对某些规范(例如 HTML)打猴子 补丁来定义这些概念。本 Controlled Frame 规范的某些部分 也需要对规范打猴子补丁。
3. controlledframe 元素
- 类别:
- 流内容。
- 短语内容。
- 嵌入内容。
- 交互内容。
- 可感知内容。
- 短语内容。
- 可以使用该元素的上下文:
- 预期使用嵌入内容的位置。
- 内容模型:
- 无内容。
- 内容属性:
- 全局属性
src— 要嵌入的内容源 URLpartition— 用于保存与此内容相关数据的分区名称 - 无障碍考虑事项:
- 面向作者。
- 面向实现者。
注:这些链接指向
iframe元素的无障碍 定义。 从无障碍的角度来看,controlledframe应与iframe表现相同。 - 面向实现者。
- DOM 接口:
-
[
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 ();Promise <boolean >canGoBack ();Promise <boolean >forward ();Promise <boolean >canGoForward ();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 ; };
controlledframe
元素表示其嵌入的
navigable。
controlledframe
元素的后代不表示任何内容。
Controlled Frame 元素暴露给任何具有
"controlled-frame" 策略控制特性,且其
环境设置对象是隔离上下文的任何 Document。
IDL 属性 src 和
partition 必须反映
同名的相应内容属性。
每个
controlledframe
都关联有:
-
嵌入的 navigable,即一个带有非 null controlledFrameEmbedderParent 的 traversable navigable,或 null。 其初始值为 null。
注:嵌入的 navigable表现为一个 parent 为 null 的顶级 traversable。嵌入的 navigable中的内容无法 检测到它被嵌入。
-
contentWindow,一个
WindowProxy或 null。 -
request,一个
WebRequest。 -
contextMenus,一个
ContextMenus。
contentWindow 获取器
步骤是返回 this 的 contentWindow。
request 获取器步骤
是返回 this 的 request。
contextMenus 获取器
步骤是返回 this 的 contextMenus。
controlledframe
元素 element 被插入到一个文档中,且该文档的
浏览上下文为非 null 时,运行以下步骤:
-
如果 element 的
src不为空,则:-
给定 element,初始化 controlledframe。
-
controlledframe
元素 element 被从文档中移除时,
运行以下步骤:
-
给定 element 的 嵌入的 navigable,销毁一个顶级 traversable。
-
将 element 的嵌入的 navigable设置为 null。
controlledframe
元素 element,运行
以下步骤:
-
断言 element 的嵌入的 navigable为 null。
-
令 group 为一个新的浏览上下文组。
-
令 document 为给定 element 的节点文档、element 和 group,创建新的浏览上下文和 文档的第二个返回值。
-
令 traversable 为一个新的traversable navigable。
-
给定 documentState,初始化 navigable traversable。
-
将 traversable 的 controlledFrameEmbedderParent 设置为 element。
-
将 element 的嵌入的 navigable设置为 traversable。
-
令 initialHistoryEntry 为 traversable 的活动会话历史条目。
-
将 initialHistoryEntry 的步数设置为 0。
-
将 initialHistoryEntry 追加到 traversable 的会话历史条目。
这些步骤 是在新的 navigable 中初始化
History.length所必需的。这是 HTML 标准中的一个现有 议题。 -
将 element 的 contentWindow 设置为 document 的
WindowProxy。 -
给定 element 和 element 的
src, 导航 controlledframe。
controlledframe
元素 element,给定一个
USVString
urlString,运行以下步骤:
-
如果 urlString 不是绝对 URL 字符串,则返回。
-
令 historyHandling 为 "
auto"。 -
如果 element 的嵌入的 navigable的活动文档未 完全加载,则将 historyHandling 设置为 "
replace"。 -
使用 element 的 节点文档,并以 historyHandling 作为
NavigationHistoryBehavior, 将 element 的嵌入的 navigable导航到 url。
HTMLControlledFrameElement()
构造器步骤为:
-
将 this 的request设置为一个新的
WebRequest。 -
将 this 的contextMenus设置为一个新的
ContextMenus。
3.1. 通用基础设施
controlledframe
controlledframe、一个 promise promise 以及一个可选的 value,
运行以下步骤:
controlledframe
controlledframe、一个 promise promise 以及一个可选的 value,
运行以下步骤:
true,则一个 URL
url 匹配
URLPattern
pattern:
-
令 result 为给定 pattern 和 url,匹配的结果。
-
如果 result 为 null,则返回
false。 -
返回
true。
3.2. 属性
partition
属性
接受一个标识符,用于指定与 Controlled Frame
实例相关的数据应存储在哪里。该标识符由一个字母数字字符组成的字符串构成。
嵌入的 navigable的所有数据都必须存储
在一个存储搁板中,该搁板由此分区字符串以及
创建该数据的源共同作为键。
默认情况下,所有存储的数据都必须保存在内存中的存储分区中,这样
当最后一个具有给定
partition
值的 Controlled Frame 元素被销毁时,该数据也会
被销毁。当数据保存在此分区中时,Controlled Frame 的
嵌入的 navigable中的任何数据都不得持久化。
如果 partition 属性标识符包含前缀 "persist:",则用户 代理必须使用基于磁盘的存储环境,而不是内存中的 存储分区。被嵌入内容不应能够检测其 存储是在内存中还是持久的。
如果多个 Controlled Frame 共享同一个分区标识符,则它们的所有 嵌入的 navigable实例必须共享同一个 存储分区。
注:下面会对 [STORAGE] 规范打猴子补丁,以基于
partition
属性的值对存储进行分区。
partition
IDL 属性设置器步骤为:
-
如果 this 的嵌入的 navigable不是 null,则:
src 属性
反映 Controlled
Frame 的嵌入的 navigable的当前会话历史条目的
URL。
src
IDL 属性设置器步骤为:
-
如果 this 的嵌入的 navigable为 null,则:
-
否则:
-
给定 this 和给定值,导航 controlledframe。
-
3.3. 导航方法
back()-
在 Controlled Frame 中的 traversable navigable 的整体 会话历史条目列表中后退一步。
返回一个 promise,如果页面成功 后退导航,则解决为
true;如果导航失败或没有上一个 步骤,则解决为false。 canGoBack()-
返回一个 promise,如果当前会话历史条目不是 嵌入的 navigable的 会话历史条目中的第一个条目,则解决为
true。这意味着 该 navigable 还有前一个 会话历史条目。 forward()-
在 Controlled Frame 中的 traversable navigable 的整体 会话历史条目列表中前进一步。
返回一个 promise,如果页面成功 前进导航,则解决为
true;如果导航失败或没有下一个 步骤,则解决为false。 canGoForward()-
返回一个 promise,如果当前会话历史条目不是 嵌入的 navigable的 会话历史条目中的最后一个条目,则解决为
true。这意味着 该 navigable 还有下一个 会话历史条目。 go()-
重新加载当前页面。
go(relativeIndex)-
在当前 traversable navigable 的整体 会话历史条目列表中,后退或前进 relativeIndex 个步骤。
相对索引为零时将重新加载当前页面。
返回一个 promise,如果页面成功 导航,则解决为
true;如果导航失败或提供的相对 索引超出范围,则解决为false。 reload()-
重新加载当前页面。
stop()-
取消文档加载。
controlledframe
controlledframe 和一个整数 delta,运行
以下步骤:
-
令 resultPromise 为一个新的 promise。
-
返回 resultPromise,并并行运行剩余步骤。
-
令 embeddedNavigable 为 controlledframe 的嵌入的 navigable。
-
如果 embeddedNavigable 为 null,则给定 controlledframe、resultPromise 和
false,解决嵌入者 promise,并中止这些 步骤。 -
如果 embeddedNavigable 的活动文档不是完全活动的, 则给定 controlledframe、resultPromise 和
false,解决嵌入者 promise,并中止这些步骤。 -
向 embeddedNavigable 追加以下会话历史 遍历步骤:
-
令 allSteps 为对 embeddedNavigable 获取所有已使用历史步骤 的结果。
-
令 currentStepIndex 为 embeddedNavigable 的 当前会话历史步骤在 allSteps 中的索引。
-
令 targetStepIndex 为 currentStepIndex + delta。
-
如果 allSteps[targetStepIndex] 不存在,则 给定 controlledframe、resultPromise 和
false,解决嵌入者 promise,并中止这些步骤。 -
令 result 为给定 "none" 的用户导航参与,将 遍历历史步骤 allSteps[targetStepIndex] 应用到 embeddedNavigable 的结果。
-
如果 result 不等于 "
applied",则给定 controlledframe、resultPromise 和false, 解决嵌入者 promise。 -
否则,给定 controlledframe、 resultPromise 和
true,解决嵌入者 promise。
-
canGoBack()
方法步骤为:
-
令 result 为一个新的 promise。
-
令 controlledframe 为 this。
-
令 embeddedNavigable 为 controlledframe 的嵌入的 navigable。
-
如果 embeddedNavigable 为 null,则用
false解决 result 并返回 result。 -
在 embeddedNavigable 的节点文档的相关全局对象的导航和遍历任务源上 排队一个全局任务,它将运行以下步骤:
-
如果 embeddedNavigable 的 当前会话历史步骤 > 0, 则令 canGoBack 为
true,否则为false。 -
给定 controlledframe、result 和 canGoBack,解决嵌入者 promise。
-
-
返回 result。
canGoForward()
方法步骤为:
-
令 result 为一个新的 promise。
-
令 controlledframe 为 this。
-
令 embeddedNavigable 为 controlledframe 的嵌入的 navigable。
-
如果 embeddedNavigable 为 null,则用
false解决 result 并返回 result。 -
在 embeddedNavigable 的节点文档的相关全局对象的 导航和遍历任务源上 排队一个全局任务,它将运行以下步骤:
-
令 step 为 embeddedNavigable 的当前会话历史步骤。
-
令 steps 为给定 embeddedNavigable,获取所有已使用历史步骤 的结果。
-
如果 step + 1 < steps 的大小, 则令 canGoForward 为
true,否则为false。 -
给定 controlledframe、result 和 canGoForward,解决嵌入者 promise。
-
-
返回 result。
back() 方法步骤为:
-
返回给定 this 和 -1,增量遍历嵌入的 navigable 的历史的结果。
forward() 方法步骤
为:
-
返回给定 this 和 1,增量遍历嵌入的 navigable 的历史的结果。
go(relativeIndex)
方法步骤为:
-
返回给定 this 和 relativeIndex,增量遍历嵌入的 navigable 的历史的结果。
reload() 步骤为:
stop() 步骤为:
3.4. 脚本方法
// 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 <(URLPattern or URLPatternInput )>;urlPatterns sequence <(URLPattern or URLPatternInput )>;excludeURLPatterns boolean ;allFrames boolean ;matchAboutBlank RunAt ; };runAt
- pendingFetchCount
-
一个表示待处理脚本/样式获取次数的
long。 - js
- css
- urlPatterns
-
一个
URLPattern的列表。 - excludeURLPatterns
-
一个
URLPattern的列表。注:如果文档的 URL 匹配这些 模式中的任意一个,则内容不会被注入到该 文档中。这会覆盖 urlPattern;如果两个列表都包含 文档的 URL 所匹配的条目,则内容不会被 注入到该文档中。
- allFrames
-
一个指示内容是否应被注入到页面中的所有 框架,还是仅顶级框架的布尔值。
- matchAboutBlank
-
一个指示内容是否应被注入到 about:blank 页面的布尔值。
- runAt
-
一个
RunAt, 指示 JavaScript 内容应在文档生命周期的何时执行。
controlledframe
controlledframe、一个 USVString
urlString、一个 布尔值 isCss、一个
long
index,以及一个接受 long、
一个 boolean
和一个 DOMString
的算法 completionSteps,运行以下步骤:
注:这里不能使用获取经典脚本,因为获取 需要使用 controlledframe 的相关设置对象,但 经典脚本是使用嵌入的 navigable的 活动文档的相关设置对象执行的。
-
如果 urlString 不是有效 URL 字符串,则:
-
给定 0、
false和 "",运行 completionSteps。 -
返回。
-
-
令 request 为一个具有以下字段的新请求:
-
获取 request,并将 processResponseConsumeBody 设置为以下步骤,给定一个 响应 response 和一个 null、failure 或 字节序列 contents:
-
如果 response 的状态不是 200,或 contents 为 null 或 failure,则给定 0、
false和 "" 运行 completionSteps -
否则,给定 index、
true和 contents 运行 completionSteps。
-
ContentScriptDetails,
给定一个
controlledframe
controlledframe 和一个 ContentScriptDetails
details,运行以下步骤:
-
令 result 为一个新的 promise。
-
如果 details["
js"] 和 details["css"] 均已定义,或均 未定义,则用TypeError拒绝 result,并返回它。 -
如果 details["
urlPatterns"] 为空, 则用TypeError拒绝 result,并返回它。 -
如果 isCss 为
true且 details["runAt"] 不等于 "document-start", 则用TypeError拒绝 result,并返回它。 -
如果 isCss 为
true,则令 injectionItems 为 details["css"], 否则为 details["js"]。 -
如果 injectionItems["
code"] 和 injectionItems["files"] 均已定义,或均 未定义,则用TypeError拒绝 result,并返回它。 -
返回 result,并并行运行剩余步骤。
-
令 config 为一个新的内容脚本配置,具有以下值:
- pendingFetchCount
-
0
- urlPatterns
-
«»
- excludeURLPatterns
-
«»
- allFrames
-
如果已定义,则为 details["
allFrames"], 否则为false - matchAboutBlank
-
如果已定义,则为 details["
matchAboutBlank"], 否则为false - runAt
-
如果已定义,则为 details["
runAt"], 否则为document-idle
-
对于 details["
urlPatterns"] 中的每个 urlPattern:-
如果 urlPattern 是一个
URLPattern, 则将 urlPattern 追加到 config 的urlPatterns。 -
否则,给定 urlPattern,将一个新的
URLPattern追加到 config 的urlPatterns。
-
-
如果 details["
excludeURLPatterns"] 已定义, 则:-
对于 details["
excludeURLPatterns"] 中的每个 urlPattern:-
如果 urlPattern 是一个
URLPattern, 则将 urlPattern 追加到 config 的 excludeURLPatterns。 -
否则,给定 urlPattern,将一个新的
URLPattern追加到 config 的 excludeURLPatterns。
-
-
-
令 completionSteps 为以下算法,其接受一个
longindex、一个 布尔值 success 和一个DOMStringsource:-
如果 success 为
false,则给定 controlledframe、result 和TypeError, 拒绝嵌入者 promise,并中止 这些步骤。 -
如果 isCss,则:
-
将 config 的 css[index] 设置为 source。
-
-
否则:
-
将 config 的 js[index] 设置为 source。
-
-
递减 config 的 pendingFetchCount。
-
如果 config 的 pendingFetchCount 大于 0,则返回。
-
给定 controlledframe 和 result,解决嵌入者 promise。
-
-
如果 injectionItems["
code"] 已定义,则:-
给定 0、
true和 injectionItems ["code"],运行 completionSteps。
-
-
否则:
-
如果 injectionItems["
files"] 为空,则 给定 controlledframe、result 和TypeError,拒绝嵌入者 promise, 并中止这些步骤。 -
对于 injectionItems ["
files"] 的每个 urlString:-
给定 controlledframe、 urlString、isCss、config 的 pendingFetchCount 和 completionSteps,运行获取注入项。
-
递增 config 的 pendingFetchCount。
-
-
-
如果 isTopLevel 为
false,且 config 的 allFrames 为false,则 返回false。 -
如果 url 匹配 about:blank,且 config 的 matchAboutBlank 为
false,则返回false。 -
令 urlString 为 序列化 url 的结果。
-
令 match 为
false。 -
对于 config 的 urlPatterns 的每个 pattern:
-
如果 urlString 匹配 URLPattern pattern,则将 match 设置为
true。
-
-
对于 config 的 excludeURLPatterns 的每个 pattern:
-
如果 urlString 匹配 URLPattern pattern,则将 match 设置为
false。
-
-
返回 match。
Document
document,以及一个 RunAt
currentPhase,运行以下步骤:
-
令 embeddedNavigable 为 document 的节点 navigable的 traversable navigable。
-
如果 embeddedNavigable 为 null,或其 controlledFrameEmbedderParent 为 null,则 返回。
-
令 controlledframe 为 embeddedNavigable 的 controlledFrameEmbedderParent。
-
令 url 为 document 的 URL。
-
如果 document 的节点 navigable的 parent 为 null,则令 isTopLevel 为
true,否则为false。 -
对于 controlledframe 的 内容脚本映射中的每个 config:
-
如果给定 config、url 和 isTopLevel,确定内容脚本配置是否适用于文档的结果等于
false,则继续。 -
如果 currentPhase 等于
document-start且 config 的 css 不是空, 则:-
对于 config 的 css 的每个 styleSource,给定 document 和 styleSource,运行将样式表注入到 文档中。
-
-
否则,如果 currentPhase 等于 config 的 runAt,则:
-
对于 config 的 js 的每个 scriptSource,给定 document、scriptSource 和一个 空 算法,运行将脚本注入到 文档中。
-
-
Document
document 和一个 DOMString
styleSource,运行以下步骤:
-
令 styleSheet 为一个新的 CSS 样式表对象。
-
给定 styleSheet 和 styleSource,同步替换 CSSStyleSheet 的规则。
-
在 document 的全局对象的 DOM 操作任务源上排队一个全局任务,以给定 document 和 styleSheet,添加 CSS 样式表。
以下算法在 Document 的 环境中执行脚本,但这不是期望的行为。目标是让该 算法在一个与 Document 环境隔离、具有不同全局对象但共享对 DOM 的访问权限的环境中执行脚本;但使用当前 HTML 规范基础设施 无法对此进行规范化。这个执行环境在 Blink 中称为 Isolated World,它使用该环境在扩展中执行 内容脚本。关于其执行模型的更多详细信息,请参见此 图示。Gecko 使用一种类似的方法,称为 Xray vision。该算法最终应描述一种可被规范化、并可由所有浏览器实现的 这种隔离的实现。
Document
document、
一个 DOMString
scriptSource,以及一个接受
完成记录的算法 completionSteps,运行以下步骤:
注:执行
scriptSource 时会故意不设置 document.currentScript。
-
令 script 为给定 scriptSource、document 的相关设置对象、document 的 URL,以及默认脚本获取选项,创建经典脚本的结果。
-
在 document 的全局对象的 DOM 操作任务源上排队一个全局任务,该任务将运行以下步骤:
-
令 completionRecord 为给定 script,运行经典脚本 的结果。
-
令 controlledframe 为 document 的节点 navigable的 traversable navigable的controlledFrameEmbedderParent。
-
在 controlledframe 的相关全局对象的 DOM 操作任务源上排队一个全局任务,该任务将以 completionRecord 运行 completionSteps。
-
addContentScripts(contentScriptList)
方法步骤为:
-
令 promises 为空列表。
-
对于 contentScriptList 中的每个 contentScript:
-
令 promise 为给定 contentScript,调用验证并解析 ContentScriptDetails的结果。
-
将 promise 追加到 promises。
-
-
返回给定 promises,获取一个等待所有 promise 的 promise 的结果。
removeContentScripts(scriptNameList)
方法步骤为:
-
令 result 为一个新的 promise。
-
令 controlledframe 为 this。
-
返回 result,并并行运行剩余步骤。
-
如果 scriptNameList 为 undefined,则:
-
否则,对于 scriptNameList 的每个 name:
-
给定 controlledframe 和 result,解决嵌入者 promise。
executeScript(details)
方法步骤为:
-
令 result 为一个新的 promise。
-
令 controlledframe 为 this。
-
返回 result,并并行运行剩余步骤。
-
如果 controlledframe 的嵌入的 navigable为 null,则给定 controlledframe、result 和一个
TypeError, 拒绝嵌入者 promise,并中止这些步骤。 -
如果 details["
code"] 和 details"[file"] 两者都已定义或两者都 未定义,则给定 controlledframe、 result 和一个TypeError,拒绝嵌入者 promise, 并中止这些步骤。 -
令 executionSteps 为以下算法,它接受一个
long和 一个DOMString或 布尔值 scriptString:-
如果 scriptString 不是
DOMString, 则给定 controlledframe、result 和一个TypeError, 拒绝嵌入者 promise, 并中止这些步骤。 -
令 document 为 controlledframe 的嵌入的 navigable的 活动文档。
-
给定 document、scriptString 以及以下接受完成记录 completionRecord 的算法,将脚本注入到文档中:
-
如果 completionRecord 是正常 完成,则:
-
给定 controlledframe、 result 和 completionRecord.
[[Value]],解决嵌入者 promise。
-
-
否则:
-
给定 controlledframe、 result 和 completionRecord.
[[Value]],拒绝嵌入者 promise。
-
-
-
-
如果 details["
code"] 已定义,则给定 0 和 details["code"],运行 executionSteps。 -
否则,给定 controlledframe、 details["
file"]、false、0 和 executionSteps,获取一个注入项。
insertCSS(details)
方法步骤为:
-
令 result 为一个新的 promise。
-
令 controlledframe 为 this。
-
返回 result,并并行运行剩余步骤。
-
如果 controlledframe 的嵌入的 navigable为 null,则 给定 controlledframe、result 和一个
TypeError, 拒绝嵌入者 promise, 并中止这些步骤。 -
如果 details["
code"] 和 details["file"] 两者都已定义或两者都 未定义,则给定 controlledframe、 result 和一个TypeError,拒绝嵌入者 promise, 并中止这些步骤。 -
令 executionSteps 为以下算法,它接受一个
long、 一个 布尔值 success 和一个DOMStringstyleString:-
如果 success 为
false,则给定 controlledframe、result 和一个TypeError, 拒绝 嵌入者 promise,并中止这些 步骤。 -
令 document 为 controlledframe 的嵌入的 navigable的 活动文档。
-
给定 document 和 styleString,将样式表注入到 文档中。
-
给定 controlledframe 和 result,解决嵌入者 promise。
-
-
如果 details["
code"] 已定义,则给定 0、true和 details["code"],运行 executionSteps。 -
否则,给定 controlledframe、 details["
file"]、false、0 和 executionSteps,获取一个注入项。
3.5. 配置方法
dictionary {ClearDataOptions long ; };since dictionary {ClearDataTypeSet boolean ;cache boolean ;cookies boolean ;fileSystems boolean ;indexedDB boolean ;localStorage boolean ;persistentCookies boolean ; };sessionCookies
long
since,运行
以下步骤:
注:如果可能,用户代理应仅 移除在 since 之后最后使用的数据,其中 since 表示自 纪元以来的毫秒时间戳。并非所有用户代理都会跟踪所有 浏览数据的写入或访问时间。实现应尽其所能尊重 since, 但该 API 不保证其可用性。
clearData(options, types)
方法步骤为:
-
令 resultPromise 为一个新的 promise。
-
令 controlledframe 为 this。
-
返回 resultPromise,并并行运行剩余步骤。
-
令 clearSince 为 0。
-
如果 options["
since"] 已定义,则将 clearSince 设置为 options|["since"]。 -
令 partition 为 controlledframe 的
partition。 -
对于用户代理的 存储棚中的每个 storageKey → shelf:
-
如果 storageKey 的嵌入源不等于 embeddingOrigin,或 storageKey 的分区不 等于 partition,则继续。
-
令 bucket 为 shelf["
default"]。 -
如果 types["
fileSystems"] 为true:-
给定 bucket、"
fileSystem" 和 clearSince,清空存储瓶。
-
-
如果 types["
indexedDB"] 为true:-
给定 bucket、"
indexedDB" 和 clearSince,清空存储瓶。
-
-
如果 types["
localStorage"] 为true:-
给定 bucket、"
localStorage" 和 clearSince,清空存储瓶。
-
-
-
如果 types["
cookies"]、 types["persistentCookies"], 或 types["sessionCookies"] 为true,则:[COOKIES] 规范不支持通过类似存储键的机制 对 cookie 进行分区。以下步骤 会清除所有 cookie,但其意图是仅删除 由此 Controlled Frame 当前
partition中的 Controlled Frame 内容所 创建的 cookie。 -
如果 types["
cache"] 为true,则: -
给定 controlledframe 和 resultPromise,解决嵌入者 promise。
每个嵌入的 navigable都持有一个
muted 布尔值,默认值为
false。当 muted 为 true 时,用户代理必须
将源自嵌入的
navigable内的所有音频流静音。
muted
状态不应暴露给
嵌入的 navigable内的内容;当 muted 为
true 时,不应以任何脚本可见的方式更改音量状态,但
底层音频流不应被用户听到。
getAudioState()
方法步骤为:
-
令 resultPromise 为一个新的 promise。
-
令 controlledframe 为 this。
-
返回 resultPromise,并并行运行剩余步骤。
-
如果 controlledframe 的嵌入的 navigable为 null,则给定 controlledframe、resultPromise 和一个
TypeError, 拒绝嵌入者 promise,并中止这些步骤。 -
如果 controlledframe 的嵌入的 navigable内的任何内容(包括嵌套框架中的内容)当前正在 播放 音频,则令 playingAudio 为
true,否则为false。 -
给定 controlledframe、resultPromise 和 playingAudio,解决嵌入者 promise。
isAudioMuted()
方法步骤为:
-
令 resultPromise 为一个新的 promise。
-
令 controlledframe 为 this。
-
返回 resultPromise,并并行运行剩余步骤。
-
如果 controlledframe 的嵌入的 navigable为 null,则给定 controlledframe、resultPromise 和一个
TypeError, 拒绝嵌入者 promise,并中止这些步骤。 -
给定 controlledframe、resultPromise 以及 controlledframe 的嵌入的 navigable的 muted 标志,解决嵌入者 promise。
setAudioMuted(mute)
方法步骤为:
-
如果 this 的嵌入的 navigable为 null,则抛出一个
TypeError。 -
将 this 的嵌入的 navigable的 muted 标志设置为 mute。
3.5.1. 缩放
enum {ZoomMode ,"per-origin" ,"per-view" };"disabled"
用户代理持有一个 Controlled Frame 缩放映射,它是一个映射,其键为元组,值为浮点数。
每个 HTMLControlledFrameElement
都持有一个 ZoomMode
zoomMode,其默认值为 per-origin。
每个 HTMLControlledFrameElement
都持有一个浮点数 currentZoom,初始设置为
1.0f。
给定 浮点数 zoomLevel,如何将缩放级别应用到文档, 由实现具体决定。
本节是非规范性的。
有效的 ZoomMode
值的行为如下:
per-origin-
缩放更改会在嵌入文档的源中持久化,也就是说,位于同一
partition中并导航到同一源的所有其他HTMLControlledFrameElement也会被缩放。 per-view-
缩放更改仅在此
HTMLControlledFrameElement中生效, 而其他HTMLControlledFrameElement中的缩放更改不会影响此HTMLControlledFrameElement的缩放。 disabled-
禁用
HTMLControlledFrameElement中的所有缩放。 内容会还原为默认缩放级别,并且所有尝试的缩放更改都会被 忽略。
要获取
按源缩放级别,给定 HTMLControlledFrameElement
e,运行以下步骤:
-
令 result 为初始设置为 1.0f 的浮点数。
-
令 key 为给定与 e 的嵌入的 navigable的活动文档的当前设置对象相关联的环境,获取 Controlled Frame 存储键的结果。
-
如果 Controlled Frame 缩放映射[key] 存在,则将 result 设置为给定键 key,从 Controlled Frame 缩放映射获取 值的结果。
-
返回 result。
要设置
按源缩放级别,给定 HTMLControlledFrameElement
e 和一个浮点数 zoomLevel,运行以下步骤:
-
令 key 为给定与 e 的嵌入的 navigable的活动文档的当前设置对象相关联的环境,获取 Controlled Frame 存储键的结果。
-
给定键 key 和值 zoomLevel,设置 值到 Controlled Frame 缩放映射。
要确定给定 HTMLControlledFrameElement
e 时,当前文档是否具有按源缩放
级别,运行以下步骤:
-
令 key 为给定与 e 的嵌入的 navigable的活动文档的当前设置对象相关联的环境,获取 Controlled Frame 存储键的结果。
-
如果 Controlled Frame 缩放映射[key] 存在,返回
true。 -
返回
false。
getZoomMode() 方法
步骤为:
-
令 p 为一个新的 promise。
-
令 controlledframe 为 this。
-
返回 p,并并行运行剩余步骤。
-
给定 controlledframe、p 和 controlledframe 的zoomMode,解决嵌入者 promise。
setZoomMode(zoomMode)
方法步骤为:
-
令 p 为一个新的 promise。
-
令 controlledframe 为 this。
-
返回 p,并并行运行剩余步骤。
-
令 currentZoomMode 为给定 controlledframe,
getZoomMode的结果。 -
如果 currentZoomMode 等于 zoomMode,则给定 controlledframe 和 p,解决嵌入者 promise。
-
将 controlledframe 的 zoomMode 设置为 zoomMode。
-
如果 zoomMode 为
per-origin:-
如果给定 controlledframe,当前文档具有 按源缩放级别为
true:-
令 oldZoomFactor 为 controlledframe 的 currentZoom。
-
将 controlledframe 的 currentZoom 设置为给定 controlledframe,获取按源缩放级别 的结果。
-
如果 oldZoomFactor 不等于 controlledframe 的 currentZoom:
-
给定 controlledframe 的 currentZoom,将缩放级别应用到 controlledframe 的嵌入文档。
-
使用 controlledframe、oldZoomFactor 和 controlledframe 的 currentZoom,触发 "zoomchange" 事件。
-
-
-
-
如果 zoomMode 为
disabled:-
令 oldZoomFactor 为 controlledframe 的 currentZoom。
-
将 controlledframe 的 currentZoom 设置为 1.0f。
-
如果 oldZoomFactor 不等于 controlledframe 的 currentZoom:
-
给定 controlledframe 的 currentZoom,将缩放级别应用到 controlledframe 的嵌入文档。
-
使用 controlledframe、oldZoomFactor 和 controlledframe 的 currentZoom,触发 "zoomchange" 事件。
-
-
-
给定 controlledframe 和 p,解决嵌入者 promise。
getZoom() 方法步骤
为:
-
令 p 为一个新的 promise。
-
令 controlledframe 为 this。
-
返回 p,并并行运行剩余步骤。
-
令 embeddedNavigable 为 controlledframe 的嵌入的 navigable。
-
如果 embeddedNavigable 为 null,则给定 controlledframe、p 和一个
TypeError, 拒绝嵌入者 promise,并中止这些步骤。 -
给定 controlledframe、p 和 controlledframe 的 currentZoom,解决嵌入者 promise。
setZoom(zoomFactor) 方法
步骤为:
-
令 p 为一个新的 promise。
-
令 controlledframe 为 this。
-
返回 p,并并行运行剩余步骤。
-
令 embeddedNavigable 为 controlledframe 的嵌入的 navigable。
-
如果 embeddedNavigable 为 null,则给定 controlledframe、p 和一个
TypeError, 拒绝嵌入者 promise,并中止这些步骤。 -
如果 controlledframe 的 ZoomMode 为
disabled:-
给定 controlledframe、p 和一个
TypeError, 拒绝嵌入者 promise, 并中止这些步骤。
-
-
如果 controlledframe 的 ZoomMode 为
per-origin:-
令 oldZoomFactor 为 controlledframe 的 currentZoom。
-
给定 controlledframe 和 zoomFactor,设置按源缩放级别。
-
对于用户代理的 浏览上下文组集合中的每个 浏览上下文组 group:
-
对于 group 中的每个 顶级浏览上下文 browsingContext:
-
令 embeddedDocument 为 browsingContext 的 活动文档。
-
令 embedder 为 embeddedDocument 的节点 navigable的 controlledFrameEmbedderParent。
-
如果 embedder 为 null,则继续。
-
如果以下所有条件均为
true,则令 match 为true:-
embedder 的 ZoomMode 为
per-origin -
embeddedDocument 的源等于 controlledframe 的嵌入的 navigable的 活动文档的源
-
embedder 的 currentZoom 不等于 zoomFactor
-
-
如果 match 为
true,则:-
将 embedder 的 currentZoom 设置为 zoomFactor。
-
给定 zoomFactor,将缩放级别应用到 embeddedDocument。
-
使用 embedder、 oldZoomFactor 和 zoomFactor,触发 "zoomchange" 事件。
-
-
-
-
-
如果 controlledframe 的 ZoomMode 为
per-view:-
令 oldZoomFactor 为 controlledframe 的 currentZoom。
-
将 controlledframe 的 currentZoom 设置为 zoomFactor。
-
如果 oldZoomFactor 不等于 controlledframe 的 currentZoom:
-
给定 controlledframe 的 currentZoom,将缩放级别应用到 controlledframe 的嵌入文档。
-
使用 controlledframe、 oldZoomFactor、controlledframe 的currentZoom,触发 "zoomchange" 事件。
-
-
-
给定 controlledframe 和 p,解决嵌入者 promise。
3.6. 捕获方法
// One of |code| or |file| must be specified but not both.dictionary {ImageDetails DOMString ;format DOMString ; };quality
captureVisibleRegion(options)
方法步骤为:
-
令 resultPromise 为一个新的 promise。
-
令 controlledframe 为 this。
-
返回 resultPromise,并并行运行剩余步骤。
-
如果 controlledframe 的嵌入的 navigable为 null,则给定 controlledframe、resultPromise 和一个
TypeError, 拒绝嵌入者 promise,并中止这些步骤。 -
令 optionsFormat 默认为 "JPEG"。
-
令 optionsQuality 默认为 100。
-
如果 options 有字段 "format":
-
令 optionsFormat 为 options["format"]。
-
-
如果 optionsFormat 是无法识别的格式,则给定 controlledframe、 resultPromise 和一个
TypeError, 拒绝嵌入者 promise,并中止这些步骤。 -
如果 options 有字段 "quality":
-
令 optionsQuality 为 options["quality"]。
-
-
如果 optionsQuality 不是整数,或不在 0 到 100(含)之间, 则给定 controlledframe、 resultPromise 和一个
TypeError, 拒绝嵌入者 promise,并中止这些步骤。 -
令 imageData 为一张显示嵌入内容可见区域的图像,该图像以 optionsFormat 编码,质量为 optionsQuality。
注:受支持图像格式的集合由实现定义, 但建议至少支持 "JPEG" 和 "PNG"。
-
给定 controlledframe、resultPromise 和一个包含 imageData 的
data:URL,解决嵌入者 promise。
print()
方法步骤为:
-
如果 this 的嵌入的 navigable为 null,则抛出一个
TypeError。 -
为嵌入内容启动浏览器打印页面功能。
3.7. 事件
HTMLControlledFrameElement
实现 EventTarget
并支持以下事件处理程序(以及它们对应的事件处理程序事件类型)。
| 事件处理程序 | 事件处理程序事件类型 |
|---|---|
onconsolemessage
| consolemessage |
oncontentload
| contentload |
ondialog
| dialog |
onloadabort
| loadabort |
onloadcommit
| loadcommit |
onloadstart
| loadstart |
onloadstop
| loadstop |
onnewwindow
| newwindow |
onpermissionrequest
| permissionrequest |
onsizechanged
| sizechanged |
onzoomchange
| zoomchange |
交互事件:
UI 更改事件:
-
onsizechanged- 当嵌入的 Web 内容通过自动调整大小被调整尺寸时触发。仅在启用自动调整大小时触发。
导航事件:
-
oncontentload- 当与嵌入的 navigable关联的Window触发 load 事件时触发。 -
onloadabort- 当导航在完成前退出时触发。 -
onloadcommit- 当导航已完成时触发。 -
onloadstart- 当导航(包括重新加载和遍历)开始时,为嵌入文档的每个 navigable 触发, 但不包括同一文档导航。 -
onloadstop- 当所有待处理导航结束(提交或中止)时触发。如果之后开始新的导航, loadstop 可能会再次触发。
每个 HTMLControlledFrameElement
都有一个加载计数器,
它是一个初始值为零的数字。
每次 onloadstart
事件触发时,加载计数器
增加 1。
每次 onloadabort
事件触发时,加载计数器
减少 1。
每次 onloadcommit
事件触发时,加载计数器
减少 1。
当加载计数器从非零数字变为 0 时,触发 "loadstop" 事件。
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
要触发 ConsoleMessageEvent
e,给定
controlledframe
元素 target、一个 long logLevel 和一个 DOMString message,
运行以下步骤:
-
令 consoleMessage 为一个新的
ConsoleMessage对象。 -
设置 consoleMessage 的以下字段:
-
将 e 的
consoleMessage设置为 consoleMessage。
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
每个 DialogController
都具有:
-
一个布尔值 accept,初始设置为
false。 -
一个 DOMString response,初始为空字符串。
cancel() 方法步骤为:
-
将 accept 设置为
false。
要触发 DialogEvent
e,给定
controlledframe
元素 target、简单对话框类型 dialogType,以及
消息 message,运行以下步骤:
-
断言 e["
dialogMessage"]["dialog"]["accept"] 等于false。 -
令 dialogMessage 为一个新的
DialogMessage对象。 -
令 dialog 为一个新的
DialogController对象。 -
设置 dialogMessage 的以下字段:
messageType-
dialogType。
messageText-
message。
dialog-
dialog。
-
将 e 的
dialogMessage设置为 dialogMessage。 -
令 complete 为
false。 -
在 target 的相关全局对象的DOM 操作任务源上排队一个全局任务,以运行以下 步骤:
-
在 target 上分派 e。
-
将 complete 设置为
true。
-
-
同步等待 complete 为
true。注: 此处阻塞是有意为之,因为 由 "dialog" 事件表示的 alert、confirm 和 prompt 对话框会阻塞主线程,并且我们在这里调用的事件 处理程序会影响返回值。
-
返回 e["
dialogMessage"]["dialog"]["accept"] 以及 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
每个 NewWindowController
都有一个对
目标 navigable 的引用,该引用最初为 null。
attach(newControlledFrame)
方法步骤为:
-
将 newControlledFrame 的嵌入的 navigable设置为 this 的 目标 navigable。
discard() 方法步骤为:
-
如果 this 的目标 navigable不是 null,则给定 this 的 目标 navigable,关闭一个顶级 traversable。
要触发 NewWindowEvent
e,
给定
controlledframe
元素 controlledFrame、USVString
url、
DOMString
target、navigable targetNavigable 和
WindowOpenDisposition
windowOpenDisposition,运行以下步骤:
-
令 controller 为一个新的
NewWindowController对象。 -
将 controller 的目标 navigable设置为 targetNavigable。
-
设置 newWindow 的以下字段:
window-
controller
targetUrl-
url
name-
target。
windowOpenDisposition-
windowOpenDisposition
-
将 e 的
newWindow设置为 newWindow。 -
在 controlledFrame 的相关全局对象的 DOM 操作任务源上排队一个全局任务,以在 controlledFrame 上分派 e。
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
每个 PermissionRequestControllerBase
都有一个布尔值 allow,其初始值为
false。
allow() 方法步骤为:
-
将 allow 设置为
true。
cancel() 方法步骤为:
-
将 allow 设置为
false。
要触发
PermissionRequestEvent
e,给定一个文档 embeddedDocument、
controlledframe
元素 target、DOMString type、USVString url、一个
可选字典 options,以及一个接受
布尔值的算法
completionSteps,运行以下步骤:
-
令 permissionRequest 为一个新的
PermissionRequest对象。 -
如果 type 为 "media":
-
令 requestController 为一个具有以下属性的新的
MediaPermissionRequestController:url-
url
-
-
如果 type 为 "geolocation":
-
令 requestController 为一个具有以下属性的新的
GeolocationPermissionRequestController:url-
url
-
-
如果 type 为 "pointerLock":
-
令 requestController 为一个具有以下属性的新的
PointerLockPermissionRequestController:lastUnlockedBySelf-
options["lastUnlockedBySelf"]
userGesture-
options["userGesture"]
url-
url
-
-
如果 type 为 "download":
-
令 requestController 为一个具有以下属性的新的
DownloadPermissionRequestController:requestMethod-
options["requestMethod"]
url-
url
-
-
如果 type 为 "filesystem":
-
令 requestController 为一个具有以下属性的新的
FileSystemPermissionRequestController:url-
url
-
-
如果 type 为 "fullscreen":
-
令 requestController 为一个具有以下属性的新的
FullscreenPermissionRequestController:origin-
url 的源
-
-
如果 type 为 "hid":
-
令 requestController 为一个具有以下属性的新的
HidPermissionRequestController:url-
url
-
-
设置 permissionRequest 的以下字段:
request-
requestController
permission-
type。
-
将 e 的
permissionRequest设置为 permissionRequest。 -
在 target 的相关全局对象的 DOM 操作任务源上排队一个全局任务,以运行以下 步骤:
-
在 target 上分派 e。
-
在 embeddedDocument 的相关全局对象的 DOM 操作任务源上排队一个全局任务,该任务使用 e["
permissionRequest"]["permission"]["allow"] 运行 completionSteps。
-
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
要触发一个 SizeChangedEvent
e,给定
controlledframe
元素 target、4 个非负数 oldWidth、oldHeight、
newWidth、newHeight:
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
要触发 ZoomChangeEvent
e,给定
controlledframe
元素 target、2 个 浮点数
oldZoomFactor、newZoomFactor:
-
令 zoomChange 为一个新的
ZoomChange对象。 -
设置 zoomChange 的以下字段:
oldZoomFactor-
oldZoomFactor。
newZoomFactor-
newZoomFactor。
-
将 e 的
zoomChange设置为 zoomChange。
3.7.7. contentload
[Exposed =Window ,IsolatedContext ]interface :ContentLoadEvent Event {(constructor DOMString ,type optional EventInit = {}); };eventInitDict
要触发 ContentLoadEvent
e,给定
controlledframe
元素 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
要触发一个 LoadAbortEvent
e,给定
controlledframe
元素 target、
一个 USVString url、一个布尔值 isTopLevel、一个 long code,
以及一个 DOMString
reason,运行以下步骤:
-
令 info 为一个具有以下属性的新的
LoadAbortInfo:url-
url
isTopLevel-
isTopLevel
code-
code
reason-
reason
-
将 e 的
loadAbortInfo设置为 info。
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
要触发一个 LoadCommitEvent
e,给定
controlledframe
元素 target、
一个 USVString url 和一个布尔值 isTopLevel,运行以下步骤:
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
要触发一个 LoadStartEvent
e,给定
controlledframe
元素 target、
一个 USVString url 和一个布尔值 isTopLevel,运行以下步骤:
3.7.11. loadstop
[Exposed =Window ,IsolatedContext ]interface :LoadStopEvent Event {(constructor DOMString ,type optional LoadStopEventInit = {}); };eventInitDict dictionary :LoadStopEventInit EventInit { };
要触发 LoadStopEvent
e
,给定
controlledframe
元素 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
要触发 LoadRedirectEvent
e,给定
controlledframe
元素 target、一个 URL oldUrl、一个
URL newUrl,以及一个布尔值 isTopLevel,运行
以下步骤:
3.7.13. 猴子补丁
3.7.13.1. [HTML]
对于 alert:
-
将 message 设置为可选地截断 message 的结果。
- 令 controlledFrameEmbedderParent 为 window 的 navigable 的controlledFrameEmbedderParent。 。
-
如果 controlledFrameEmbedderParent 是一个
HTMLControlledFrameElement, 则使用 controlledFrameEmbedderParent、"alert" 和 message 触发 "dialog" 事件,并返回。
对于 confirm:
-
将 message 设置为可选地截断 message 的结果。
- 令 controlledFrameEmbedderParent 为 window 的 navigable 的controlledFrameEmbedderParent。 。
-
如果 controlledFrameEmbedderParent 是一个
HTMLControlledFrameElement, 则返回使用 controlledFrameEmbedderParent、"confirm" 和 message 触发 "dialog" 事件的结果。
对于 prompt:
-
将 default 设置为可选地截断 default 的结果。
- 令 controlledFrameEmbedderParent 为 window 的navigable 的controlledFrameEmbedderParent。 。
-
如果 controlledFrameEmbedderParent 是一个
HTMLControlledFrameElement, 则:- 令 accept 和 response 为使用 controlledFrameEmbedderParent、"prompt" 和 message 触发 "dialog" 事件的结果。
-
如果 accept 等于
false,返回 null。 - 返回 response。
-
令 windowOpenDisposition 为 "
ignore"。 - 令 controlledFrameEmbedderParent 为 sourceDocument 的节点 navigable 的controlledFrameEmbedderParent。
...
-
如果 targetNavigable 为 null:
-
如果 controlledFrameEmbedderParent 不是 null:
- 使用 controlledFrameEmbedderParent、url、 target、targetNavigable 和 windowOpenDisposition,触发 "newwindow" 事件。
- 返回 null。
-
如果 controlledFrameEmbedderParent 不是 null:
-
如果 windowType 为 "new and unrestricted" 或 "new with no opener", 则:
-
将 windowOpenDisposition 设置为以下之一:
"
new_background_tab"、 "new_foreground_tab", 或 "new_window"。
注:该值取决于用户代理的行为支持 和用户设置。
-
将 targetNavigable 的活动浏览上下文的 is popup 设置为给定 tokenizedFeatures,检查是否请求了弹出窗口的结果。
-
如果 targetNavigable 的活动浏览上下文的 is popup
为
true,则将 windowOpenDisposition 设置为 "new_popup"。
...
-
将 windowOpenDisposition 设置为以下之一:
"
-
否则:
-
将 windowOpenDisposition 设置为
"
current_tab"。
...
-
将 windowOpenDisposition 设置为
"
注:步骤 15 和 16 也会导航 targetNavigable;在导航期间,
windowOpenDisposition 也可能会被更新。例如,如果导航被
阻止,windowOpenDisposition 可能会被设置为
"ignore"。
如果导航响应导致
下载,则 windowOpenDisposition 可能会被设置为
"save_to_disk"。
-
如果 controlledFrameEmbedderParent 不是 null:
- 使用 controlledFrameEmbedderParent、url、 target、targetNavigable 和 windowOpenDisposition,触发 "newwindow" 事件。
对于完全完成加载:
-
否则,如果 container 非 null,则给定 container,在 DOM 操作任务源上排队一个元素任务, 以在 container 处触发名为 load 的事件。
- 令 controlledFrameEmbedderParent 为 document 的节点 navigable 的controlledFrameEmbedderParent。
-
如果 controlledFrameEmbedderParent 是
HTMLControlledFrameElement, 则使用 controlledFrameEmbedderParent 触发 "contentload" 事件。
用于 loadstart、loadabort 和 loadcommit 的猴子补丁如下所示:
-
loadstart -> 在导航入口点:普通导航、重新加载、遍历。
-
loadcommit -> 在通用导航完成点。
-
loadabort -> 在 loadstart 和 loadcommit 之间算法的每个提前退出点。
对于这些事件中的每一个,检查 navigable 的顶级 traversable是否具有 HTMLControlledFrameElement
类型的 controlledFrameEmbedderParent,
如果是,则使用输入参数触发对应事件。
3.7.13.2. [FETCH]
对于 HTTP fetch(loadredirect):
-
如果 internalResponse 的状态是重定向状态:
-
如果 request 的 window window 是一个
环境设置对象,其全局对象是
Window对象:- 令 currentNavigable 为 window 的关联 navigable。
- 令 controlledFrameEmbedderParent 为 currentNavigable 的 顶级 traversable 的controlledFrameEmbedderParent。
-
如果 controlledFrameEmbedderParent 是一个
HTMLControlledFrameElement:1. 令 oldUrl 为 request 的关联 URL。
1. 令 newUrl 为 response 的位置 URL。
1. 令 isTopLevel 为
false;如果 currentNavigable 具有 null parent,则将 isTopLevel 设置为true。1. 使用 controlledFrameEmbedderParent、oldUrl、newUrl 和 isTopLevel,触发 "loadredirect" 事件。
-
如果 request 的 window window 是一个
环境设置对象,其全局对象是
3.7.13.3. [Permissions]
定义新算法:
要确定一个 Document document 是否 被嵌入者允许使用某项 权限,给定 DOMString permission、一个可选字典 options,以及一个接受 布尔值的算法 completionSteps,运行以下步骤:
-
令 controlledFrameEmbedderParent 为 document 的节点 navigable 的controlledFrameEmbedderParent。
-
如果 controlledFrameEmbedderParent 不是
HTMLControlledFrameElement, 返回true。 -
使用 document、 controlledFrameEmbedderParent、permission、document 的 URL、options 和 completionSteps,触发 "permissionrequest" 事件。
对于请求位置(geolocation):
-
如果 document 不被允许使用 "geolocation" 特性:
-
如果传入了 watchId,则从 watchIDs 中移除 watchId。
-
使用 errorCallback 和 PERMISSION_DENIED 回调错误。
-
终止此算法。
-
-
令 blockedByEmbedder 为
false。 - 检查 document 是否被嵌入者允许使用 "geolocation" 特性,给定一个算法,该算法将其 布尔值参数赋给 blockedByEmbedder 并继续执行这些步骤的剩余部分。
-
如果 blockedByEmbedder 为
true,则:- 如果传入了 watchId,则从 watchIDs 中移除 watchId。
- 使用 errorCallback 和 PERMISSION_DENIED 回调错误。
- 终止此算法。
- 令 controlledFrameEmbedderParent 为 document 的节点 navigable 的controlledFrameEmbedderParent。
-
如果 controlledFrameEmbedderParent 是
HTMLControlledFrameElement:-
令 nodeDocument 为 controlledFrameEmbedderParent 的节点文档。
-
如果 nodeDocument 为 null:
- 如果传入了 watchId,则从 watchIDs 中移除 watchId。
- 使用 errorCallback 和 PERMISSION_DENIED 回调错误。
- 终止此算法。
- 令 embedderNavigator 为 nodeDocument 的全局对象的 关联 Navigator。
-
令 embedderGeolocation 为 embedderNavigator 的
geolocation。 - 返回使用 embedderGeolocation、successCallback、errorCallback、 options 和 whatchId 请求位置的结果。
-
注:其他权限也会以类似于 geolocation 的方式打上猴子补丁。 但为了简洁起见,本文档省略了 细节。
3.7.13.4. [Console]
对于 Logger:
-
否则,执行 Printer(logLevel, Formatter(args))。
- 使用 logLevel、Formatter(args),触发 "consolemessage" 事件。
注:Console 默认不与
document 关联,因此我们无法跟踪关联的 HTMLControlledFrameElement。
3.8. 与其他规范的集成
本规范将对一些规范作出修改,以满足 Controlled Frame 的需求。
3.8.1. 猴子补丁
3.8.1.1. [HTML]
每个 navigable 都具有:
-
一个 frameId 整数,初始值为 0。
-
一个 next frameId 整数,初始值为 1。
-
一个 controlledFrameEmbedderParent,即一个
HTMLControlledFrameElement或 null。
给定一个 navigable navigable 和一个可选的 navigable-or-null parent(默认为 null),初始化 navigable 算法 被猴子补丁如下:
-
将 navigable 的 parent 设置为 parent。
-
如果 parent 不是 null(navigable 不是
顶级 traversable),则:
- 令 topLevelTraversable 为 navigable 作为其后代的顶级 traversable。
- 将 navigable 的 frameId 设置为 topLevelTraversable 的 next frameId。
- 递增 topLevelTraversable 的 next frameId。
用于 Document
document 到
readinessValue 的更新当前文档就绪状态算法被猴子补丁如下:
-
令 runAt 为将以下映射应用于
readinessValue 的结果:
- "
loading" - "
interactive" - "
complete"
- "
- 给定 document 和 runAt,将内容脚本注入到文档中。
-
在 document 处触发一个事件,其名称为
readystatechange。
3.8.1.2. [FETCH]
确定网络分区键算法被猴子扩展为 要求对源自 Controlled Frame 的嵌入的 navigable的网络请求 进行双键化。
-
令 topLevelSite 为给定 topLevelOrigin,获取站点的结果。
-
令 secondKey 为 null
或一个实现定义的值。 - 令 controlledFrameEmbedderParent 为给定 environment,获取环境的 controlledFrameEmbedderParent的结果。
-
如果 controlledFrameEmbedderParent 不是 null,则将 secondKey 设置为一个元组,该元组由
controlledFrameEmbedderParent 的
相关设置对象的顶级源,以及
controlledFrameEmbedderParent 的
partition组成。 -
返回 (topLevelSite, secondKey)。
3.8.1.3. [STORAGE]
存储键被重新定义如下:
存储键是一个元组,
由
嵌入源(一个源或 null)、一个
分区(一个 DOMString
或 null),以及一个
源(一个源)组成。
注:将来一旦存储分区被完整规范化, 该定义将需要扩展为除源之外,还包括嵌入内容的 顶级源。
注:Controlled Frame 数据是用拥有 Controlled Frame 元素的文档的源进行三重键化,而不是用拥有它的顶级文档的源。
为非存储目的获取存储键算法被扩展为
要求对属于
controlledframe
的
嵌入的 navigable 的所有存储进行双键化。
-
如果 environment 是一个环境设置对象,则令 origin 为 environment 的源;否则为 environment 的创建 URL的源。
-
返回一个由 origin 组成的元组。 - 令 topLevelOrigin 和 partition 为 null。
- 令 controlledFrameEmbedderParent 为给定 environment,获取环境的 controlledFrameEmbedderParent的结果。
- 如果 controlledFrameEmbedderParent 不是 null,则:
- 返回一个由 topLevelOrigin、partition 和 origin 组成的元组。
-
如果 environment 是一个环境设置对象,其 全局对象是一个
Window对象,则:此算法 不适用于 Shared 或 Service Workers,因为 controlledFrameEmbedderParent 仅 定义在 navigable 上,并且 并不总是可以从非
Window环境到达一个 navigable。-
令 top 为 navigable 的顶级 traversable。
-
如果 top 的 controlledFrameEmbedderParent 不是 null,则返回 top 的 controlledFrameEmbedderParent。
-
返回 null。
4. Web Request API
enum {ResourceType ,"main-frame" ,"sub-frame" ,"stylesheet" ,"script" ,"image" ,"font" ,"object" ,"xmlhttprequest" ,"ping" ,"csp-report" ,"media" ,"websocket" , };"other" enum {RequestedHeaders ,"none" ,"cors" , };"all" enum {ConnectionState ,"broken" ,"insecure" };"secure" dictionary {Fingerprint required DOMString ; };sha256 dictionary {CertificateInfo required Fingerprint ;fingerprint Uint8Array ; };rawDER dictionary {SecurityInfo required sequence <CertificateInfo >;certificates required ConnectionState ; };state dictionary {WebRequestInterceptorOptions required sequence <(URLPattern or URLPatternInput )>;urlPatterns sequence <ResourceType >= [];resourceTypes boolean =blocking false ;boolean =includeRequestBody false ;RequestedHeaders = "none";includeHeaders boolean =securityInfo false ;boolean =securityInfoRawDer false ; }; [Exposed =Window ,IsolatedContext ]interface {WebRequest WebRequestInterceptor createWebRequestInterceptor (WebRequestInterceptorOptions ); }; [options Exposed =Window ,IsolatedContext ]interface :WebRequestInterceptor EventTarget {attribute EventHandler onauthrequired ;attribute EventHandler onbeforeredirect ;attribute EventHandler onbeforerequest ;attribute EventHandler onbeforesendheaders ;attribute EventHandler oncompleted ;attribute EventHandler onerroroccurred ;attribute EventHandler onheadersreceived ;attribute EventHandler onsendheaders ;attribute EventHandler onresponsestarted ; };enum {DocumentLifecycle ,"prerender" ,"active" ,"cached" , };"pending-deletion" enum {FrameType ,"outermost-frame" ,"fenced-frame" , }; ["sub-frame" Exposed =Window ,IsolatedContext ]interface {UploadData readonly attribute ArrayBuffer ?bytes ;readonly attribute DOMString ?file ; }; [Exposed =Window ,IsolatedContext ]interface {RequestBody readonly attribute DOMString ?error ;readonly attribute any formData ;readonly attribute FrozenArray <UploadData >?raw ; }; [Exposed =Window ,IsolatedContext ]interface {WebRequestRequest readonly attribute DOMString method ;readonly attribute DOMString id ;readonly attribute ResourceType type ;readonly attribute USVString url ;readonly attribute USVString ?initiator ;readonly attribute Headers ?headers ;readonly attribute RequestBody ?body ; }; [Exposed =Window ,IsolatedContext ]interface {AuthChallenger readonly attribute DOMString host ;readonly attribute long port ; }; [Exposed =Window ,IsolatedContext ]interface {WebRequestAuthDetails readonly attribute AuthChallenger challenger ;readonly attribute boolean isProxy ;readonly attribute DOMString scheme ;readonly attribute DOMString ?realm ; }; [Exposed =Window ,IsolatedContext ]interface {WebRequestResponse readonly attribute long statusCode ;readonly attribute DOMString statusLine ;readonly attribute boolean fromCache ;readonly attribute Headers ?headers ;readonly attribute DOMString ?ip ;readonly attribute USVString ?redirectURL ;readonly attribute WebRequestAuthDetails ?auth ; }; [Exposed =Window ,IsolatedContext ]interface :WebRequestEvent Event {readonly attribute WebRequestRequest request ;readonly attribute long frameId ;readonly attribute FrameType ?frameType ;readonly attribute DOMString ?documentId ;readonly attribute DocumentLifecycle ?documentLifecycle ;readonly attribute DOMString ?parentDocumentId ;readonly attribute long ?parentFrameId ; };dictionary {WebRequestAuthCredentials required DOMString ;username required DOMString ; };password dictionary {WebRequestAuthOptions AbortSignal ; }; [signal Exposed =Window ,IsolatedContext ]interface :WebRequestAuthRequiredEvent WebRequestEvent {readonly attribute WebRequestResponse response ;undefined setCredentials (Promise <WebRequestAuthCredentials >,credentials optional WebRequestAuthOptions = {}); }; [options Exposed =Window ,IsolatedContext ]interface :WebRequestBeforeRedirectEvent WebRequestEvent {readonly attribute WebRequestResponse response ; }; [Exposed =Window ,IsolatedContext ]interface :WebRequestBeforeRequestEvent WebRequestEvent {undefined redirect (USVString ); }; [redirectURL Exposed =Window ,IsolatedContext ]interface :WebRequestBeforeSendHeadersEvent WebRequestEvent {undefined setRequestHeaders ((Headers or HeadersInit )); }; [requestHeaders Exposed =Window ,IsolatedContext ]interface :WebRequestCompletedEvent WebRequestEvent {readonly attribute WebRequestResponse response ; }; [Exposed =Window ,IsolatedContext ]interface :WebRequestErrorOccurredEvent WebRequestEvent {readonly attribute DOMString error ; }; [Exposed =Window ,IsolatedContext ]interface :WebRequestHeadersReceivedEvent WebRequestEvent {readonly attribute WebRequestResponse response ;readonly attribute SecurityInfo ?securityInfo ;undefined redirect (USVString );redirectURL undefined setResponseHeaders ((Headers or HeadersInit )); }; [responseHeaders Exposed =Window ,IsolatedContext ]interface :WebRequestResponseStartedEvent WebRequestEvent {readonly attribute WebRequestResponse response ; }; [Exposed =Window ,IsolatedContext ]interface :WebRequestSendHeadersEvent WebRequestEvent {};
每个 WebRequest
都有一个关联的:
-
拦截器,它是一个
WebRequestInterceptor的列表, 初始为 «»。
注:拦截器将由
controlledframe
元素事件循环上的任务写入,但会在 fetch 期间并行读取。
在分派 WebRequest 事件之前,会创建
适用的 WebRequestInterceptors 的快照。
在处理事件时注册到 WebRequestInterceptor
上的事件监听器不会针对该事件触发。
每个 WebRequestInterceptor
都有一个关联的:
-
urlPatterns,它是一个
URLPattern的列表。 -
resourceTypes,它是一个
ResourceType的列表。 -
blocking,它是一个布尔值。
-
includeRequestBody,它是一个布尔值。
-
includeHeaders,它是一个
RequestedHeaders。 -
securityInfo,它是一个布尔值。
-
securityInfoRawDer,它是一个布尔值。
每个 UploadData
都有一个关联的:
每个 RequestBody
都有一个关联的:
每个 WebRequestRequest
都有一个关联的:
-
method,它是一个
DOMString。 -
id,它是一个
DOMString。 -
type,它是一个
ResourceType。 -
url,它是一个
USVString。 -
initiator,它是一个
USVString或 null。 -
headers,它是一个
Headers或 null,初始为 null。 -
body,它是一个
RequestBody或 null,初始为 null。
每个 AuthChallenger
都有一个关联的:
每个 WebRequestAuthDetails
都有一个关联的:
每个 WebRequestResponse
都有一个关联的:
-
statusCode,它是一个
long。statusCode获取器 步骤为 返回 this 的 statusCode。 -
statusLine,它是一个
DOMString。statusLine获取器 步骤为 返回 this 的 statusLine。 -
fromCache,它是一个布尔值。
-
headers,它是一个
Headers或 null,初始为 null。 -
ip,它是一个
DOMString或 null。 -
redirectURL,它是一个
USVString或 null,初始为 null。redirectURL获取器 步骤为 返回 this 的 redirectURL。 -
auth,它是一个
WebRequestAuthDetails或 null,初始为 null。
每个 WebRequestEvent
都有一个关联的:
-
request,它是一个
WebRequestRequest。 -
frameId,它是一个
long。 -
frameType,它是一个
FrameType或 null,初始为 null。 -
documentId,它是一个
DOMString或 null,初始为 null。documentId获取器步骤 为 返回 this 的 documentId。 -
documentLifecycle,它是一个
DocumentLifecycle或 null, 初始为 null。documentLifecycle获取器步骤为 返回 this 的 documentLifecycle。 -
parentDocumentId,它是一个
DOMString或 null,初始为 null。parentDocumentId获取器步骤为 返回 this 的 parentDocumentId。 -
parentFrameId,它是一个
long或 null,初始为 null。parentFrameId获取器 步骤为 返回 this 的 parentFrameId。
每个 WebRequestAuthRequiredEvent
都有一个关联的:
-
response,它是一个
WebRequestResponse。
每个 WebRequestBeforeRedirectEvent
都有一个关联的:
-
response,它是一个
WebRequestResponse。
每个 WebRequestCompletedEvent
都有一个关联的:
-
response,它是一个
WebRequestResponse。
每个 WebRequestErrorOccurredEvent
都有一个关联的:
每个 WebRequestHeadersReceivedEvent
都有一个关联的:
-
response,它是一个
WebRequestResponse。 -
securityInfo,它是 一个
SecurityInfo。securityInfo获取器 步骤为 返回 this 的 securityInfo。
每个 WebRequestResponseStartedEvent
都有一个关联的:
-
response,它是一个
WebRequestResponse。
createWebRequestInterceptor(options)
方法步骤为:
-
令 interceptor 为一个新的
WebRequestInterceptor对象。 -
在 interceptor 上设置以下字段:
- resourceTypes
-
options["
resourceTypes"] - blocking
-
options["
blocking"] - includeRequestBody
-
options["
includeRequestBody"] - includeHeaders
-
options["
includeHeaders"] - securityInfo
-
options["
securityInfo"] - securityInfoRawDer
-
options["
securityInfoRawDer"]
-
对于 options["
urlPatterns"] 中的每个 urlPattern:-
如果 urlPattern 是一个
URLPattern, 则将 urlPattern 追加到 interceptor 的 urlPatterns。 -
否则,给定 urlPattern,将一个新的
URLPattern追加到 interceptor 的 urlPatterns。
-
-
返回 interceptor。
WebRequestInterceptor,
运行以下步骤:
-
令 client 为 request 的客户端。
-
如果 client 为 null,则返回一个空列表和
false。 -
令 window 为给定 client,环境设置对象的所属 Window。
-
如果 window 为 null,则返回一个空列表和
false。 -
令 navigable 为 window 的navigable。
-
如果 navigable 或其 controlledFrameEmbedderParent 为 null,则返回一个空列表 和
false。 -
令 controlledFrame 为 navigable 的 controlledFrameEmbedderParent。
-
令 applicableInterceptors 为空列表。
-
返回 applicableInterceptors。
WebRequestInterceptor
拦截,
运行以下步骤:
-
令 types 为 interceptor 的 resourceTypes。
-
如果 types 不是空, 且 types 不 包含给定 request 调用获取请求的 ResourceType的结果,则返回
false。 -
令 urlPatterns 为 interceptor 的 urlPatterns。
-
对于 urlPatterns 中的每个 urlPattern:
-
如果 request 的 URL 给定 urlPattern 匹配一个 URLPattern,则返回
true。
-
-
返回
false。
Window,
给定一个环境设置对象 environment,运行
以下步骤:
-
令 global 为 environment 的全局对象。
-
如果 global 是一个
Window对象,则返回 global。 -
如果 global 是一个
DedicatedWorkerGlobalScope对象,则:-
令 owner 为 global。
-
当 owner 是一个
DedicatedWorkerGlobalScope对象时:-
令 owner 为 owner 的所有者集合[0]。
-
-
-
返回 null。
4.1. 事件
WebRequestInterceptor
触发以下事件:
| 事件名称 | 接口 | 触发时机... |
|---|---|---|
| authrequired | WebRequestAuthRequiredEvent
| 一个被拦截的请求收到一个 HTTP 401(Unauthorized)407(Proxy Authentication Required)状态的响应时。 |
| beforeredirect | WebRequestBeforeRedirectEvent
| 一个被拦截的请求收到一个重定向响应时。 |
| beforerequest | WebRequestBeforeRequestEvent
| 一个被拦截的请求即将开始 处理时。 |
| beforesendheaders | WebRequestBeforeSendHeadersEvent
| 一个被拦截的 请求的请求标头即将发送时。 |
| completed | WebRequestCompletedEvent
| 一个被拦截的请求完成时。 |
| erroroccurred | WebRequestErrorOccurredEvent
| 处理一个被拦截的 请求时发生错误。 |
| headersreceived | WebRequestHeadersReceivedEvent
| 一个被拦截的请求收到 响应标头时。 |
| sendheaders | WebRequestSendHeadersEvent
| 一个被拦截的请求发送其请求 标头时。 |
| responsestarted | WebRequestResponseStartedEvent
| 一个被拦截的请求已开始 接收其响应时。 |
WebRequestInterceptor
支持以下事件处理程序(以及它们
对应的事件处理程序事件类型)作为事件处理程序 IDL 属性:
| 事件处理程序 | 事件处理程序事件类型 |
|---|---|
onauthrequired
| authrequired |
onbeforeredirect
| beforeredirect |
onbeforerequest
| beforerequest |
onbeforesendheaders
| beforesendheaders |
oncompleted
| completed |
onerroroccurred
| erroroccurred |
onheadersreceived
| headersreceived |
onsendheaders
| sendheaders |
onresponsestarted
| responsestarted |
每个 WebRequestAuthRequiredEvent
都有一个关联的:
-
cancel,一个布尔值,初始为
false。 -
authCredentials,一个
Promise<WebRequestAuthCredentials> 或 null,初始为 null。 -
options,一个
WebRequestAuthOptions, 初始为 «»。
WebRequestAuthRequiredEvent
的
setCredentials(credentials, options)
方法步骤为:
-
将 this 的 authCredentials 设置为 credentials。
每个 WebRequestBeforeRequestEvent
都有一个关联的:
每个 WebRequestBeforeSendHeadersEvent
都有一个关联的:
WebRequestBeforeSendHeadersEvent
的
setRequestHeaders(requestHeaders)
方法步骤为将 this 的
requestHeaders 设置为
requestHeaders。
每个 WebRequestHeadersReceivedEvent
都有一个关联的:
WebRequestHeadersReceivedEvent
的
setResponseHeaders(responseHeaders)
方法步骤为将 this 的
responseHeaders 设置为
responseHeaders。
WebRequestEvent 结果是一个具有以下 项的结构:
- cancel
-
一个布尔值,初始为
false - redirectURL
-
一个
USVString, 初始为 "" - authCredentials
-
一个
WebRequestAuthCredentials或 null,初始为 null - requestHeaders
-
一个标头列表,初始为 «»
- responseHeaders
-
一个标头列表,初始为 «»
-
令 interceptors 为获取 request 的适用的 WebRequestInterceptors的结果。
-
令 result 为一个 WebRequestEvent 结果。
-
令 pendingHandlerCount 为 0。
-
令 controlledFrameEmbedderGlobal 为给定 request 的客户端,获取环境的 controlledFrameEmbedderParent的结果的相关全局对象。
-
如果 controlledFrameEmbedderGlobal 为 null,则返回。
-
对于 interceptors 中的每个 interceptor:
-
如果 interceptor 的 blocking 为
true, 则递增 pendingHandlerCount。 -
在 controlledFrameEmbedderGlobal 的 DOM 操作任务源上排队一个全局任务,该任务将运行以下步骤:
-
令 event 为一个新的、名为 beforerequest 的
WebRequestBeforeRequestEvent。 -
给定 event、request 和 "
none",填充 WebRequestEvent。 -
如果 interceptor 的 includeRequestBody 为
true,且 request 的主体不是 null,则: -
将 event 分派给 interceptor。
-
如果 event 的 redirectURL 不为 null,且 result 的 redirectURL 为 "", 则将 result 的 redirectURL 设置为 event 的 redirectURL。
-
如果 interceptor 的 blocking 为
true, 则递减 pendingHandlerCount。
-
-
-
如果 pendingHandlerCount > 0,则并行等待 pendingHandlerCount 等于 0,然后排队一个全局任务,该任务将在 request 的客户端的全局对象的网络任务源,或这些步骤最初被调用所在的 并行上下文上继续运行此算法的剩余步骤, 具体取决于这些步骤在进入并行之前是如何运行的。
-
返回 result。
-
令 interceptors 为获取 request 的适用的 WebRequestInterceptors的结果。
-
令 result 为一个 WebRequestEvent 结果。
-
令 pendingHandlerCount 为 0。
-
令 controlledFrameEmbedderGlobal 为给定 request 的客户端,获取环境的 controlledFrameEmbedderParent的结果的相关全局对象。
-
如果 controlledFrameEmbedderGlobal 为 null,则返回。
-
对于 interceptors 中的每个 interceptor:
-
如果 interceptor 的 blocking 为
true, 则递增 pendingHandlerCount。 -
在 controlledFrameEmbedderGlobal 的 DOM 操作任务源上排队一个全局任务,该任务将运行以下步骤:
-
令 event 为一个新的、名为 beforesendheaders 的
WebRequestBeforeSendHeadersEvent。 -
给定 event、request,以及 interceptor 的 includeHeaders, 填充 WebRequestEvent。
-
将 event 分派给 interceptor。
-
如果 event 的 requestHeaders 不为 null,则:
-
如果 result 的 requestHeaders 为 null,则将其设置为一个新的
Headers。 -
对于 event 的 requestHeaders 中的每个 header:
-
将 header 追加到 result 的 requestHeaders。
-
-
-
如果 interceptor 的 blocking 为
true, 则递减 pendingHandlerCount。
-
-
-
如果 pendingHandlerCount > 0,则并行等待 pendingHandlerCount 等于 0,然后排队一个全局任务,该任务将在 request 的客户端的全局对象的网络任务源,或这些步骤最初被调用所在的 并行上下文上继续运行此算法的剩余步骤, 具体取决于这些步骤在进入并行之前是如何运行的。
-
返回 result。
-
令 interceptors 为获取 request 的适用的 WebRequestInterceptors的结果。
-
令 controlledFrameEmbedderGlobal 为给定 request 的客户端,获取环境的 controlledFrameEmbedderParent的结果的相关全局对象。
-
如果 controlledFrameEmbedderGlobal 为 null,则返回。
-
对于 interceptors 中的每个 interceptor:
-
在 controlledFrameEmbedderGlobal 的 DOM 操作任务源上排队一个全局任务,该任务将运行以下步骤:
-
令 event 为一个新的、名为 sendheaders 的
WebRequestSendHeadersEvent。 -
给定 event、request,以及 interceptor 的 includeHeaders, 填充 WebRequestEvent。
-
将 event 分派给 interceptor。
-
-
-
令 interceptors 为获取 request 的适用的 WebRequestInterceptors的结果。
-
令 result 为一个 WebRequestEvent 结果。
-
令 pendingHandlerCount 为 interceptor 的大小。
-
令 controlledFrameEmbedderGlobal 为给定 request 的客户端,获取环境的 controlledFrameEmbedderParent的结果的相关全局对象。
-
如果 controlledFrameEmbedderGlobal 为 null,则返回。
-
对于 interceptors 中的每个 interceptor:
-
如果 interceptor 的 blocking 为
true, 则递增 pendingHandlerCount。 -
在 controlledFrameEmbedderGlobal 的 DOM 操作任务源上排队一个全局任务,该任务将运行以下步骤:
-
令 event 为一个新的、名为 headersreceived 的
WebRequestHeadersReceivedEvent。 -
给定 event、request 和 "
none", 填充 WebRequestEvent。 -
将 event 的 response 设置为给定 request、 response,以及 interceptor 的 includeHeaders, 创建 WebRequestResponse 对象的结果。
-
如果 interceptor 的 securityInfo 为
true,或 interceptor 的 securityInfoRawDer 为true,则:-
令 info 为给定 response 和 interceptor 的 securityInfoRawDer,获取 安全信息的结果。
-
将 event 的 securityInfo 设置为 info。
-
-
将 event 分派给 interceptor。
-
如果 event 的 redirectURL 不为 null,且 result 的 redirectURL 为 "", 则将 result 的 redirectURL 设置为 event 的 redirectURL。
-
如果 event 的 responseHeaders 不为 null,则:
-
如果 result 的 responseHeaders 为 null,则将其设置为一个新的
Headers。 -
对于 event 的 responseHeaders 中的每个 header:
-
将 header 追加到 result 的 responseHeaders。
-
-
-
如果 interceptor 的 blocking 为
true, 则递减 pendingHandlerCount。
-
-
-
如果 pendingHandlerCount > 0,则并行等待 pendingHandlerCount 等于 0,然后排队一个全局任务,该任务将在 request 的客户端的全局对象的网络任务源,或这些步骤最初被调用所在的 并行上下文上继续运行此算法的剩余步骤, 具体取决于这些步骤在进入并行之前是如何运行的。
-
返回 result。
-
令 challenger 为一个新的
AuthChallenger, 其 host 和 port 等于 response 的 URL 的主机和 端口。 -
如果 response 的状态为 401,则:
-
否则:
-
如果 scheme 为 null,则返回 null。
-
令 interceptors 为获取 request 的适用的 WebRequestInterceptors的结果。
-
令 result 为一个 WebRequestEvent 结果。
-
令 pendingHandlerCount 为 0。
-
令 controlledFrameEmbedderGlobal 为给定 request 的客户端,获取环境的 controlledFrameEmbedderParent的结果的相关全局对象。
-
如果 controlledFrameEmbedderGlobal 为 null,则返回。
-
对于 interceptors 中的每个 interceptor:
-
如果 interceptor 的 blocking 为
true, 则递增 pendingHandlerCount。 -
在 controlledFrameEmbedderGlobal 的 DOM 操作任务源上排队一个全局任务,该任务将运行以下步骤:
-
令 event 为一个新的、名为 authrequired 的
WebRequestAuthRequiredEvent。 -
给定 event、request 和 "
none", 填充 WebRequestEvent。 -
将 event 的 response 设置为给定 request、 response,以及 interceptor 的 includeHeaders, 创建 WebRequestResponse 对象的结果。
-
将 event 的 response 的 auth 设置为一个新的
WebRequestAuthDetails, 其 challenger、 isProxy、 scheme 和 realm 字段的值 分别为 challenger、isProxy、scheme 和 realm。 -
将 event 分派给 interceptor。
-
令 credentials 为 event 的 authCredentials。
-
否则,如果 credentials 是一个
Promise, 则:-
令 done 为
false。 -
如果 signal 是一个
AbortSignal, 则向 signal 添加 以下中止算法:-
将 result 的 cancel 设置为
true。 -
将 done 设置为
true。
-
-
在 credentials 兑现时,运行以下接收 resolvedValue 的步骤:
-
如果 resolvedValue 是一个字典,且包含 两个等于 "username" 和 "password" 的键,并且 result 的 authCredentials 为 undefined,则将 result 的 authCredentials 设置为 resolvedValue。
-
将 done 设置为
true。
-
-
在 credentials 拒绝时,运行以下步骤:
-
将 done 设置为
true。
注:被拒绝的 promise 不会取消请求,但不会向服务器 提供凭据。
-
-
并行等待 done 等于
true,然后在 controlledFrameEmbedderGlobal 的 DOM 操作任务 源上排队一个全局任务,该任务将继续运行 此算法的剩余步骤。
-
如果 interceptor 的 blocking 为
true, 则递减 pendingHandlerCount。
-
-
-
如果 pendingHandlerCount > 0,则并行等待 pendingHandlerCount 等于 0,然后排队一个全局任务,该任务将在 request 的客户端的全局对象的网络任务源,或这些步骤最初被调用所在的 并行上下文上继续运行此算法的剩余步骤, 具体取决于这些步骤在进入并行之前是如何运行的。
-
返回 result。
-
令 interceptors 为获取 request 的适用的 WebRequestInterceptors的结果。
-
令 controlledFrameEmbedderGlobal 为给定 request 的客户端,获取环境的 controlledFrameEmbedderParent的结果的相关全局对象。
-
如果 controlledFrameEmbedderGlobal 为 null,则返回。
-
对于 interceptors 中的每个 interceptor:
-
在 controlledFrameEmbedderGlobal 的 DOM 操作任务源上排队一个全局任务,该任务将运行以下步骤:
-
令 event 为一个新的、名为 beforeredirect 的
WebRequestBeforeRedirectEvent。 -
给定 event、request 和 "
none", 填充 WebRequestEvent。 -
将 event 的 response 设置为给定 request、 response,以及 interceptor 的 includeHeaders, 创建 WebRequestResponse 对象的结果。
-
令 internalResponse 为 response,如果 response 不是过滤后的响应;否则为 response 的内部响应。
-
将 event 的 response 的 redirectURL 设置为给定 request 的当前 URL的 片段,internalResponse 的 位置 URL。
-
将 event 分派给 interceptor。
-
-
-
令 interceptors 为获取 request 的适用的 WebRequestInterceptors的结果。
-
令 controlledFrameEmbedderGlobal 为给定 request 的客户端,获取环境的 controlledFrameEmbedderParent的结果的相关全局对象。
-
如果 controlledFrameEmbedderGlobal 为 null,则返回。
-
对于 interceptors 中的每个 interceptor:
-
在 controlledFrameEmbedderGlobal 的 DOM 操作任务源上排队一个全局任务,该任务将运行以下步骤:
-
令 event 为一个新的、名为 responsestarted 的
WebRequestResponseStartedEvent。 -
给定 event、request 和 "
none", 填充 WebRequestEvent。 -
将 event 的 response 设置为给定 request、 response,以及 interceptor 的 includeHeaders, 创建 WebRequestResponse 对象的结果。
-
将 event 分派给 interceptor。
-
-
-
令 interceptors 为获取 request 的适用的 WebRequestInterceptors的结果。
-
令 controlledFrameEmbedderGlobal 为给定 request 的客户端,获取环境的 controlledFrameEmbedderParent的结果的相关全局对象。
-
如果 controlledFrameEmbedderGlobal 为 null,则返回。
-
对于 interceptors 中的每个 interceptor:
-
在 controlledFrameEmbedderGlobal 的 DOM 操作任务源上排队一个全局任务,该任务将运行以下步骤:
-
令 event 为一个新的、名为 completed 的
WebRequestCompletedEvent。 -
给定 event、request 和 "
none", 填充 WebRequestEvent。 -
将 event 的 response 设置为给定 request、 response,以及 interceptor 的 includeHeaders, 创建 WebRequestResponse 对象的结果。
-
将 event 分派给 interceptor。
-
-
-
令 interceptors 为获取 request 的适用的 WebRequestInterceptors的结果。
-
令 controlledFrameEmbedderGlobal 为给定 request 的客户端,获取环境的 controlledFrameEmbedderParent的结果的相关全局对象。
-
如果 controlledFrameEmbedderGlobal 为 null,则返回。
-
对于 interceptors 中的每个 interceptor:
-
在 controlledFrameEmbedderGlobal 的 DOM 操作任务源上排队一个全局任务,该任务将运行以下步骤:
-
令 event 为一个新的、名为 erroroccurred 的
WebRequestErrorOccurredEvent。 -
给定 event、request 和 "
none", 填充 WebRequestEvent。 -
将 event 分派给 interceptor。
-
-
WebRequestEvent,
给定一个 WebRequestEvent
event、一个请求 request,以及一个 RequestedHeaders
requestedHeaders,运行以下步骤:
-
令 environmentSettingsObject 为 request 的客户端。
-
在 event 上设置以下字段:
- frameId
-
-1
-
令 window 为给定 environmentSettingsObject, 环境设置对象的所属 Window。
-
如果 window 不为 null,则:
-
更新 event 的以下字段:
- documentId
-
environmentSettingsObject 的id。
- documentLifecycle
-
给定 window 的关联文档, 获取 Document 的 DocumentLifecycle的结果。
- frameId
- frameType
-
如果 window 的 浏览上下文的 fenced frame config instance 为非 null,则为
"fenced-frame"; 如果 parentNavigable 为 null,则为"outermost-frame"; 否则为"sub-frame"。
-
如果 parentNavigable 不为 null,则更新 event 的以下值:
- parentDocumentId
- parentFrameId
-
parentNavigable 的 frameId。
-
将 event 的 request 设置为一个具有以下字段的新的
WebRequestRequest: -
如果 requestedHeaders 不是 "
none", 则将 event 的 request 的 headers 设置为给定 request 的标头列表、requestedHeaders,以及 isRequest 等于true,调用将标头列表转换为 Headers 对象的结果。
Document
的 DocumentLifecycle,
给定 document,
运行以下步骤:
-
如果 document 的 unload counter > 0,则返回 "
pending-deletion"。 -
如果 document 的节点 navigable为非 null,且是一个预渲染 navigable,则返回 "
prerender"。 -
如果 document 是可抢救的,并且没有其 page showing, 则返回 "
cached"。 -
返回 "
active"。
WebRequestResponse
对象,给定一个请求
request、一个响应 response,以及一个 RequestedHeaders
requestedHeaders,运行以下步骤:
-
令 response 为一个具有以下字段的新的
WebRequestResponse:- statusCode
-
response 的状态。
- statusLine
-
response 的状态消息。
- fromCache
-
如果 response 的缓存状态为 "local",则为
true;否则为false。 - ip
-
如果该请求涉及网络请求,则为接收 response 来源的 IP 地址。
[FETCH] 规范目前未指定存储发送 request 时使用的远程 IP 地址。
-
如果 requestedHeaders 不是 "
none", 则将 response 的 headers 设置为 给定 response 的标头列表、requestedHeaders,以及 isRequest 等于false,调用将标头列表转换为 Headers 对象的结果。 -
返回 response。
-
令 info 为一个新的
SecurityInfo。 -
如果 scheme 为 "http" 或 "ws":
-
注:浏览器通常会在证书错误时中断 连接。如果用户已明确允许,则状态可能改为设置 为 "
broken"。 -
令 leafCert 为与 response 关联的服务器 X.509 证书(定义于 [RFC5280])。
-
令 derBytes 为对 leafCert 进行 DER 编码的结果(定义于 [X.690])。
-
令 certInfo 为一个新的
CertificateInfo。 -
令 fingerprint 为一个新的
Fingerprint。 -
计算 fingerprint 字符串:
-
将 certInfo["
fingerprint"] 设置为 fingerprint。 -
如果 includeRawDER 为
true:-
令 arrayBuffer 为从 derBytes 创建 ArrayBuffer 的结果。
-
将 certInfo["
rawDER"] 设置为一个新的、查看 arrayBuffer 的Uint8Array对象。
-
-
令 certList 为空列表。
-
将 certInfo 追加到 certList。
-
将 info["
certificates"] 设置为 certList。 -
返回 info。
Headers
对象,给定
一个标头列表 fetchHeaders、一个 RequestedHeaders
requestedHeaders,
和一个布尔值
isRequest,运行以下步骤:
-
对于 fetchHeaders 中的每个 fetchHeader:
-
如果满足以下所有条件,则继续:
-
isRequest 为
true -
requestedHeaders 为 "
cors"。 -
fetchHeader 不是 CORS 安全列出的 request-header
-
-
如果满足以下所有条件,则继续:
-
isRequest 为
false -
requestedHeaders 为 "
cors"。 -
fetchHeader[0] 不是 CORS 安全列出的 response-header 名称
-
-
将 fetchHeader 追加到 headers。
-
-
返回 headers。
ResourceType,
给定一个请求
request,运行以下步骤:
-
如果 request 的initiator 等于
"fetch"或"xmlhttprequest",则返回 "xmlhttprequest"。 -
如果 request 的destination 等于
"document", 则返回 "main-frame"。 -
如果 request 的destination 等于
"frame"或"iframe", 则返回 "sub-frame"。 -
如果 request 的destination 等于
"style"或"xslt", 则返回 "stylesheet"。 -
如果 request 的destination 等于
"script"、"json"、"audioworklet"、"paintworklet"、"serviceworker"、"sharedworker"或"worker",则返回 "script"。 -
如果 request 的destination 等于
"image", 则返回 "image"。 -
如果 request 的destination 等于
"font", 则返回 "font"。 -
如果 request 的destination 等于
"object"或"embed", 则返回 "object"。 -
如果 request 的destination 等于
"audio"、"track"或"video",则返回 "media"。 -
如果 request 的destination 等于
"report", 则返回 "csp-report"。 -
如果 request 的destination 等于
"",且 request 的 keepalive 为true,则返回 "ping"。 -
返回 "
other"。
4.2. 猴子补丁
4.2.1. Fetch
一个请求具有关联的 requestId,它 是一个 不透明字符串,在请求创建时随机分配。
main fetch 算法被猴子补丁如下:
-
令 request 为 fetchParams 的 request。
-
令 response 为 null。
- 令 webRequestResult 为给定 request 调用处理 beforeRequest 事件的结果。
-
如果 webRequestResult 不为 null,则:
-
如果 webRequestResult 的 cancel 为
true,则将 response 设置为网络错误。 -
否则,如果 webRequestResult 的 redirectURL 不是一个空
DOMString, 则将 response 设置为 给定 webRequestResult 的 redirectURL 创建重定向响应的结果。
-
如果 webRequestResult 的 cancel 为
fetch response handover 算法被猴子补丁如下:
- 如果 response 不是网络错误,则给定 fetchParams 的 request 和 response,调用处理 responseStarted 事件。
-
令 timingInfo 为 fetchParams 的 timing info。
⋮
-
如果 fetchParams 的 process response consume body 非 null,则:
…
- 如果 response 不是网络错误,则给定 fetchParams 的 request 和 response,调用处理 completed 事件。
- 否则,给定 fetchParams 的 request 和 response,调用 处理 errorOccurred 事件。
HTTP-network-or-cache fetch 算法被猴子 补丁如下:
-
令 revalidatingFlag 为未设置。
- 将 webRequestResult 设置为给定 request 调用处理 beforeSendHeaders 事件的结果。
-
如果 webRequestResult 不为 null,则:
-
如果 webRequestResult 的 cancel 为
true,则将 response 设置为网络错误。 - 否则,如果 webRequestResult 的 requestHeaders 是非空列表,则将 request 的 标头列表设置为 webRequestResult 的 requestHeaders 的标头列表。
-
如果 webRequestResult 的 cancel 为
-
如果 response 不为 null,
运行这些步骤,但在
fetchParams 被取消时中止:
⋮
-
如果已中止,则返回适合 fetchParams 的网络错误。
-
如果 response 为 null,则:
-
如果 httpRequest 的 cache mode 为 "
only-if-cached",则返回一个 网络错误。 - 给定 request,调用处理 sendHeaders 事件。
-
令 forwardResponse 为给定 httpFetchParams、includeCredentials 和 isNewConnectionFetch,运行HTTP-network fetch的结果。
- 如果 forwardResponse 不是网络错误,令 webRequestResult 为给定 request 和 forwardResponse 调用处理 headersReceived 事件的结果; 否则为 null。
-
如果 webRequestResult 不为 null,则:
-
如果 webRequestResult 的 cancel 为
true,则将 response 设置为网络错误。 -
否则,如果 webRequestResult 的
redirectURL 不是空
DOMString, 则将 forwardResponse 设置为给定 webRequestResult 的 redirectURL 创建重定向响应的结果。 - 否则,如果 webRequestResult 的 responseHeaders 是非空 列表,则将 forwardResponse 的标头列表设置为 webRequestResult 的 responseHeaders 的 标头列表。
-
如果 webRequestResult 的 cancel 为
-
⋮
-
如果 response 的状态为 401,httpRequest 的 response tainting 不是 "cors",includeCredentials 为
true,且 request 的 window 是一个 环境设置对象,则:⋮
-
如果 request 的 use-URL-credentials flag 未设置,或 isAuthenticationFetch 为
true,则:-
如果 fetchParams 被取消,则返回适合 fetchParams 的网络 错误。
-
令 username 和 password 为 null。
- 令 webRequestResult 为给定 request 和 response 调用处理 authRequired 事件的结果。
-
如果 webRequestResult 不为 null,则:
-
如果 webRequestResult 的 cancel
为
true,则将 response 设置为网络错误。 -
否则,如果 webRequestResult 的 authCredentials
是一个
object, 则:-
将 username 设置为 webRequestResult 的
authCredentials["
username"]。 -
将 password 设置为 webRequestResult 的
authCredentials["
password"]。
-
将 username 设置为 webRequestResult 的
authCredentials["
-
如果 webRequestResult 的 cancel
为
- 如果 username 和 password 为 null,则将它们分别设置为 在 request 的window 中提示最终用户输入用户名和密码的结果。
-
-
-
如果 response 的状态为 407,则:
- 令 webRequestResult 为给定 request 和 response 调用处理 authRequired 事件的结果。
-
如果 webRequestResult 不为 null,则:
-
如果 webRequestResult 的 cancel 为
true,则将 response 设置为网络错误。 -
否则,如果 webRequestResult 的 authCredentials 是一个
object, 则:- 将 webRequestResult 的 authCredentials 存储为proxy-authentication entry。
-
如果 webRequestResult 的 cancel 为
- 否则, 适当地提示最终用户 ...
HTTP-redirect fetch 算法被猴子补丁如下:
- 给定 request 和 response,调用处理 beforeRedirect 事件。
-
令 request 为 fetchParams 的 request。
5. Context Menus API
enum {ContextType ,"all" ,"page" ,"frame" ,"selection" ,"link" ,"editable" ,"image" ,"video" , };"audio" enum {ItemType ,"normal" ,"checkbox" ,"radio" , };"separator" dictionary {ContextMenusProperties boolean ;checked sequence <ContextType >;contexts sequence <(URLPattern or URLPatternInput )>;documentURLPatterns boolean ;enabled DOMString ;parentId sequence <(URLPattern or URLPatternInput )>;targetURLPatterns DOMString ;title ItemType ; };type dictionary :ContextMenusCreateProperties ContextMenusProperties {required DOMString ; }; [id Exposed =Window ,IsolatedContext ]interface :ContextMenus EventTarget {Promise <undefined >create (ContextMenusCreateProperties );properties Promise <undefined >remove (DOMString );id Promise <undefined >removeAll ();Promise <undefined >update (DOMString ,id optional ContextMenusProperties = {});properties attribute EventHandler onclick ;attribute EventHandler onshow ; }; [Exposed =Window ,IsolatedContext ]interface {MenuItemDetails readonly attribute DOMString ;id readonly attribute DOMString ?;parentMenuId readonly attribute boolean ?;checked readonly attribute boolean ?; }; [wasChecked Exposed =Window ,IsolatedContext ]interface :ContextMenusClickEvent Event {readonly attribute MenuItemDetails ; // Details about the frame the context menu is opened within.menuItem readonly attribute long ;frameId readonly attribute USVString ;frameURL readonly attribute USVString ; // Details about the element the context menu is opened within the context of.pageURL readonly attribute boolean ;editable readonly attribute USVString ?;linkURL readonly attribute DOMString ?;mediaType readonly attribute DOMString ?;selectionText readonly attribute USVString ?; };srcURL
每个
controlledframe
都有一个 contextMenus
成员,它是一个 ContextMenus。
每个 ContextMenus
管理一个
上下文菜单映射,其
键是
表示菜单项 id 的 DOMString,
其值是
ContextMenusProperties。
条目 中的每个上下文菜单映射表示一个 上下文菜单项。一个 上下文菜单项 表示上下文菜单中的一个条目。每个上下文菜单 项都具有关联的:
一个 上下文菜单表示一个实现定义的接口,可向用户显示
上下文菜单项。每个上下文菜单都具有关联的
上下文元素,即打开该上下文菜单
所处上下文中的 HTMLElement。
如果给定 item 确定该上下文菜单项是否会被显示返回
true,则应当作为实现定义的操作的结果,向用户显示上下文菜单项
item。
注:此 API 的意图是向用户公开依赖上下文的附加 操作。在桌面平台上,这可能表现为通过右键点击 Controlled Frame 内部内容来访问的上下文菜单中的条目; 在移动设备上,则可能通过长按 Controlled Frame 内部的某个项目来访问。在这些示例中,上下文 菜单的上下文元素会是用户右键点击或长按的元素。
上下文菜单映射的
值,即
ContextMenusProperties
对象,用于控制
上下文菜单项在何种条件下显示,以及这些项目的
特性和行为。
ContextMenusProperties
具有以下字段:
contexts-
不同
ContextType的列表。 如果它不是空, 则除非被点击以打开上下文菜单的元素等于其中一个 列表项,否则该 上下文菜单项不会显示。如果它是 空,则忽略此检查。 documentURLPatterns-
URLPattern或URLPatternInput的列表。 如果它不是 空,则除非嵌入文档的 URL 与其中一个列表项的 URLPattern 匹配,否则该上下文 菜单项不会显示。如果它是 空,则忽略此 检查。 targetURLPatterns-
URLPattern或URLPatternInput的列表。 如果它不是 空,则除非上下文菜单目标的 URL 与其中一个列表项的 URLPattern 匹配,否则该上下文 菜单项不会显示。如果它是 空,则忽略此检查。
注:Target 是 img/audio/video 标签的 "src" 属性 以及锚点标签的 "href"。
create(properties) 方法步骤为:
-
令 p 为一个新 promise。
-
令 controlledframe 为 this。
-
返回 p 并并行运行以下步骤。
-
令 contextMenusMap 为 controlledframe 的上下文 菜单映射。
-
令 id 为 properties["
id"]。 -
如果 contextMenusMap[id] 存在,则给定 controlledframe、p 和
TypeError, 拒绝一个嵌入者 promise, 并中止这些步骤。 -
将 contextMenusMap[id] 设置为 properties。
-
给定 controlledframe 和 p,解决一个嵌入者 promise。
remove(id) 方法步骤为:
-
令 p 为一个新 promise。
-
令 controlledframe 为 this。
-
返回 p 并并行运行以下步骤。
-
令 contextMenusMap 为 controlledframe 的上下文 菜单映射。
-
移除 contextMenusMap[id]。
-
给定 controlledframe 和 p,解决一个嵌入者 promise。
removeAll() 方法步骤为:
-
令 p 为一个新 promise。
-
令 controlledframe 为 this。
-
返回 p 并并行运行以下步骤。
-
令 contextMenusMap 为 controlledframe 的上下文 菜单映射。
-
清空 contextMenusMap。
-
给定 controlledframe 和 p,解决一个嵌入者 promise。
update(id, properties) 方法
步骤为:
-
令 p 为一个新 promise。
-
令 controlledframe 为 this。
-
返回 p 并并行运行以下步骤。
-
令 contextMenusMap 为 controlledframe 的上下文 菜单映射。
-
如果 contextMenusMap[id] 不存在,则给定 controlledframe、p 和
TypeError, 拒绝一个嵌入者 promise, 并中止这些步骤。 -
将 contextMenusMap[id] 设置为 properties。
-
给定 controlledframe 和 p,解决一个嵌入者 promise。
ContextType
表示上下文菜单的上下文,可以是以下值:
要确定该上下文菜单项是否会被显示 ,给定一个上下文菜单项 item:
-
令 properties 为 item 的properties。
-
令 controlledframe 为 element 的节点 navigable的 controlledFrameEmbedderParent。
-
如果 controlledframe 为 null,则返回
false。 -
令 documentUrl 为 controlledframe 的嵌入的 navigable的活动文档的 URL。
-
令 targetUrl 为空字符串。
-
如果 element 是
HTMLImageElement的实例,则将 targetUrl 设置为 element 的src属性。 -
如果 element 是
HTMLMediaElement的实例,则将 targetUrl 设置为 element 的src属性。 -
如果 element 是
HTMLAnchorElement的实例,则将 targetUrl 设置为 element 的 href 属性。 -
如果 properties["
contexts"] 不是 空:-
令 matchesContext 为初始值为
false的布尔值。 -
对于 properties["
contexts"] 中的每个 context:-
如果 element 匹配 context,则将 matchesContext 设置为
true并跳出;ContextType的匹配行为尚未被指定,尽管上面的注释包含了一些期望行为的信息。
-
-
如果 matchesContext 为
false,则返回false。
-
-
如果 properties["
documentURLPatterns"] 不是空:-
令 matchesDocumentUrl 为初始值为
false的布尔值。 -
对于 properties["
documentURLPatterns"] 中的每个 urlPattern:-
如果 urlPattern 是一个
URLPatternInput, 则将 urlPattern 设置为给定 urlPattern 的 一个新的URLPattern。 -
如果给定 urlPattern,documentUrl 匹配一个 URLPattern, 则将 matchesDocumentUrl 设置为
true并跳出;
-
-
如果 matchesDocumentUrl 为
false,则返回false。
-
-
如果 properties["
targetURLPatterns"] 不是 空:-
令 matchesTargetUrl 为初始值为
false的布尔值。 -
对于 properties["
targetURLPatterns"] 中的每个 urlPattern:-
如果 urlPattern 是一个
URLPatternInput, 则将 urlPattern 设置为给定 urlPattern 的 一个新的URLPattern。 -
如果给定 urlPattern,targetUrl 匹配一个 URLPattern,则 将 matchesTargetUrl 设置为
true并跳出;
-
-
如果 matchesTargetUrl 为
false,则返回false。
-
-
返回
true。
5.1. 事件
ContextMenus
触发以下事件:
| 事件名称 | 接口 | 触发时机... |
|---|---|---|
| show | Event
| 向用户显示上下文菜单时。 |
| click | ContextMenusClickEvent
| 用户选择一个上下文菜单项时。 |
ContextMenus
支持以下事件处理程序(以及它们
对应的事件处理程序事件类型)作为事件处理程序 IDL 属性:
| 事件处理程序 | 事件处理程序事件类型 |
|---|---|
onshow
| show |
onclick
| click |
当 ContextMenus
contextMenus 的一个或多个上下文菜单项被显示给用户时,向
contextMenus 分派一个 show 事件。
当一个上下文菜单项 item 被用户选中时, 给定 item 分派一个 click 事件。
-
令 properties 为 item 的properties。
-
令 menu 为 item 的menu。
-
令 element 为 menu 的上下文 元素。
-
令 event 为一个新的、名为 click 的
ContextMenusClickEvent。 -
将 event["
menuItem"] 设置为一个具有以下字段的新的MenuItemDetails:id-
item 的id。
parentMenuId-
properties["
parentId"]。 checked-
该上下文菜单项是否被选中。
wasChecked-
复选框或单选项在被点击之前的状态。
-
设置 event 的以下字段:
frameId-
element 的节点 navigable的 frameId。
frameURL-
element 的节点 navigable的 URL。
pageURL-
element 的traversable navigable的 URL。
editable-
所选 element 是否可编辑,例如文本输入框。
linkURL-
如果 element 是
HTMLAnchorElement的实例,则为 element 的href属性。 mediaType-
如果存在,则基于 element,为 "image"、"video" 或 "audio" 之一。
selectionText-
上下文选择的文本,如果有。
srcURL-
element 的 "src" 属性,如果存在。
-
在 menu 上分派 event。
6. 使用概述
Lorem ipsum。此处插入基本信息和示例。
7. 激励性应用
本节是非规范性的。
7.1. 虚拟化会话中的延迟敏感应用
在虚拟化环境中,用户通常有一个本地瘦客户端,用于渲染完整的虚拟桌面。 实际的桌面执行环境将在远程虚拟化服务器上运行。如果用户的浏览器导航到一个 延迟敏感应用(例如视频应用),所渲染的内容将具有额外延迟("lag"),从而使用户体验变得困难或 不可能。这也适用于会记录用户的应用,例如视频会议应用。在这些延迟敏感 应用中,虚拟桌面应用可以在本地渲染延迟敏感内容,并将其叠加在所渲染的远程内容之上, 以减少这种延迟。此用例也称为 "browser content redirection"。
7.2. 不受限制地嵌入第三方 Web 内容
在信息亭环境中,应用必须从第三方加载内容,并在其应用内的屏幕上
显示该内容。导航事件可能由教师触发,也可能由购物中心经理等管理员配置。
内容可能通过使用 X-Frame-Options 和 CSP 来禁止通过
iframe
嵌入。然而,controlled frame 应当能够加载所有内容,甚至包括禁止通过
iframe
嵌入的内容。
7.3. 远程显示和操纵 Web 内容
在信息亭环境中,应用必须确保内容持续显示在屏幕上,并且可能需要用它们自己提供的 行为打断内容。此行为应当在没有管理员本地值守的情况下工作,并且理想情况下可以通过网络远程管理。 例如,如果内容发生崩溃,这些应用应当观察并响应崩溃,在新的嵌入视图中重新加载内容。
7.4. 每个会话后清除用户内容
在某些环境中,某人只会短时间使用单个设备来完成其任务,例如在餐厅点餐。 当其任务完成时,嵌入者应用应当能够清除与该任务相关的所有本地用户数据, 然后重新启动嵌入实例。
7.5. 监控空闲会话
当用户与嵌入内容交互时,用户可能不会明确结束其会话。即使他们实际上已经完成或离开而没有完成任务, 该内容仍可能假定用户仍在场。嵌入者应用希望检测用户在超过其场景阈值时处于空闲状态, 并开始一个新的会话。
7.6. 任意阻止导航
在显示并非由嵌入者创作的嵌入式 Web 内容时,页面可能链接到被禁止的第三方 Web 内容。 允许嵌入者通过向 Web 内容中注入任意脚本来编辑嵌入内容中的元素,可以确保不会导航到被阻止的页面。 嵌入者还可以使用 Controlled Frame API 捕获导航事件,并确保只有获准站点的页面可以 在该 controlled frame 中加载。
8. 安全、隐私和可访问性考虑事项
本节是非规范性的。
8.1. 安全
Controlled Frame 基于 [Isolated-Web-Apps] (IWA), 并与核心安全规范集成
由于 Controlled Frame 是一个特别强大的 API,使用它,甚至只是让它可用, 都会使应用成为各种类型攻击的目标。因此,此 API 被限制在 IWA 中使用,IWA 具有额外的 保护措施来保护应用开发者和用户。Isolated Web App 解释器对此有如下说明:
"如果开发者需要访问会使应用成为 XSS 或服务器端攻击诱人目标的 API, 用户代理也可以强制应用采用这种威胁模型。"
Controlled Frame 正是这样一种诱人的目标,并且为了谨慎地公开它,我们选择加入 IWA,以防范某些攻击。一般来说, IWA 提供强大的安全保证,确保应用中的每项资源 在静态存储和传输中都是安全的。你可以在 IWA 解释器和 IWA [High-Watermark-Permissions] 解释器中阅读更多关于 IWA 安全性和权限的内容。
Controlled Frame 与 [Permissions-Policy] 和 [Permissions] 集成。 你可以阅读更多关于 Permissions Policy § 12. Privacy and Security 以及 Permissions § E Security considerations 的内容(注意该条目目前较为简略)。
攻击性网站可能显示原本不允许自身被嵌入的内容,并欺骗非 IWA 上的用户。
计划中的缓解措施:
-
Controlled Frame 将仅在 IWA 内可用
一个 IWA 可能通过 Controlled Frame 嵌入另一个 IWA(或 自身),从而以某种方式操纵我们的 IWA 策略(例如,被 Controlled Frame 嵌入的 IWA 可能会因缺少 "controlled-frame" 策略控制特性而检测到自己正被嵌入)。
计划中的缓解措施:
-
Controlled Frame 只能指向 "https" scheme,排除 用于 IWA 的 "isolated-app" scheme
Controlled Frame 可能获得对强大的 <controlledframe> 元素的访问权限。
不预期使用 Controlled Frame 的 IWA 可能尝试嵌入内容。
计划中的缓解措施:
-
其次,只有嵌入者应用及其已被授予 "controlled-frame" 策略控制特性的同源 IWA 子 navigable 才会有 Controlled Frame 元素可用。
-
没有 "controlled-frame" 策略控制特性的同源子 navigable 将不会获得 Controlled Frame 元素。 其内部同源嵌套 navigable 也始终不会有它可用。
IWA 可能尝试嵌入来自非 https scheme 的内容,例如 'http:' 或 'isolated-app:'
计划中的缓解措施:
-
Controlled Frame 仅在 navigable 的 "src" URL 具有 'https:' scheme 时工作。
恶意 Controlled Frame 可能访问嵌入者正在运行的进程(例如 Spectre 攻击)
计划中的缓解措施:
-
Controlled Frame 将在与嵌入者进程分离的进程中执行
给定 "https origin" 的 Controlled Frame 可能与该 https origin 的用户自身存储数据 交互或产生干扰
计划中的缓解措施:
-
我们正在添加 Partition 概念。每个 Partition 是 StorageKey 和一个独立对象键的元组。
-
存在一个 key=0 的默认 partition,用于存储 "non-IWA" 窗口 和标签页使用。
-
Controlled Frame 将始终把数据存储在某个 StorageKey 中,该 StorageKey 与默认 partition 分离。
-
当用户通过 IWA Controlled Frame 访问给定 "https origin" 时, 由该 origin 写入的数据将与默认 partition 隔离。
-
所有使用都将在 IWA 和每个 partition 之间分离,并且各 partition 将彼此完全隔离,也与 IWA 外部的默认使用完全隔离。
恶意 Controlled Frame 可能覆盖嵌入者存储的数据
-
嵌入者和被嵌入的存储用户代理可能重叠,并且可能有多个同站点 IWA 子 navigable 会受到 Controlled Frame 中活动的影响
-
如果存储用户代理在嵌入者和被嵌入站点之间共享,清除其中任一方的数据 都可能对另一方产生负面影响
计划中的缓解措施:
-
IWA 和 Controlled Frame 将始终拥有分离的 存储用户代理
-
Controlled Frame 不应具有读取或写入其自身之外其他存储用户代理的权限
恶意 Controlled Frame 可能检测到自身被嵌入,并试图攻击嵌入者应用
计划中的缓解措施:
-
用户代理将与浏览器匹配。
-
Controlled Frame 存储用户代理将与 IWA 以及默认存储用户代理分离。
-
Controlled Frame 进程将与 IWA 以及默认渲染器和浏览器进程分离。
-
Controlled Frame 环境将看起来像最顶层 navigable:
-
window 应当与 window.parent 和 window.top 匹配
-
策略控制特性列表及其禁用/启用状态应当与 navigable 的默认状态匹配
-
想法:
-
调查围绕文件系统、配额存储和 localStorage API 的潜在交互
用户可能无法验证在 Controlled Frame 中查看的页面的源
想法:
-
以某种方式向用户公开源,例如在 Controlled Frame 顶部添加显示源的 UI?
-
让 IWA 在清单中指定它们 预期访问的源?
Controlled Frame 可能利用过时浏览器引擎中的漏洞
已通过以下方式解决:
-
现有浏览器引擎自动更新机制
8.2. 隐私
Controlled Frame 与 Permissions Policy 和 Permissions 集成。你可以阅读更多关于 Permissions Policy § 12. Privacy and Security 的内容。你可以阅读更多关于 Permissions § E Security considerations 的内容。
对于 Controlled Frame,我们已识别出以下隐私考虑事项:
-
用户在 Controlled Frame 中的浏览将对 IWA 可见
-
IWA 可以访问并外传 Controlled Frame 的 会话 cookie(这仅适用于 Controlled Frame 的会话,因为它们使用与 IWA 以及在标签页中浏览时的 第三方 origin 分离的存储 partition)
-
Controlled Frame 中的用户活动可被 IWA 观察(例如,可监视键盘事件,可嗅探密码输入)
-
用户向 Controlled Frame 上传文件可能被劫持
-
Controlled Frame 远程服务器中保存的用户数据可能被 IWA 植入的代码访问
-
希望清除其会话历史的用户也必须通过 IWA 执行清除,而该 IWA 随后需要清除关联的 存储用户代理
-
这是必要的,因为对于任意给定 https origin,嵌入式存储用户代理 与非嵌入式存储用户代理是分离的
-
-
我们计划调查浏览器 UX,以允许用户清除 Controlled Frame 存储用户代理,将考虑以下情况:
-
如果用户想要清除某个 IWA 的站点数据, 关联的嵌入式存储用户代理也会被清除
-
用户可能希望清除给定 "https origin" 的所有站点数据,即使该 origin 存储在某个 IWA 的嵌入式 存储用户代理中
-
我们可以选择提供清除该 "https origin" 的所有 IWA 站点数据的能力, 即使该站点数据保存在嵌入式存储用户代理中
-
如果我们选择清除 "https origin" 数据, IWA 将需要为嵌入式存储用户代理可能在其 控制之外被移除的情况做好准备,这可能会扰乱 IWA 并引入实现复杂性
-
在浏览器用户代理中支持此做法会让浏览器厂商、开发者和用户面临额外复杂性, 因此我们可以选择不支持此方式,而是将其留给 IWA 开发者实现
-
作为支持清除单个给定 "https origin" 的嵌入式存储用户代理的反例,请考虑: 据我们所知,没有操作系统会这样行为
-
也就是说,不存在一个中央的 "clear browsing data" 选项会清除所有已安装浏览器引擎的 存储;每个应用的存储都被视为由其自身管理
-
-
-
用户想要清除给定 IWA 的、 针对给定 "https origin" 的 Controlled Frame 嵌入式存储用户代理的站点数据
-
用户想要清除给定 IWA 的、 针对所有 "https origins" 的 Controlled Frame 嵌入式存储用户代理的站点数据
-
-
IWA 将需要具备清除存储用户代理的、针对给定 "https origin" 的 Controlled Frame 嵌入式存储用户代理的能力
8.3. 可访问性
对于 Controlled Frame,我们已识别出以下可访问性考虑事项:
-
浏览器用户代理的可访问性工具和 API 应当能够看到 Controlled Frame
-
IWA 应当预期为 Controlled Frame 内容提供自己的 可访问性工具,以便为某些用例(例如 "browser content redirection")正确集成可访问性特性
9. 致谢
以下人员为本文档的开发做出了贡献。