受控框架 API

社区组报告草案

本版本:
https://wicg.github.io/controlled-frame/
问题跟踪:
GitHub
规范内联
编辑:
Google LLC
Google LLC
Google LLC

摘要

本文档定义了一种 API,用于仅在隔离 Web 应用(IWA)的上下文中 嵌入任意 Web 内容。被嵌入的 内容是在嵌入者内部并受其控制的一个新的顶级浏览上下文。

本文档的状态

本规范由 Web Platform Incubator Community Group 发布。 它不是 W3C 标准,也不在 W3C 标准轨道上。 请注意,根据 W3C 社区贡献者许可协议 (CLA) 存在有限的退出选择,并且适用其他条件。 了解更多关于 W3C 社区和业务组的信息。

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 — 要嵌入的内容源 URL
partition — 用于保存与此内容相关数据的分区名称
无障碍考虑事项
面向作者
面向实现者

注:这些链接指向 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> scriptNameList);

    // Configuration methods.
    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 zoomMode);

    // Capture methods.
    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 属性 srcpartition 必须反映 同名的相应内容属性。

每个 controlledframe 都关联有:

contentWindow 获取器 步骤是返回 thiscontentWindow

request 获取器步骤 是返回 thisrequest

contextMenus 获取器 步骤是返回 thiscontextMenus

controlledframe 元素 element插入到一个文档中,且该文档的 浏览上下文为非 null 时,运行以下步骤:
  1. 如果 elementsrc 不为空,则:

    1. 给定 element初始化 controlledframe

controlledframe 元素 element从文档中移除时, 运行以下步骤:
  1. 给定 element嵌入的 navigable销毁一个顶级 traversable

  2. element嵌入的 navigable设置为 null。

初始化一个 controlledframe 元素 element,运行 以下步骤:
  1. 断言 element嵌入的 navigable为 null。

  2. group 为一个新的浏览上下文组

  3. document 为给定 element节点文档elementgroup创建新的浏览上下文和 文档的第二个返回值。

  4. documentState 为一个新的文档状态,其文档document

  5. traversable 为一个新的traversable navigable

  6. 给定 documentState初始化 navigable traversable

  7. traversablecontrolledFrameEmbedderParent 设置为 element

  8. element嵌入的 navigable设置为 traversable

  9. initialHistoryEntrytraversable活动会话历史条目

  10. initialHistoryEntry步数设置为 0。

  11. initialHistoryEntry 追加traversable会话历史条目

    这些步骤 是在新的 navigable 中初始化 History.length 所必需的。这是 HTML 标准中的一个现有 议题

  12. elementcontentWindow 设置为 documentWindowProxy

  13. 给定 elementelementsrc导航 controlledframe

导航一个 controlledframe 元素 element,给定一个 USVString urlString,运行以下步骤:
  1. 如果 urlString 不是绝对 URL 字符串,则返回。

  2. url 为给定 urlStringelement节点文档解析 URL的结果。

  3. historyHandling 为 "auto"。

  4. 如果 element嵌入的 navigable活动文档完全加载,则将 historyHandling 设置为 "replace"。

  5. 使用 element节点文档,并以 historyHandling 作为 NavigationHistoryBehavior, 将 element嵌入的 navigable导航url

HTMLControlledFrameElement() 构造器步骤为:
  1. thisrequest设置为一个新的 WebRequest

  2. thiscontextMenus设置为一个新的 ContextMenus

3.1. 通用基础设施

解决嵌入者 promise,给定一个 controlledframe controlledframe、一个 promise promise 以及一个可选的 value, 运行以下步骤:
  1. controlledframe相关全局对象DOM 操作任务源排队一个全局任务,以使用 value 解决 promise

    注: controlledframe相关全局对象嵌入者的 Window 对象。

拒绝嵌入者 promise,给定一个 controlledframe controlledframe、一个 promise promise 以及一个可选的 value, 运行以下步骤:
  1. controlledframe相关全局对象DOM 操作任务源排队一个全局任务,以使用 value 拒绝 promise

    注: controlledframe相关全局对象嵌入者的 Window 对象。

如果以下步骤返回 true,则一个 URL url 匹配 URLPattern pattern
  1. result 为给定 patternurl匹配的结果。

  2. 如果 result 为 null,则返回 false

  3. 返回 true

3.2. 属性

partition 属性 接受一个标识符,用于指定与 Controlled Frame 实例相关的数据应存储在哪里。该标识符由一个字母数字字符组成的字符串构成。 嵌入的 navigable的所有数据都必须存储 在一个存储搁板中,该搁板由此分区字符串以及 创建该数据的源共同作为键。

默认情况下,所有存储的数据都必须保存在内存中的存储分区中,这样 当最后一个具有给定 partition 值的 Controlled Frame 元素被销毁时,该数据也会 被销毁。当数据保存在此分区中时,Controlled Frame 的 嵌入的 navigable中的任何数据都不得持久化。

如果 partition 属性标识符包含前缀 "persist:",则用户 代理必须使用基于磁盘的存储环境,而不是内存中的 存储分区。被嵌入内容不应能够检测其 存储是在内存中还是持久的。

如果多个 Controlled Frame 共享同一个分区标识符,则它们的所有 嵌入的 navigable实例必须共享同一个 存储分区。

注:下面会对 [STORAGE] 规范打猴子补丁,以基于 partition 属性的值对存储进行分区。

partition IDL 属性设置器步骤为:
  1. 如果 this嵌入的 navigable不是 null,则:

    1. 抛出一个 "NotSupportedError" DOMException

  2. thispartition 设置为给定值。

src 属性 反映 Controlled Frame 的嵌入的 navigable当前会话历史条目URL

src IDL 属性设置器步骤为:
  1. 如果 this在文档树中,则返回。

  2. 如果 this嵌入的 navigable为 null,则:

    1. 给定 this初始化 controlledframe

  3. 否则:

    1. 给定 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()

取消文档加载。

增量遍历嵌入的 navigable 的历史, 给定一个 controlledframe controlledframe 和一个整数 delta,运行 以下步骤:
  1. resultPromise一个新的 promise

  2. 返回 resultPromise,并并行运行剩余步骤。

  3. embeddedNavigablecontrolledframe嵌入的 navigable

  4. 如果 embeddedNavigable 为 null,则给定 controlledframeresultPromisefalse解决嵌入者 promise,并中止这些 步骤。

  5. 如果 embeddedNavigable活动文档不是完全活动的, 则给定 controlledframeresultPromisefalse解决嵌入者 promise,并中止这些步骤。

  6. embeddedNavigable 追加以下会话历史 遍历步骤

    1. allSteps 为对 embeddedNavigable 获取所有已使用历史步骤 的结果。

    2. currentStepIndexembeddedNavigable当前会话历史步骤allSteps 中的索引。

    3. targetStepIndexcurrentStepIndex + delta

    4. 如果 allSteps[targetStepIndex] 不存在,则 给定 controlledframeresultPromisefalse解决嵌入者 promise,并中止这些步骤。

    5. result 为给定 "none" 的用户导航参与,将 遍历历史步骤 allSteps[targetStepIndex] 应用到 embeddedNavigable 的结果。

    6. 如果 result 不等于 "applied",则给定 controlledframeresultPromisefalse解决嵌入者 promise

    7. 否则,给定 controlledframeresultPromisetrue解决嵌入者 promise

canGoBack() 方法步骤为:
  1. result一个新的 promise

  2. controlledframethis

  3. embeddedNavigablecontrolledframe嵌入的 navigable

  4. 如果 embeddedNavigable 为 null,则用 false 解决 result 并返回 result

  5. embeddedNavigable节点文档相关全局对象导航和遍历任务源排队一个全局任务,它将运行以下步骤:

    1. 如果 embeddedNavigable当前会话历史步骤 > 0, 则令 canGoBacktrue,否则为 false

    2. 给定 controlledframeresultcanGoBack解决嵌入者 promise

  6. 返回 result

canGoForward() 方法步骤为:
  1. result一个新的 promise

  2. controlledframethis

  3. embeddedNavigablecontrolledframe嵌入的 navigable

  4. 如果 embeddedNavigable 为 null,则用 false 解决 result 并返回 result

  5. embeddedNavigable节点文档相关全局对象导航和遍历任务源排队一个全局任务,它将运行以下步骤:

    1. stepembeddedNavigable当前会话历史步骤

    2. steps 为给定 embeddedNavigable获取所有已使用历史步骤 的结果。

    3. 如果 step + 1 < steps大小, 则令 canGoForwardtrue,否则为 false

    4. 给定 controlledframeresultcanGoForward解决嵌入者 promise

  6. 返回 result

back() 方法步骤为:
  1. 返回给定 this 和 -1,增量遍历嵌入的 navigable 的历史的结果。

forward() 方法步骤 为:
  1. 返回给定 this 和 1,增量遍历嵌入的 navigable 的历史的结果。

go(relativeIndex) 方法步骤为:
  1. 返回给定 thisrelativeIndex增量遍历嵌入的 navigable 的历史的结果。

reload() 步骤为:
  1. embeddedNavigablethis嵌入的 navigable

  2. 如果 embeddedNavigable 为 null,则返回。

  3. embeddedNavigable节点文档相关全局对象导航和遍历任务源排队一个全局任务,它将给定 "none" 的 用户导航参与重新加载 embeddedNavigable

stop() 步骤为:
  1. embeddedNavigablethis嵌入的 navigable

  2. 如果 embeddedNavigable 为 null,则返回。

  3. embeddedNavigable节点文档相关全局对象导航和遍历任务源排队一个全局任务,它将停止加载 embeddedNavigable

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

一个 DOMString列表, 其中包含将被注入到文档中的 JavaScript。

css

一个 DOMString列表, 其中包含将被注入到 文档中的 CSS。

urlPatterns

一个 URLPattern列表

注:如果文档的 URL 匹配这些模式中的任意一个,则内容可能会被注入到该文档中。

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活动文档相关设置对象执行的。

  1. 如果 urlString 不是有效 URL 字符串,则:

    1. 给定 0、false 和 "",运行 completionSteps

    2. 返回。

  2. request 为一个具有以下字段的新请求

    URL

    给定 urlStringcontrolledframe节点文档解析 URL的结果。

    method

    "GET"

    destination

    如果 isCsstrue,则为 "style",否则为 "script"

    client

    controlledframe相关设置对象

    mode

    "cors"

  3. 获取 request,并将 processResponseConsumeBody 设置为以下步骤,给定一个 响应 response 和一个 null、failure 或 字节序列 contents

    1. 如果 response状态不是 200,或 contents 为 null 或 failure,则给定 0、false 和 "" 运行 completionSteps

    2. 否则,给定 indextruecontents 运行 completionSteps

验证并解析 ContentScriptDetails, 给定一个 controlledframe controlledframe 和一个 ContentScriptDetails details,运行以下步骤:
  1. result一个新的 promise

  2. 如果 details["js"] 和 details["css"] 均已定义,或均 未定义,则用 TypeError 拒绝 result,并返回它。

  3. 如果 details["urlPatterns"] 为, 则用 TypeError 拒绝 result,并返回它。

  4. isCss 为一个布尔值,如果 details["css"] 已定义,则等于 true,否则等于 false

  5. 如果 isCsstruedetails["runAt"] 不等于 "document-start", 则用 TypeError 拒绝 result,并返回它。

  6. 如果 isCsstrue,则令 injectionItemsdetails["css"], 否则为 details["js"]。

  7. 如果 injectionItems["code"] 和 injectionItems["files"] 均已定义,或均 未定义,则用 TypeError 拒绝 result,并返回它。

  8. 返回 result,并并行运行剩余步骤。

  9. config 为一个新的内容脚本配置,具有以下值:

    pendingFetchCount

    0

    urlPatterns

    «»

    excludeURLPatterns

    «»

    allFrames

    如果已定义,则为 details["allFrames"], 否则为 false

    matchAboutBlank

    如果已定义,则为 details["matchAboutBlank"], 否则为 false

    runAt

    如果已定义,则为 details["runAt"], 否则为 document-idle

  10. 对于 details["urlPatterns"] 中的每个 urlPattern

    1. 如果 urlPattern 是一个 URLPattern, 则将 urlPattern 追加configurlPatterns

    2. 否则,给定 urlPattern,将一个新的 URLPattern 追加configurlPatterns

  11. 如果 details["excludeURLPatterns"] 已定义, 则:

    1. 对于 details["excludeURLPatterns"] 中的每个 urlPattern

      1. 如果 urlPattern 是一个 URLPattern, 则将 urlPattern 追加configexcludeURLPatterns

      2. 否则,给定 urlPattern,将一个新的 URLPattern 追加configexcludeURLPatterns

  12. completionSteps 为以下算法,其接受一个 long index、一个 布尔值 success 和一个 DOMString source

    1. 如果 successfalse,则给定 controlledframeresultTypeError拒绝嵌入者 promise,并中止 这些步骤。

    2. 如果 isCss,则:

      1. configcss[index] 设置为 source

    3. 否则:

      1. configjs[index] 设置为 source

    4. 递减 configpendingFetchCount

    5. 如果 configpendingFetchCount 大于 0,则返回。

    6. controlledframe内容脚本 映射[details[name]] 设置为 config

    7. 给定 controlledframeresult解决嵌入者 promise

  13. 如果 injectionItems["code"] 已定义,则:

    1. 给定 0、trueinjectionItems ["code"],运行 completionSteps

  14. 否则:

    1. 如果 injectionItems["files"] 为,则 给定 controlledframeresultTypeError拒绝嵌入者 promise, 并中止这些步骤。

    2. 对于 injectionItems ["files"] 的每个 urlString

      1. 给定 controlledframeurlStringisCssconfigpendingFetchCountcompletionSteps,运行获取注入项

      2. 递增 configpendingFetchCount

要确定一个内容脚本配置是否适用于某个文档, 给定一个内容 脚本配置 config、一个 URL url 和一个 布尔值 isTopLevel,运行以下步骤:
  1. 如果 isTopLevelfalse,且 configallFramesfalse,则 返回 false

  2. 如果 url 匹配 about:blank,且 configmatchAboutBlankfalse,则返回 false

  3. urlString 序列化 url 的结果。

  4. matchfalse

  5. 对于 configurlPatterns每个 pattern

    1. 如果 urlString 匹配 URLPattern pattern,则将 match 设置为 true

  6. 对于 configexcludeURLPatterns每个 pattern

    1. 如果 urlString 匹配 URLPattern pattern,则将 match 设置为 false

  7. 返回 match

将内容脚本注入到文档中,给定一个 Document document,以及一个 RunAt currentPhase,运行以下步骤:
  1. embeddedNavigabledocument节点 navigabletraversable navigable

  2. 如果 embeddedNavigable 为 null,或其 controlledFrameEmbedderParent 为 null,则 返回。

  3. controlledframeembeddedNavigablecontrolledFrameEmbedderParent

  4. urldocumentURL

  5. 如果 document节点 navigableparent 为 null,则令 isTopLeveltrue,否则为 false

  6. 对于 controlledframe内容脚本映射中的每个 config

    1. 如果给定 configurlisTopLevel,确定内容脚本配置是否适用于文档的结果等于 false,则继续

    2. 如果 currentPhase 等于 document-startconfigcss 不是, 则:

      1. 对于 configcss每个 styleSource,给定 documentstyleSource,运行将样式表注入到 文档中

    3. 否则,如果 currentPhase 等于 configrunAt,则:

      1. 对于 configjs每个 scriptSource,给定 documentscriptSource 和一个 空 算法,运行将脚本注入到 文档中

将样式表注入到文档中,给定一个 Document document 和一个 DOMString styleSource,运行以下步骤:
  1. styleSheet 为一个新的 CSS 样式表对象。

  2. 给定 styleSheetstyleSource同步替换 CSSStyleSheet 的规则

  3. document全局对象DOM 操作任务源排队一个全局任务,以给定 documentstyleSheet添加 CSS 样式表

以下算法在 Document 的 环境中执行脚本,但这不是期望的行为。目标是让该 算法在一个与 Document 环境隔离、具有不同全局对象但共享对 DOM 的访问权限的环境中执行脚本;但使用当前 HTML 规范基础设施 无法对此进行规范化。这个执行环境在 Blink 中称为 Isolated World,它使用该环境在扩展中执行 内容脚本。关于其执行模型的更多详细信息,请参见此 图示。Gecko 使用一种类似的方法,称为 Xray vision。该算法最终应描述一种可被规范化、并可由所有浏览器实现的 这种隔离的实现。

将 脚本注入到文档中,给定一个 Document document、 一个 DOMString scriptSource,以及一个接受 完成记录的算法 completionSteps,运行以下步骤:

注:执行 scriptSource 时会故意不设置 document.currentScript

  1. script 为给定 scriptSourcedocument相关设置对象documentURL,以及默认脚本获取选项创建经典脚本的结果。

  2. document全局对象DOM 操作任务源排队一个全局任务,该任务将运行以下步骤:

    1. completionRecord 为给定 script运行经典脚本 的结果。

    2. controlledframedocument节点 navigabletraversable navigablecontrolledFrameEmbedderParent

    3. controlledframe相关全局对象DOM 操作任务源排队一个全局任务,该任务将以 completionRecord 运行 completionSteps

addContentScripts(contentScriptList) 方法步骤为:
  1. 如果 contentScriptList,则返回 一个以 TypeError 拒绝新 promise

  2. promises 为空列表

  3. 对于 contentScriptList 中的每个 contentScript

    1. promise 为给定 contentScript,调用验证并解析 ContentScriptDetails的结果。

    2. promise 追加promises

  4. 返回给定 promises获取一个等待所有 promise 的 promise 的结果。

removeContentScripts(scriptNameList) 方法步骤为:
  1. result一个新的 promise

  2. controlledframethis

  3. 返回 result,并并行运行剩余步骤。

  4. 如果 scriptNameList 为 undefined,则:

    1. 清空 controlledframe内容脚本映射

  5. 否则,对于 scriptNameList每个 name

    1. 移除 controlledframe内容脚本 映射[name]。

  6. 给定 controlledframeresult解决嵌入者 promise

executeScript(details) 方法步骤为:
  1. result一个新的 promise

  2. controlledframethis

  3. 返回 result,并并行运行剩余步骤。

  4. 如果 controlledframe嵌入的 navigable为 null,则给定 controlledframeresult 和一个 TypeError拒绝嵌入者 promise,并中止这些步骤。

  5. 如果 details["code"] 和 details"[file"] 两者都已定义或两者都 未定义,则给定 controlledframeresult 和一个 TypeError拒绝嵌入者 promise, 并中止这些步骤。

  6. executionSteps 为以下算法,它接受一个 long 和 一个 DOMString布尔值 scriptString

    1. 如果 scriptString 不是 DOMString, 则给定 controlledframeresult 和一个 TypeError拒绝嵌入者 promise, 并中止这些步骤。

    2. documentcontrolledframe嵌入的 navigable活动文档

    3. 给定 documentscriptString 以及以下接受完成记录 completionRecord 的算法,将脚本注入到文档中

      1. 如果 completionRecord正常 完成,则:

        1. 给定 controlledframeresultcompletionRecord.[[Value]]解决嵌入者 promise

      2. 否则:

        1. 给定 controlledframeresultcompletionRecord.[[Value]]拒绝嵌入者 promise

  7. 如果 details["code"] 已定义,则给定 0 和 details["code"],运行 executionSteps

  8. 否则,给定 controlledframedetails["file"]、 false、0 和 executionSteps获取一个注入项

insertCSS(details) 方法步骤为:
  1. result一个新的 promise

  2. controlledframethis

  3. 返回 result,并并行运行剩余步骤。

  4. 如果 controlledframe嵌入的 navigable为 null,则 给定 controlledframeresult 和一个 TypeError拒绝嵌入者 promise, 并中止这些步骤。

  5. 如果 details["code"] 和 details["file"] 两者都已定义或两者都 未定义,则给定 controlledframeresult 和一个 TypeError拒绝嵌入者 promise, 并中止这些步骤。

  6. executionSteps 为以下算法,它接受一个 long、 一个 布尔值 success 和一个 DOMString styleString

    1. 如果 successfalse,则给定 controlledframeresult 和一个 TypeError拒绝 嵌入者 promise,并中止这些 步骤。

    2. documentcontrolledframe嵌入的 navigable活动文档

    3. 给定 documentstyleString将样式表注入到 文档中

    4. 给定 controlledframeresult解决嵌入者 promise

  7. 如果 details["code"] 已定义,则给定 0、truedetails["code"],运行 executionSteps

  8. 否则,给定 controlledframedetails["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;
};
清空一个存储瓶,给定一个存储桶 bucket、 一个存储标识符 identifier,以及一个 long since,运行 以下步骤:

注:如果可能,用户代理应仅 移除在 since 之后最后使用的数据,其中 since 表示自 纪元以来的毫秒时间戳。并非所有用户代理都会跟踪所有 浏览数据的写入或访问时间。实现应尽其所能尊重 since, 但该 API 不保证其可用性。

  1. bottlebucket[identifier]。

  2. 清空 bottle映射

  3. bottle代理映射引用集合设置为一个新的集合

clearData(options, types) 方法步骤为:
  1. resultPromise一个新的 promise

  2. controlledframethis

  3. 返回 resultPromise,并并行运行剩余步骤。

  4. clearSince 为 0。

  5. 如果 options["since"] 已定义,则将 clearSince 设置为 options|["since"]。

  6. embeddingOrigincontrolledframe相关设置对象顶级源

  7. partitioncontrolledframepartition

  8. 对于用户代理存储棚中的每个 storageKeyshelf

    1. 如果 storageKey嵌入源不等于 embeddingOrigin,或 storageKey分区不 等于 partition,则继续

    2. bucketshelf["default"]。

    3. 如果 types["fileSystems"] 为 true

      1. 给定 bucket、"fileSystem" 和 clearSince清空存储瓶

    4. 如果 types["indexedDB"] 为 true

      1. 给定 bucket、"indexedDB" 和 clearSince清空存储瓶

    5. 如果 types["localStorage"] 为 true

      1. 给定 bucket、"localStorage" 和 clearSince清空存储瓶

  9. 如果 types["cookies"]、 types["persistentCookies"], 或 types["sessionCookies"] 为 true,则:

    [COOKIES] 规范不支持通过类似存储键的机制 对 cookie 进行分区。以下步骤 会清除所有 cookie,但其意图是仅删除 由此 Controlled Frame 当前 partition 中的 Controlled Frame 内容所 创建的 cookie。

    1. 对于用户代理的 cookie 存储中的每个 cookie

      1. 如果 cookie 的 persistent-flag 已设置,则:

        1. 如果 types["cookies"] 和 types["persistentCookies"] 为 false, 则继续

      2. 否则:

        1. 如果 types["cookies"] 和 types["sessionCookies"] 为 false, 则继续

      3. 如果 cookie 的 last-access-time 表示为自 纪元以来的毫秒数小于 clearSince,则继续

      4. 用户代理的 cookie 存储中移除 cookie

  10. 如果 types["cache"] 为 true,则:

    1. 对于 用户代理管理的每个 storageKeycache[HTTP-CACHING]

      1. 如果 storageKey嵌入源不等于 embeddingOrigin,或 storageKey分区不等于 partition, 则继续

      2. 清空 cache

  11. 给定 controlledframeresultPromise解决嵌入者 promise

每个嵌入的 navigable都持有一个 muted 布尔值,默认值为 false。当 mutedtrue 时,用户代理必须 将源自嵌入的 navigable内的所有音频流静音。 muted 状态不应暴露给 嵌入的 navigable内的内容;当 mutedtrue 时,不应以任何脚本可见的方式更改音量状态,但 底层音频流不应被用户听到。

getAudioState() 方法步骤为:
  1. resultPromise一个新的 promise

  2. controlledframethis

  3. 返回 resultPromise,并并行运行剩余步骤。

  4. 如果 controlledframe嵌入的 navigable为 null,则给定 controlledframeresultPromise 和一个 TypeError拒绝嵌入者 promise,并中止这些步骤。

  5. 如果 controlledframe嵌入的 navigable内的任何内容(包括嵌套框架中的内容)当前正在 播放 音频,则令 playingAudiotrue,否则为 false

  6. 给定 controlledframeresultPromiseplayingAudio解决嵌入者 promise

isAudioMuted() 方法步骤为:
  1. resultPromise一个新的 promise

  2. controlledframethis

  3. 返回 resultPromise,并并行运行剩余步骤。

  4. 如果 controlledframe嵌入的 navigable为 null,则给定 controlledframeresultPromise 和一个 TypeError拒绝嵌入者 promise,并中止这些步骤。

  5. 给定 controlledframeresultPromise 以及 controlledframe嵌入的 navigablemuted 标志,解决嵌入者 promise

setAudioMuted(mute) 方法步骤为:
  1. 如果 this嵌入的 navigable为 null,则抛出一个 TypeError

  2. this嵌入的 navigablemuted 标志设置为 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,运行以下步骤:

  1. result 为初始设置为 1.0f 的浮点数。

  2. key 为给定与 e嵌入的 navigable活动文档当前设置对象相关联的环境获取 Controlled Frame 存储键的结果。

  3. 如果 Controlled Frame 缩放映射[key] 存在,则将 result 设置为给定键 key,从 Controlled Frame 缩放映射获取 值的结果。

  4. 返回 result

设置 按源缩放级别,给定 HTMLControlledFrameElement e 和一个浮点数 zoomLevel,运行以下步骤:

  1. key 为给定与 e嵌入的 navigable活动文档当前设置对象相关联的环境获取 Controlled Frame 存储键的结果。

  2. 给定键 key 和值 zoomLevel设置 值Controlled Frame 缩放映射

要确定给定 HTMLControlledFrameElement e 时,当前文档是否具有按源缩放 级别,运行以下步骤:

  1. key 为给定与 e嵌入的 navigable活动文档当前设置对象相关联的环境获取 Controlled Frame 存储键的结果。

  2. 如果 Controlled Frame 缩放映射[key] 存在,返回 true

  3. 返回 false

getZoomMode() 方法 步骤为:

  1. p一个新的 promise

  2. controlledframethis

  3. 返回 p,并并行运行剩余步骤。

  4. 给定 controlledframepcontrolledframezoomMode解决嵌入者 promise

setZoomMode(zoomMode) 方法步骤为:

  1. p一个新的 promise

  2. controlledframethis

  3. 返回 p,并并行运行剩余步骤。

  4. currentZoomMode 为给定 controlledframegetZoomMode 的结果。

  5. 如果 currentZoomMode 等于 zoomMode,则给定 controlledframep解决嵌入者 promise

  6. controlledframezoomMode 设置为 zoomMode

  7. 如果 zoomModeper-origin

    1. 如果给定 controlledframe当前文档具有 按源缩放级别true

      1. oldZoomFactorcontrolledframecurrentZoom

      2. controlledframecurrentZoom 设置为给定 controlledframe获取按源缩放级别 的结果。

      3. 如果 oldZoomFactor 不等于 controlledframecurrentZoom

        1. 给定 controlledframecurrentZoom将缩放级别应用controlledframe 的嵌入文档。

        2. 使用 controlledframeoldZoomFactorcontrolledframecurrentZoom触发 "zoomchange" 事件

  8. 如果 zoomModedisabled

    1. oldZoomFactorcontrolledframecurrentZoom

    2. controlledframecurrentZoom 设置为 1.0f。

    3. 如果 oldZoomFactor 不等于 controlledframecurrentZoom

      1. 给定 controlledframecurrentZoom将缩放级别应用controlledframe 的嵌入文档。

      2. 使用 controlledframeoldZoomFactorcontrolledframecurrentZoom触发 "zoomchange" 事件

  9. 给定 controlledframep解决嵌入者 promise

getZoom() 方法步骤 为:

  1. p一个新的 promise

  2. controlledframethis

  3. 返回 p,并并行运行剩余步骤。

  4. embeddedNavigablecontrolledframe嵌入的 navigable

  5. 如果 embeddedNavigable 为 null,则给定 controlledframep 和一个 TypeError拒绝嵌入者 promise,并中止这些步骤。

  6. 给定 controlledframepcontrolledframecurrentZoom解决嵌入者 promise

setZoom(zoomFactor) 方法 步骤为:

  1. p一个新的 promise

  2. controlledframethis

  3. 返回 p,并并行运行剩余步骤。

  4. embeddedNavigablecontrolledframe嵌入的 navigable

  5. 如果 embeddedNavigable 为 null,则给定 controlledframep 和一个 TypeError拒绝嵌入者 promise,并中止这些步骤。

  6. 如果 controlledframeZoomModedisabled

    1. 给定 controlledframep 和一个 TypeError拒绝嵌入者 promise, 并中止这些步骤。

  7. 如果 controlledframeZoomModeper-origin

    1. oldZoomFactorcontrolledframecurrentZoom

    2. 给定 controlledframezoomFactor设置按源缩放级别

    3. 对于用户代理的 浏览上下文组集合中的每个 浏览上下文组 group

      1. 对于 group 中的每个 顶级浏览上下文 browsingContext

        1. embeddedDocumentbrowsingContext活动文档

        2. embedderembeddedDocument节点 navigablecontrolledFrameEmbedderParent

        3. 如果 embedder 为 null,则继续

        4. 如果以下所有条件均为 true,则令 matchtrue

        5. 如果 matchtrue,则:

          1. embeddercurrentZoom 设置为 zoomFactor

          2. 给定 zoomFactor将缩放级别应用embeddedDocument

          3. 使用 embedderoldZoomFactorzoomFactor触发 "zoomchange" 事件

  8. 如果 controlledframeZoomModeper-view

    1. oldZoomFactorcontrolledframecurrentZoom

    2. controlledframecurrentZoom 设置为 zoomFactor

    3. 如果 oldZoomFactor 不等于 controlledframecurrentZoom

      1. 给定 controlledframecurrentZoom将缩放级别应用controlledframe 的嵌入文档。

      2. 使用 controlledframeoldZoomFactorcontrolledframecurrentZoom触发 "zoomchange" 事件

  9. 给定 controlledframep解决嵌入者 promise

3.6. 捕获方法

// One of |code| or |file| must be specified but not both.
dictionary ImageDetails {
  DOMString format;
  DOMString quality;
};
captureVisibleRegion(options) 方法步骤为:
  1. resultPromise一个新的 promise

  2. controlledframethis

  3. 返回 resultPromise,并并行运行剩余步骤。

  4. 如果 controlledframe嵌入的 navigable为 null,则给定 controlledframeresultPromise 和一个 TypeError拒绝嵌入者 promise,并中止这些步骤。

  5. optionsFormat 默认为 "JPEG"。

  6. optionsQuality 默认为 100。

  7. 如果 options 有字段 "format":

    1. optionsFormatoptions["format"]。

  8. 如果 optionsFormat 是无法识别的格式,则给定 controlledframeresultPromise 和一个 TypeError拒绝嵌入者 promise,并中止这些步骤。

  9. 如果 options 有字段 "quality":

    1. optionsQualityoptions["quality"]。

  10. 如果 optionsQuality 不是整数,或不在 0 到 100(含)之间, 则给定 controlledframeresultPromise 和一个 TypeError拒绝嵌入者 promise,并中止这些步骤。

  11. imageData 为一张显示嵌入内容可见区域的图像,该图像以 optionsFormat 编码,质量为 optionsQuality

    注:受支持图像格式的集合由实现定义, 但建议至少支持 "JPEG" 和 "PNG"。

  12. 给定 controlledframeresultPromise 和一个包含 imageDatadata: URL解决嵌入者 promise

print() 方法步骤为:
  1. 如果 this嵌入的 navigable为 null,则抛出一个 TypeError

  2. 为嵌入内容启动浏览器打印页面功能。

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 更改事件:

导航事件:

每个 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, 运行以下步骤:

  1. consoleMessage 为一个新的 ConsoleMessage 对象。

  2. 设置 consoleMessage 的以下字段:

    level

    logLevel

    message

    message

  3. econsoleMessage 设置为 consoleMessage

  4. target相关全局对象DOM 操作任务源排队一个全局任务,以在 target分派 e

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 都具有:

okay(response) 方法步骤为:

  1. accept 设置为 true

  2. response 设置为 response

cancel() 方法步骤为:

  1. accept 设置为 false

触发 DialogEvent e,给定 controlledframe 元素 target简单对话框类型 dialogType,以及 消息 message,运行以下步骤:

  1. 断言 e["dialogMessage"]["dialog"]["accept"] 等于 false

  2. dialogMessage 为一个新的 DialogMessage 对象。

  3. dialog 为一个新的 DialogController 对象。

  4. 设置 dialogMessage 的以下字段:

    messageType

    dialogType

    messageText

    message

    dialog

    dialog

  5. edialogMessage 设置为 dialogMessage

  6. completefalse

  7. target相关全局对象DOM 操作任务源排队一个全局任务,以运行以下 步骤:

    1. target分派 e

    2. complete 设置为 true

  8. 同步等待 completetrue

    注: 此处阻塞是有意为之,因为 由 "dialog" 事件表示的 alert、confirm 和 prompt 对话框会阻塞主线程,并且我们在这里调用的事件 处理程序会影响返回值。

  9. 返回 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) 方法步骤为:

  1. newControlledFrame嵌入的 navigable设置为 this目标 navigable

discard() 方法步骤为:

  1. 如果 this目标 navigable不是 null,则给定 this目标 navigable关闭一个顶级 traversable

触发 NewWindowEvent e, 给定 controlledframe 元素 controlledFrameUSVString urlDOMString targetnavigable targetNavigableWindowOpenDisposition windowOpenDisposition,运行以下步骤:

  1. controller 为一个新的 NewWindowController 对象。

  2. controller目标 navigable设置为 targetNavigable

  3. newWindow 为一个新的 NewWindow 对象。

  4. 设置 newWindow 的以下字段:

    window

    controller

    targetUrl

    url

    name

    target

    windowOpenDisposition

    windowOpenDisposition

  5. enewWindow 设置为 newWindow

  6. 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() 方法步骤为:

  1. allow 设置为 true

cancel() 方法步骤为:

  1. allow 设置为 false

触发 PermissionRequestEvent e,给定一个文档 embeddedDocumentcontrolledframe 元素 target、DOMString type、USVString url、一个 可选字典 options,以及一个接受 布尔值的算法 completionSteps,运行以下步骤:

  1. permissionRequest 为一个新的 PermissionRequest 对象。

  2. 如果 type 为 "media":

    1. requestController 为一个具有以下属性的新的 MediaPermissionRequestController

      url

      url

  3. 如果 type 为 "geolocation":

    1. requestController 为一个具有以下属性的新的 GeolocationPermissionRequestController

      url

      url

  4. 如果 type 为 "pointerLock":

    1. requestController 为一个具有以下属性的新的 PointerLockPermissionRequestController

      lastUnlockedBySelf

      options["lastUnlockedBySelf"]

      userGesture

      options["userGesture"]

      url

      url

  5. 如果 type 为 "download":

    1. requestController 为一个具有以下属性的新的 DownloadPermissionRequestController

      requestMethod

      options["requestMethod"]

      url

      url

  6. 如果 type 为 "filesystem":

    1. requestController 为一个具有以下属性的新的 FileSystemPermissionRequestController

      url

      url

  7. 如果 type 为 "fullscreen":

    1. requestController 为一个具有以下属性的新的 FullscreenPermissionRequestController

      origin

      url 的源

  8. 如果 type 为 "hid":

    1. requestController 为一个具有以下属性的新的 HidPermissionRequestController

      url

      url

  9. 设置 permissionRequest 的以下字段:

    request

    requestController

    permission

    type

  10. epermissionRequest 设置为 permissionRequest

  11. target相关全局对象DOM 操作任务源排队一个全局任务,以运行以下 步骤:

    1. target分派 e

    2. 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 个非负数 oldWidtholdHeightnewWidthnewHeight

  1. sizeChange 为一个新的 SizeChange 对象。

  2. 设置 sizeChange 的以下字段:

    oldWidth

    oldWidth

    oldHeight

    oldHeight

    newWidth

    newWidth

    newHeight

    newHeight

  3. esizeChange 设置为 sizeChange

  4. target相关全局对象DOM 操作任务源排队一个全局任务,以在 target分派 e

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 个 浮点数 oldZoomFactornewZoomFactor

  1. zoomChange 为一个新的 ZoomChange 对象。

  2. 设置 zoomChange 的以下字段:

    oldZoomFactor

    oldZoomFactor

    newZoomFactor

    newZoomFactor

  3. ezoomChange 设置为 zoomChange

  4. target相关全局对象DOM 操作任务源排队一个全局任务,以在 target分派 e

3.7.7. contentload

[Exposed=Window, IsolatedContext]
interface ContentLoadEvent : Event {
  constructor(DOMString type, optional EventInit eventInitDict = {});
};

触发 ContentLoadEvent e,给定 controlledframe 元素 target,运行以下步骤:

  1. target相关全局对象DOM 操作任务源排队一个全局任务,以在 target分派 e

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,运行以下步骤:

  1. info 为一个具有以下属性的新的 LoadAbortInfo

    url

    url

    isTopLevel

    isTopLevel

    code

    code

    reason

    reason

  2. eloadAbortInfo 设置为 info

  3. target相关全局对象DOM 操作任务源排队一个全局任务,以在 target分派 e

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,运行以下步骤:

  1. info 为一个具有以下属性的新的 LoadInfo

    url

    url

    isTopLevel

    isTopLevel

  2. eloadInfo 设置为 info

  3. target相关全局对象DOM 操作任务源排队一个全局任务,以在 target分派 e

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,运行以下步骤:

  1. info 为一个具有以下属性的新的 LoadInfo

    url

    url

    isTopLevel

    isTopLevel

  2. eloadInfo 设置为 info

  3. target相关全局对象DOM 操作任务源排队一个全局任务,以在 target分派 e

3.7.11. loadstop

[Exposed=Window, IsolatedContext]
interface LoadStopEvent : Event {
  constructor(DOMString type, optional LoadStopEventInit eventInitDict = {});
};

dictionary LoadStopEventInit: EventInit {
};

触发 LoadStopEvent e ,给定 controlledframe 元素 target,运行以下步骤:

  1. target相关全局对象DOM 操作任务源排队一个全局任务,以在 target分派 e

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,运行 以下步骤:

  1. info 为一个具有以下属性的新的 LoadInfo

    oldUrl

    给定 oldUrl序列化 URL的结果

    newUrl

    给定 newUrl序列化 URL的结果

    isTopLevel

    isTopLevel

  2. eloadRedirectInfo 设置为 info

  3. target相关全局对象DOM 操作任务源排队一个全局任务,以在 target分派 e

3.7.13. 猴子补丁

3.7.13.1. [HTML]

对于 alert

  1. message 设置为可选地截断 message 的结果。

  2. controlledFrameEmbedderParentwindownavigablecontrolledFrameEmbedderParent
  3. 如果 controlledFrameEmbedderParent 是一个 HTMLControlledFrameElement, 则使用 controlledFrameEmbedderParent、"alert" 和 message 触发 "dialog" 事件,并返回。

对于 confirm

  1. message 设置为可选地截断 message 的结果。

  2. controlledFrameEmbedderParentwindownavigablecontrolledFrameEmbedderParent
  3. 如果 controlledFrameEmbedderParent 是一个 HTMLControlledFrameElement, 则返回使用 controlledFrameEmbedderParent、"confirm" 和 message 触发 "dialog" 事件的结果。

对于 prompt

  1. default 设置为可选地截断 default 的结果。

  2. controlledFrameEmbedderParentwindownavigablecontrolledFrameEmbedderParent
  3. 如果 controlledFrameEmbedderParent 是一个 HTMLControlledFrameElement, 则:
    1. acceptresponse 为使用 controlledFrameEmbedderParent、"prompt" 和 message 触发 "dialog" 事件的结果。
    2. 如果 accept 等于 false,返回 null。
    3. 返回 response

对于 window open steps

  1. windowOpenDisposition 为 "ignore"。
  2. controlledFrameEmbedderParentsourceDocument节点 navigablecontrolledFrameEmbedderParent

...

14. 如果 targetNavigable 为 null,则返回 null。
  1. 如果 targetNavigable 为 null:
    1. 如果 controlledFrameEmbedderParent 不是 null:
      1. 使用 controlledFrameEmbedderParenturltargettargetNavigablewindowOpenDisposition触发 "newwindow" 事件
    2. 返回 null。
  2. 如果 windowType 为 "new and unrestricted" 或 "new with no opener", 则:

    1. windowOpenDisposition 设置为以下之一: "new_background_tab"、 "new_foreground_tab", 或 "new_window"。

    注:该值取决于用户代理的行为支持 和用户设置。

    1. targetNavigable 的活动浏览上下文的 is popup 设置为给定 tokenizedFeatures,检查是否请求了弹出窗口的结果。

    2. 如果 targetNavigable活动浏览上下文is popuptrue,则将 windowOpenDisposition 设置为 "new_popup"。

    ...

  3. 否则:

    1. windowOpenDisposition 设置为 "current_tab"。

    ...

注:步骤 15 和 16 也会导航 targetNavigable;在导航期间, windowOpenDisposition 也可能会被更新。例如,如果导航被 阻止,windowOpenDisposition 可能会被设置为 "ignore"。 如果导航响应导致 下载,则 windowOpenDisposition 可能会被设置为 "save_to_disk"。

  1. 如果 controlledFrameEmbedderParent 不是 null:
    1. 使用 controlledFrameEmbedderParenturltargettargetNavigablewindowOpenDisposition触发 "newwindow" 事件

对于完全完成加载

  1. 否则,如果 container 非 null,则给定 container,在 DOM 操作任务源上排队一个元素任务, 以在 container 处触发名为 load 的事件。

  2. controlledFrameEmbedderParentdocument节点 navigablecontrolledFrameEmbedderParent
  3. 如果 controlledFrameEmbedderParentHTMLControlledFrameElement, 则使用 controlledFrameEmbedderParent 触发 "contentload" 事件

用于 loadstart、loadabort 和 loadcommit 的猴子补丁如下所示:

  1. loadstart -> 在导航入口点:普通导航、重新加载、遍历。

  2. loadcommit -> 在通用导航完成点。

  3. loadabort -> 在 loadstart 和 loadcommit 之间算法的每个提前退出点。

对于这些事件中的每一个,检查 navigable顶级 traversable是否具有 HTMLControlledFrameElement 类型的 controlledFrameEmbedderParent, 如果是,则使用输入参数触发对应事件。

3.7.13.2. [FETCH]

对于 HTTP fetch(loadredirect):

  1. 如果 internalResponse 的状态是重定向状态:

    1. 如果 requestwindow window 是一个 环境设置对象,其全局对象Window 对象:
      1. currentNavigablewindow 的关联 navigable
      2. controlledFrameEmbedderParentcurrentNavigable顶级 traversablecontrolledFrameEmbedderParent
      3. 如果 controlledFrameEmbedderParent 是一个 HTMLControlledFrameElement

        1. oldUrlrequest 的关联 URL

        1. newUrlresponse位置 URL

        1. isTopLevelfalse;如果 currentNavigable 具有 null parent,则将 isTopLevel 设置为 true

        1. 使用 controlledFrameEmbedderParentoldUrlnewUrlisTopLevel触发 "loadredirect" 事件

3.7.13.3. [Permissions]

定义新算法:

要确定一个 Document document 是否 被嵌入者允许使用某项 权限,给定 DOMString permission、一个可选字典 options,以及一个接受 布尔值的算法 completionSteps,运行以下步骤:

  1. controlledFrameEmbedderParentdocument节点 navigablecontrolledFrameEmbedderParent

  2. 如果 controlledFrameEmbedderParent 不是 HTMLControlledFrameElement, 返回 true

  3. 使用 documentcontrolledFrameEmbedderParentpermissiondocumentURLoptionscompletionSteps触发 "permissionrequest" 事件

对于请求位置(geolocation):

  1. 如果 document 不被允许使用 "geolocation" 特性:

    1. 如果传入了 watchId,则从 watchIDs 中移除 watchId。

    2. 使用 errorCallback 和 PERMISSION_DENIED 回调错误。

    3. 终止此算法。

  2. blockedByEmbedderfalse
  3. 检查 document 是否被嵌入者允许使用 "geolocation" 特性,给定一个算法,该算法将其 布尔值参数赋给 blockedByEmbedder 并继续执行这些步骤的剩余部分。
  4. 如果 blockedByEmbeddertrue,则:
    1. 如果传入了 watchId,则从 watchIDs 中移除 watchId。
    2. 使用 errorCallback 和 PERMISSION_DENIED 回调错误。
    3. 终止此算法。
  5. controlledFrameEmbedderParentdocument节点 navigablecontrolledFrameEmbedderParent
  6. 如果 controlledFrameEmbedderParentHTMLControlledFrameElement
    1. nodeDocumentcontrolledFrameEmbedderParent节点文档

    2. 如果 nodeDocument 为 null:
      1. 如果传入了 watchId,则从 watchIDs 中移除 watchId。
      2. 使用 errorCallback 和 PERMISSION_DENIED 回调错误。
      3. 终止此算法。
    3. embedderNavigatornodeDocument全局对象关联 Navigator
    4. embedderGeolocationembedderNavigatorgeolocation
    5. 返回使用 embedderGeolocationsuccessCallbackerrorCallbackoptionswhatchId 请求位置的结果。

注:其他权限也会以类似于 geolocation 的方式打上猴子补丁。 但为了简洁起见,本文档省略了 细节。

3.7.13.4. [Console]

对于 Logger

  1. 否则,执行 Printer(logLevel, Formatter(args))。

  2. 使用 logLevelFormatter(args),触发 "consolemessage" 事件

注:Console 默认不与 document 关联,因此我们无法跟踪关联的 HTMLControlledFrameElement

3.8. 与其他规范的集成

本规范将对一些规范作出修改,以满足 Controlled Frame 的需求。

3.8.1. 猴子补丁

3.8.1.1. [HTML]

每个 navigable 都具有:

给定一个 navigable navigable 和一个可选的 navigable-or-null parent(默认为 null),初始化 navigable 算法 被猴子补丁如下:

  1. navigableparent 设置为 parent

  2. 如果 parent 不是 null(navigable 不是 顶级 traversable),则:
    1. topLevelTraversablenavigable 作为其后代的顶级 traversable
    2. navigableframeId 设置为 topLevelTraversablenext frameId
    3. 递增 topLevelTraversablenext frameId

用于 Document documentreadinessValue更新当前文档就绪状态算法被猴子补丁如下:

  1. runAt 为将以下映射应用于 readinessValue 的结果:
    "loading"

    "document-start"

    "interactive"

    "document-end"

    "complete"

    "document-idle"

  2. 给定 documentrunAt将内容脚本注入到文档中
  3. document触发一个事件,其名称为 readystatechange

3.8.1.2. [FETCH]

确定网络分区键算法被猴子扩展为 要求对源自 Controlled Frame 的嵌入的 navigable的网络请求 进行双键化。

要确定网络分区键,给定一个环境 environment
  1. topLevelSite 为给定 topLevelOrigin,获取站点的结果。

  2. secondKey 为 null 或一个实现定义的

  3. controlledFrameEmbedderParent 为给定 environment获取环境的 controlledFrameEmbedderParent的结果。
  4. 如果 controlledFrameEmbedderParent 不是 null,则将 secondKey 设置为一个元组,该元组由 controlledFrameEmbedderParent相关设置对象顶级源,以及 controlledFrameEmbedderParentpartition组成。
  5. 返回 (topLevelSite, secondKey)。

3.8.1.3. [STORAGE]

存储键被重新定义如下:

存储键是一个元组, 由 嵌入源(一个或 null)、一个 分区(一个 DOMString 或 null),以及一个 (一个)组成。

注:将来一旦存储分区被完整规范化, 该定义将需要扩展为除之外,还包括嵌入内容的 顶级源。

注:Controlled Frame 数据是用拥有 Controlled Frame 元素的文档的源进行三重键化,而不是用拥有它的顶级文档的源。

为非存储目的获取存储键算法被扩展为 要求对属于 controlledframe嵌入的 navigable 的所有存储进行双键化。

为非存储目的获取存储键,给定一个环境 environment,运行以下步骤:
  1. 如果 environment 是一个环境设置对象,则令 originenvironment;否则为 environment创建 URL

  2. 返回一个由 origin 组成的元组
  3. topLevelOriginpartition 为 null。
  4. controlledFrameEmbedderParent 为给定 environment获取环境的 controlledFrameEmbedderParent的结果。
  5. 如果 controlledFrameEmbedderParent 不是 null,则:
    1. topLevelOrigin 设置为 controlledFrameEmbedderParent相关设置对象顶级源
    2. partition 设置为 controlledFrameEmbedderParentpartition
  6. 返回一个由 topLevelOriginpartitionorigin 组成的元组
获取一个环境controlledFrameEmbedderParent,给定 一个环境 environment,运行以下步骤:
  1. 如果 environment 是一个环境设置对象,其 全局对象是一个 Window 对象,则:

    此算法 不适用于 Shared 或 Service Workers,因为 controlledFrameEmbedderParent 仅 定义在 navigable 上,并且 并不总是可以从非 Window 环境到达一个 navigable

    1. navigableenvironment全局对象navigable

    2. topnavigable顶级 traversable

    3. 如果 topcontrolledFrameEmbedderParent 不是 null,则返回 topcontrolledFrameEmbedderParent

  2. 返回 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 includeHeaders = "none";
  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 都有一个关联的:

注:拦截器将由 controlledframe 元素事件循环上的任务写入,但会在 fetch 期间并行读取。

在分派 WebRequest 事件之前,会创建 适用的 WebRequestInterceptors 的快照。 在处理事件时注册到 WebRequestInterceptor 上的事件监听器不会针对该事件触发。

每个 WebRequestInterceptor 都有一个关联的:

每个 UploadData 都有一个关联的:

每个 RequestBody 都有一个关联的:

每个 WebRequestRequest 都有一个关联的:

每个 AuthChallenger 都有一个关联的:

每个 WebRequestAuthDetails 都有一个关联的:

每个 WebRequestResponse 都有一个关联的:

每个 WebRequestEvent 都有一个关联的:

每个 WebRequestAuthRequiredEvent 都有一个关联的:

每个 WebRequestBeforeRedirectEvent 都有一个关联的:

每个 WebRequestCompletedEvent 都有一个关联的:

每个 WebRequestErrorOccurredEvent 都有一个关联的:

每个 WebRequestHeadersReceivedEvent 都有一个关联的:

每个 WebRequestResponseStartedEvent 都有一个关联的:

createWebRequestInterceptor(options) 方法步骤为:
  1. interceptor 为一个新的 WebRequestInterceptor 对象。

  2. interceptor 上设置以下字段:

    resourceTypes

    options["resourceTypes"]

    blocking

    options["blocking"]

    includeRequestBody

    options["includeRequestBody"]

    includeHeaders

    options["includeHeaders"]

    securityInfo

    options["securityInfo"]

    securityInfoRawDer

    options["securityInfoRawDer"]

  3. 对于 options["urlPatterns"] 中的每个 urlPattern

    1. 如果 urlPattern 是一个 URLPattern, 则将 urlPattern 追加interceptorurlPatterns

    2. 否则,给定 urlPattern,将一个新的 URLPattern 追加interceptorurlPatterns

  4. interceptor 追加this拦截器

  5. 返回 interceptor

要获取一个请求 request适用的 WebRequestInterceptor, 运行以下步骤:
  1. clientrequest客户端

  2. 如果 client 为 null,则返回一个空列表false

  3. window 为给定 client环境设置对象的所属 Window

  4. 如果 window 为 null,则返回一个空列表false

  5. navigablewindownavigable

  6. 如果 navigable 或其 controlledFrameEmbedderParent 为 null,则返回一个空列表false

  7. controlledFramenavigablecontrolledFrameEmbedderParent

  8. applicableInterceptors 为空列表

  9. 对于 controlledFramerequest拦截器中的每个 interceptor

    1. 如果 request 不应被 interceptor 拦截, 则继续

    2. interceptor 追加applicableInterceptors

  10. 返回 applicableInterceptors

要确定一个请求 request 是否应被一个 WebRequestInterceptor 拦截, 运行以下步骤:
  1. typesinterceptorresourceTypes

  2. 如果 types 不是, 且 types包含给定 request 调用获取请求的 ResourceType的结果,则返回 false

  3. urlPatternsinterceptorurlPatterns

  4. 对于 urlPatterns 中的每个 urlPattern

    1. 如果 requestURL 给定 urlPattern 匹配一个 URLPattern,则返回 true

  5. 返回 false

要获取一个环境设置对象所属 Window, 给定一个环境设置对象 environment,运行 以下步骤:
  1. globalenvironment全局对象

  2. 如果 global 是一个 Window 对象,则返回 global

  3. 如果 global 是一个 DedicatedWorkerGlobalScope 对象,则:

    1. ownerglobal

    2. owner 是一个 DedicatedWorkerGlobalScope 对象时:

      1. ownerowner所有者集合[0]。

    3. 如果 owner 是一个 Document 对象,则返回 owner相关全局对象

  4. 返回 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 都有一个关联的:

WebRequestAuthRequiredEventsetCredentials(credentials, options) 方法步骤为:
  1. thisauthCredentials 设置为 credentials

  2. thisoptions 设置为 options

WebRequestAuthRequiredEventpreventDefault() 方法步骤为将 thiscancel 设置为 true

每个 WebRequestBeforeRequestEvent 都有一个关联的:

WebRequestBeforeRequestEventredirect(redirectURL) 方法步骤为将 thisredirectURL 设置为 redirectURL
WebRequestBeforeRequestEventpreventDefault() 方法步骤为将 thiscancel 设置为 true

每个 WebRequestBeforeSendHeadersEvent 都有一个关联的:

WebRequestBeforeSendHeadersEventsetRequestHeaders(requestHeaders) 方法步骤为将 thisrequestHeaders 设置为 requestHeaders
WebRequestBeforeSendHeadersEventpreventDefault() 方法步骤为将 thiscancel 设置为 true

每个 WebRequestHeadersReceivedEvent 都有一个关联的:

WebRequestHeadersReceivedEventredirect(redirectURL) 方法步骤为将 thisredirectURL 设置为 redirectURL
WebRequestHeadersReceivedEventsetResponseHeaders(responseHeaders) 方法步骤为将 thisresponseHeaders 设置为 responseHeaders
WebRequestHeadersReceivedEventpreventDefault() 方法步骤为将 thiscancel 设置为 true

WebRequestEvent 结果是一个具有以下 结构

cancel

一个布尔值,初始为 false

redirectURL

一个 USVString, 初始为 ""

authCredentials

一个 WebRequestAuthCredentials 或 null,初始为 null

requestHeaders

一个标头列表,初始为 «»

responseHeaders

一个标头列表,初始为 «»

处理 beforeRequest 事件,给定一个请求 request, 运行以下步骤:
  1. interceptors 为获取 request适用的 WebRequestInterceptors的结果。

  2. result 为一个 WebRequestEvent 结果

  3. pendingHandlerCount 为 0。

  4. controlledFrameEmbedderGlobal 为给定 request客户端获取环境的 controlledFrameEmbedderParent的结果的相关全局对象

  5. 如果 controlledFrameEmbedderGlobal 为 null,则返回。

  6. 对于 interceptors 中的每个 interceptor

    1. 如果 interceptorblockingtrue, 则递增 pendingHandlerCount

    2. controlledFrameEmbedderGlobalDOM 操作任务源排队一个全局任务,该任务将运行以下步骤:

      1. event 为一个新的、名为 beforerequestWebRequestBeforeRequestEvent

      2. 给定 eventrequest 和 "none",填充 WebRequestEvent

      3. 如果 interceptorincludeRequestBodytrue,且 request主体不是 null,则:

        1. requestBody 为一个新的 RequestBody

        2. bodyrequest主体

          TODO:如果 body存在,则对其进行序列化。

        3. body切换:

          字节序列

          将一个新的 UploadData 追加requestBodyraw,其 bytes 等于已序列化的 body

          Blob

          将一个新的 UploadData 追加requestBodyraw,其 bytes 等于已序列化的 body

          FormData
          1. formData 为 «[]»。

          2. 对于 body条目 列表中的每个 entry

            1. entry[1] 切换:

            File

            将一个新的 UploadData 追加requestBodyraw,其 file 等于 entry[1] 的 name

            USVString
            1. 如果 formData[entry[0]] 不存在,则将 formData[entry[0]] 设置为空列表

            2. entry[1] 追加formData[entry[0]]。

          3. requestBodyformData 设置为 formData

        4. eventrequestbody 设置为 requestBody

      4. event 分派interceptor

      5. 如果 eventcanceltrue, 则将 resultcancel 设置为 true

      6. 如果 eventredirectURL 不为 null,且 resultredirectURL 为 "", 则将 resultredirectURL 设置为 eventredirectURL

      7. 如果 interceptorblockingtrue, 则递减 pendingHandlerCount

  7. 如果 pendingHandlerCount > 0,则并行等待 pendingHandlerCount 等于 0,然后排队一个全局任务,该任务将在 request客户端全局对象网络任务源,或这些步骤最初被调用所在的 并行上下文上继续运行此算法的剩余步骤, 具体取决于这些步骤在进入并行之前是如何运行的。

  8. 返回 result

处理 beforeSendHeaders 事件,给定一个请求 request, 运行以下步骤:
  1. interceptors 为获取 request适用的 WebRequestInterceptors的结果。

  2. result 为一个 WebRequestEvent 结果

  3. pendingHandlerCount 为 0。

  4. controlledFrameEmbedderGlobal 为给定 request客户端获取环境的 controlledFrameEmbedderParent的结果的相关全局对象

  5. 如果 controlledFrameEmbedderGlobal 为 null,则返回。

  6. 对于 interceptors 中的每个 interceptor

    1. 如果 interceptorblockingtrue, 则递增 pendingHandlerCount

    2. controlledFrameEmbedderGlobalDOM 操作任务源排队一个全局任务,该任务将运行以下步骤:

      1. event 为一个新的、名为 beforesendheadersWebRequestBeforeSendHeadersEvent

      2. 给定 eventrequest,以及 interceptorincludeHeaders填充 WebRequestEvent

      3. event 分派interceptor

      4. 如果 eventcanceltrue, 则将 resultcancel 设置为 true

      5. 如果 eventrequestHeaders 不为 null,则:

        1. 如果 resultrequestHeaders 为 null,则将其设置为一个新的 Headers

        2. 对于 eventrequestHeaders 中的每个 header

          1. header 追加resultrequestHeaders

      6. 如果 interceptorblockingtrue, 则递减 pendingHandlerCount

  7. 如果 pendingHandlerCount > 0,则并行等待 pendingHandlerCount 等于 0,然后排队一个全局任务,该任务将在 request客户端全局对象网络任务源,或这些步骤最初被调用所在的 并行上下文上继续运行此算法的剩余步骤, 具体取决于这些步骤在进入并行之前是如何运行的。

  8. 返回 result

处理 sendHeaders 事件,给定一个请求 request, 运行以下步骤:
  1. interceptors 为获取 request适用的 WebRequestInterceptors的结果。

  2. controlledFrameEmbedderGlobal 为给定 request客户端获取环境的 controlledFrameEmbedderParent的结果的相关全局对象

  3. 如果 controlledFrameEmbedderGlobal 为 null,则返回。

  4. 对于 interceptors 中的每个 interceptor

    1. controlledFrameEmbedderGlobalDOM 操作任务源排队一个全局任务,该任务将运行以下步骤:

      1. event 为一个新的、名为 sendheadersWebRequestSendHeadersEvent

      2. 给定 eventrequest,以及 interceptorincludeHeaders填充 WebRequestEvent

      3. event 分派interceptor

处理 headersReceived 事件,给定一个请求 request 和一个响应 response,运行以下步骤:
  1. interceptors 为获取 request适用的 WebRequestInterceptors的结果。

  2. result 为一个 WebRequestEvent 结果

  3. pendingHandlerCountinterceptor大小

  4. controlledFrameEmbedderGlobal 为给定 request客户端获取环境的 controlledFrameEmbedderParent的结果的相关全局对象

  5. 如果 controlledFrameEmbedderGlobal 为 null,则返回。

  6. 对于 interceptors 中的每个 interceptor

    1. 如果 interceptorblockingtrue, 则递增 pendingHandlerCount

    2. controlledFrameEmbedderGlobalDOM 操作任务源排队一个全局任务,该任务将运行以下步骤:

      1. event 为一个新的、名为 headersreceivedWebRequestHeadersReceivedEvent

      2. 给定 eventrequest 和 "none", 填充 WebRequestEvent

      3. eventresponse 设置为给定 requestresponse,以及 interceptorincludeHeaders创建 WebRequestResponse 对象的结果。

      4. 如果 interceptorsecurityInfotrue,或 interceptorsecurityInfoRawDertrue,则:

        1. info 为给定 responseinterceptorsecurityInfoRawDer获取 安全信息的结果。

        2. eventsecurityInfo 设置为 info

      5. event 分派interceptor

      6. 如果 eventcanceltrue, 则将 resultcancel 设置为 true

      7. 如果 eventredirectURL 不为 null,且 resultredirectURL 为 "", 则将 resultredirectURL 设置为 eventredirectURL

      8. 如果 eventresponseHeaders 不为 null,则:

        1. 如果 resultresponseHeaders 为 null,则将其设置为一个新的 Headers

        2. 对于 eventresponseHeaders 中的每个 header

          1. header 追加resultresponseHeaders

      9. 如果 interceptorblockingtrue, 则递减 pendingHandlerCount

  7. 如果 pendingHandlerCount > 0,则并行等待 pendingHandlerCount 等于 0,然后排队一个全局任务,该任务将在 request客户端全局对象网络任务源,或这些步骤最初被调用所在的 并行上下文上继续运行此算法的剩余步骤, 具体取决于这些步骤在进入并行之前是如何运行的。

  8. 返回 result

处理 authRequired 事件,给定一个请求 request 和一个响应 response,运行以下步骤:
  1. challenger 为一个新的 AuthChallenger, 其 hostport 等于 responseURL主机端口

  2. 如果 response状态为 401,则:

    1. isProxyfalse

    2. scheme 为来自 responseWWW-Authenticate 标头的 scheme, 按 [HTML] 规范中定义的方式解析;如果该标头 缺失或无效,则为 null。

    3. realm 为来自 responseWWW-Authenticate 标头的 realm, 按 [HTML] 规范中定义的方式解析。

  3. 否则:

    1. isProxytrue

    2. scheme 为来自 responseProxy-Authenticate 标头的 scheme,按 [HTML] 规范中定义的方式解析;如果 该标头缺失或无效,则为 null。

    3. realm 为来自 responseProxy-Authenticate 标头的 realm, 按 [HTML] 规范中定义的方式解析。

  4. 如果 scheme 为 null,则返回 null。

  5. interceptors 为获取 request适用的 WebRequestInterceptors的结果。

  6. result 为一个 WebRequestEvent 结果

  7. pendingHandlerCount 为 0。

  8. controlledFrameEmbedderGlobal 为给定 request客户端获取环境的 controlledFrameEmbedderParent的结果的相关全局对象

  9. 如果 controlledFrameEmbedderGlobal 为 null,则返回。

  10. 对于 interceptors 中的每个 interceptor

    1. 如果 interceptorblockingtrue, 则递增 pendingHandlerCount

    2. controlledFrameEmbedderGlobalDOM 操作任务源排队一个全局任务,该任务将运行以下步骤:

      1. event 为一个新的、名为 authrequiredWebRequestAuthRequiredEvent

      2. 给定 eventrequest 和 "none", 填充 WebRequestEvent

      3. eventresponse 设置为给定 requestresponse,以及 interceptorincludeHeaders创建 WebRequestResponse 对象的结果。

      4. eventresponseauth 设置为一个新的 WebRequestAuthDetails, 其 challengerisProxyschemerealm 字段的值 分别为 challengerisProxyschemerealm

      5. event 分派interceptor

      6. credentialseventauthCredentials

      7. 如果 eventcanceltrue, 则将 resultcancel 设置为 true

      8. 否则,如果 credentials 是一个 Promise, 则:

        1. signaleventoptions["signal"]。

        2. donefalse

        3. 如果 signal 是一个 AbortSignal, 则向 signal 添加 以下中止算法:

          1. resultcancel 设置为 true

          2. done 设置为 true

        4. credentials 兑现时,运行以下接收 resolvedValue 的步骤:

          1. 如果 resolvedValue 是一个字典,且包含 两个等于 "username" 和 "password" 的,并且 resultauthCredentials 为 undefined,则将 resultauthCredentials 设置为 resolvedValue

          2. done 设置为 true

        5. credentials 拒绝时,运行以下步骤:

          1. done 设置为 true

          注:被拒绝的 promise 不会取消请求,但不会向服务器 提供凭据。

        6. 并行等待 done 等于 true,然后在 controlledFrameEmbedderGlobalDOM 操作任务 源排队一个全局任务,该任务将继续运行 此算法的剩余步骤。

      9. 如果 interceptorblockingtrue, 则递减 pendingHandlerCount

  11. 如果 pendingHandlerCount > 0,则并行等待 pendingHandlerCount 等于 0,然后排队一个全局任务,该任务将在 request客户端全局对象网络任务源,或这些步骤最初被调用所在的 并行上下文上继续运行此算法的剩余步骤, 具体取决于这些步骤在进入并行之前是如何运行的。

  12. 返回 result

处理 beforeRedirect 事件,给定一个请求 request 和一个响应 response,运行以下步骤:
  1. interceptors 为获取 request适用的 WebRequestInterceptors的结果。

  2. controlledFrameEmbedderGlobal 为给定 request客户端获取环境的 controlledFrameEmbedderParent的结果的相关全局对象

  3. 如果 controlledFrameEmbedderGlobal 为 null,则返回。

  4. 对于 interceptors 中的每个 interceptor

    1. controlledFrameEmbedderGlobalDOM 操作任务源排队一个全局任务,该任务将运行以下步骤:

      1. event 为一个新的、名为 beforeredirectWebRequestBeforeRedirectEvent

      2. 给定 eventrequest 和 "none", 填充 WebRequestEvent

      3. eventresponse 设置为给定 requestresponse,以及 interceptorincludeHeaders创建 WebRequestResponse 对象的结果。

      4. internalResponseresponse,如果 response 不是过滤后的响应;否则为 response内部响应

      5. eventresponseredirectURL 设置为给定 request当前 URL片段internalResponse位置 URL

      6. event 分派interceptor

处理 responseStarted 事件,给定一个请求 request 和一个响应 response,运行以下步骤:
  1. interceptors 为获取 request适用的 WebRequestInterceptors的结果。

  2. controlledFrameEmbedderGlobal 为给定 request客户端获取环境的 controlledFrameEmbedderParent的结果的相关全局对象

  3. 如果 controlledFrameEmbedderGlobal 为 null,则返回。

  4. 对于 interceptors 中的每个 interceptor

    1. controlledFrameEmbedderGlobalDOM 操作任务源排队一个全局任务,该任务将运行以下步骤:

      1. event 为一个新的、名为 responsestartedWebRequestResponseStartedEvent

      2. 给定 eventrequest 和 "none", 填充 WebRequestEvent

      3. eventresponse 设置为给定 requestresponse,以及 interceptorincludeHeaders创建 WebRequestResponse 对象的结果。

      4. event 分派interceptor

处理 completed 事件,给定一个请求 request 和一个响应 response,运行以下步骤:
  1. interceptors 为获取 request适用的 WebRequestInterceptors的结果。

  2. controlledFrameEmbedderGlobal 为给定 request客户端获取环境的 controlledFrameEmbedderParent的结果的相关全局对象

  3. 如果 controlledFrameEmbedderGlobal 为 null,则返回。

  4. 对于 interceptors 中的每个 interceptor

    1. controlledFrameEmbedderGlobalDOM 操作任务源排队一个全局任务,该任务将运行以下步骤:

      1. event 为一个新的、名为 completedWebRequestCompletedEvent

      2. 给定 eventrequest 和 "none", 填充 WebRequestEvent

      3. eventresponse 设置为给定 requestresponse,以及 interceptorincludeHeaders创建 WebRequestResponse 对象的结果。

      4. event 分派interceptor

处理 errorOccurred 事件,给定一个请求 request 和一个响应 response,运行以下步骤:
  1. interceptors 为获取 request适用的 WebRequestInterceptors的结果。

  2. controlledFrameEmbedderGlobal 为给定 request客户端获取环境的 controlledFrameEmbedderParent的结果的相关全局对象

  3. 如果 controlledFrameEmbedderGlobal 为 null,则返回。

  4. 对于 interceptors 中的每个 interceptor

    1. controlledFrameEmbedderGlobalDOM 操作任务源排队一个全局任务,该任务将运行以下步骤:

      1. event 为一个新的、名为 erroroccurredWebRequestErrorOccurredEvent

      2. 给定 eventrequest 和 "none", 填充 WebRequestEvent

      3. eventerror 设置为一个 描述 response 中错误的实现定义的错误消息。

      4. event 分派interceptor

填充一个 WebRequestEvent, 给定一个 WebRequestEvent event、一个请求 request,以及一个 RequestedHeaders requestedHeaders,运行以下步骤:
  1. environmentSettingsObjectrequest客户端

  2. event 上设置以下字段:

    frameId

    -1

  3. window 为给定 environmentSettingsObject环境设置对象的所属 Window

  4. 如果 window 不为 null,则:

    1. parentNavigablewindownavigableparent

    2. 更新 event 的以下字段:

      documentId

      environmentSettingsObjectid

      documentLifecycle

      给定 window关联文档获取 Document 的 DocumentLifecycle的结果。

      frameId

      windownavigableframeId

      frameType

      如果 window浏览上下文fenced frame config instance 为非 null,则为 "fenced-frame"; 如果 parentNavigable 为 null,则为 "outermost-frame"; 否则为 "sub-frame"

    3. 如果 parentNavigable 不为 null,则更新 event 的以下值:

      parentDocumentId

      parentNavigable活动文档相关全局对象id

      parentFrameId

      parentNavigableframeId

  5. eventrequest 设置为一个具有以下字段的新的 WebRequestRequest

    url

    requestURL 列表的最后一个元素。

    method

    request方法

    initiator

    给定 request源的序列化

    注:不透明源会导致 initiator 被设置为 DOMString "null"。

    type

    给定 request,调用获取请求的 ResourceType的结果。

    id

    requestrequestId

  6. 如果 requestedHeaders 不是 "none", 则将 eventrequestheaders 设置为给定 request标头列表requestedHeaders,以及 isRequest 等于 true,调用将标头列表转换为 Headers 对象的结果。

获取一个 DocumentDocumentLifecycle, 给定 document, 运行以下步骤:
  1. 如果 documentunload counter > 0,则返回 "pending-deletion"。

  2. 如果 document节点 navigable为非 null,且是一个预渲染 navigable,则返回 "prerender"。

  3. 如果 document可抢救的,并且没有其 page showing, 则返回 "cached"。

  4. 返回 "active"。

创建 一个 WebRequestResponse 对象,给定一个请求 request、一个响应 response,以及一个 RequestedHeaders requestedHeaders,运行以下步骤:
  1. response 为一个具有以下字段的新的 WebRequestResponse

    statusCode

    response状态

    statusLine

    response状态消息

    fromCache

    如果 response缓存状态为 "local",则为 true;否则为 false

    ip

    如果该请求涉及网络请求,则为接收 response 来源的 IP 地址

    [FETCH] 规范目前未指定存储发送 request 时使用的远程 IP 地址。

  2. 如果 requestedHeaders 不是 "none", 则将 responseheaders 设置为 给定 response标头列表requestedHeaders,以及 isRequest 等于 false,调用将标头列表转换为 Headers 对象的结果。

  3. 返回 response

获取安全信息, 给定一个响应 response 和一个布尔值 includeRawDER, 运行以下步骤:
  1. info 为一个新的 SecurityInfo

  2. schemeresponseurlscheme

  3. 如果 scheme 为 "http" 或 "ws":

    1. info["state"] 设置为 "insecure"。

    2. 返回 info

  4. info["state"] 设置为 "secure"。

    注:浏览器通常会在证书错误时中断 连接。如果用户已明确允许,则状态可能改为设置 为 "broken"。

  5. leafCert 为与 response 关联的服务器 X.509 证书(定义于 [RFC5280])。

  6. derBytes 为对 leafCert 进行 DER 编码的结果(定义于 [X.690])。

  7. certInfo 为一个新的 CertificateInfo

  8. fingerprint 为一个新的 Fingerprint

  9. 计算 fingerprint 字符串:

    1. hashBytes 为对 derBytes 执行 SHA-256 算法(定义于 [RFC6234])的结果。

    2. hexString 为空字符串。

    3. 对于 hashBytes 中的每个字节 byte

      1. 如果 hexString 非空,则将 U+003A (:) 追加到 hexString

      2. hexPair 为表示 byte 的两个 ASCII 大写十六进制数字组成的字符串。

      3. hexPair 追加到 hexString

    4. fingerprint["sha256"] 设置为 hexString

  10. certInfo["fingerprint"] 设置为 fingerprint

  11. 如果 includeRawDERtrue

    1. arrayBuffer 为从 derBytes 创建 ArrayBuffer 的结果。

    2. certInfo["rawDER"] 设置为一个新的、查看 arrayBufferUint8Array 对象。

  12. certList 为空列表

  13. certInfo 追加certList

  14. info["certificates"] 设置为 certList

  15. 返回 info

将一个标头 列表转换为 Headers 对象,给定 一个标头列表 fetchHeaders、一个 RequestedHeaders requestedHeaders, 和一个布尔值 isRequest,运行以下步骤:
  1. 断言 requestedHeaders 不是 "none"。

  2. headers 为一个新的 Headers 对象。

  3. 对于 fetchHeaders 中的每个 fetchHeader

    1. 如果满足以下所有条件,则继续

    2. 如果满足以下所有条件,则继续

    3. fetchHeader 追加headers

  4. 返回 headers

获取一个 请求的 ResourceType, 给定一个请求 request,运行以下步骤:
  1. 如果 requesturlscheme 等于 "ws""wss", 则返回 "websocket"。

  2. 如果 requestinitiator 等于 "fetch""xmlhttprequest",则返回 "xmlhttprequest"。

  3. 如果 requestdestination 等于 "document", 则返回 "main-frame"。

  4. 如果 requestdestination 等于 "frame""iframe", 则返回 "sub-frame"。

  5. 如果 requestdestination 等于 "style""xslt", 则返回 "stylesheet"。

  6. 如果 requestdestination 等于 "script""json""audioworklet""paintworklet""serviceworker""sharedworker""worker",则返回 "script"。

  7. 如果 requestdestination 等于 "image", 则返回 "image"。

  8. 如果 requestdestination 等于 "font", 则返回 "font"。

  9. 如果 requestdestination 等于 "object""embed", 则返回 "object"。

  10. 如果 requestdestination 等于 "audio""track""video",则返回 "media"。

  11. 如果 requestdestination 等于 "report", 则返回 "csp-report"。

  12. 如果 requestdestination 等于 "",且 requestkeepalivetrue,则返回 "ping"。

  13. 返回 "other"。

创建一个 重定向响应,给定一个 DOMString redirectUrl, 返回一个具有以下字段的响应
状态

301

标头列表

« ("Location", redirectUrl) »

4.2. 猴子补丁

4.2.1. Fetch

一个请求具有关联的 requestId,它 是一个 不透明字符串,在请求创建时随机分配。

main fetch 算法被猴子补丁如下:

  1. requestfetchParams 的 request。

  2. response 为 null。

  3. webRequestResult 为给定 request 调用处理 beforeRequest 事件的结果。
  4. 如果 webRequestResult 不为 null,则:
    1. 如果 webRequestResultcanceltrue,则将 response 设置为网络错误
    2. 否则,如果 webRequestResultredirectURL 不是一个空 DOMString, 则将 response 设置为 给定 webRequestResultredirectURL 创建重定向响应的结果。

fetch response handover 算法被猴子补丁如下:

  1. 如果 response 不是网络错误,则给定 fetchParamsrequestresponse,调用处理 responseStarted 事件
  2. 令 timingInfo 为 fetchParams 的 timing info。

  1. 如果 fetchParams 的 process response consume body 非 null,则:

  2. 如果 response 不是网络错误,则给定 fetchParamsrequestresponse,调用处理 completed 事件
  3. 否则,给定 fetchParamsrequestresponse,调用 处理 errorOccurred 事件

HTTP-network-or-cache fetch 算法被猴子 补丁如下:

  1. 令 revalidatingFlag 为未设置。

  2. webRequestResult 设置为给定 request 调用处理 beforeSendHeaders 事件的结果。
  3. 如果 webRequestResult 不为 null,则:
    1. 如果 webRequestResultcanceltrue,则将 response 设置为网络错误
    2. 否则,如果 webRequestResultrequestHeaders 是非空列表,则将 request标头列表设置为 webRequestResultrequestHeaders标头列表
  4. 如果 response 不为 null, 运行这些步骤,但在 fetchParams 被取消时中止:

  5. 如果已中止,则返回适合 fetchParams 的网络错误。

  6. 如果 response 为 null,则:

    1. 如果 httpRequest 的 cache mode 为 "only-if-cached",则返回一个 网络错误。

    2. 给定 request,调用处理 sendHeaders 事件
    3. forwardResponse 为给定 httpFetchParams、includeCredentials 和 isNewConnectionFetch,运行HTTP-network fetch的结果。

    4. 如果 forwardResponse 不是网络错误,令 webRequestResult 为给定 requestforwardResponse 调用处理 headersReceived 事件的结果; 否则为 null。
    5. 如果 webRequestResult 不为 null,则:
      1. 如果 webRequestResultcanceltrue,则将 response 设置为网络错误
      2. 否则,如果 webRequestResultredirectURL 不是空 DOMString, 则将 forwardResponse 设置为给定 webRequestResultredirectURL 创建重定向响应的结果。
      3. 否则,如果 webRequestResultresponseHeaders 是非空 列表,则将 forwardResponse标头列表设置为 webRequestResultresponseHeaders标头列表

  1. 如果 response 的状态为 401,httpRequest 的 response tainting 不是 "cors",includeCredentials 为 true,且 request 的 window 是一个 环境设置对象,则:

    1. 如果 request 的 use-URL-credentials flag 未设置,或 isAuthenticationFetch 为 true,则:

      1. 如果 fetchParams 被取消,则返回适合 fetchParams 的网络 错误。

      2. usernamepassword 为 null。

      3. webRequestResult 为给定 requestresponse 调用处理 authRequired 事件的结果。
      4. 如果 webRequestResult 不为 null,则:
        1. 如果 webRequestResultcanceltrue,则将 response 设置为网络错误
        2. 否则,如果 webRequestResultauthCredentials 是一个 object, 则:
          1. username 设置为 webRequestResultauthCredentials["username"]。
          2. password 设置为 webRequestResultauthCredentials["password"]。
      5. 如果 usernamepassword 为 null,则将它们分别设置为requestwindow 中提示最终用户输入用户名和密码的结果。
  2. 如果 response 的状态为 407,则:

    1. webRequestResult 为给定 requestresponse 调用处理 authRequired 事件的结果。
    2. 如果 webRequestResult 不为 null,则:
      1. 如果 webRequestResultcanceltrue,则将 response 设置为网络错误
      2. 否则,如果 webRequestResultauthCredentials 是一个 object, 则:
        1. webRequestResultauthCredentials 存储为proxy-authentication entry
    3. 否则, 适当地提示最终用户 ...

HTTP-redirect fetch 算法被猴子补丁如下:

  1. 给定 requestresponse,调用处理 beforeRedirect 事件
  2. 令 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 menuItem;

  // Details about the frame the context menu is opened within.
  readonly attribute long frameId;
  readonly attribute USVString frameURL;
  readonly attribute USVString pageURL;

  // Details about the element the context menu is opened within the context of.
  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

URLPatternURLPatternInput列表。 如果它不是 ,则除非嵌入文档的 URL 与其中一个列表URLPattern 匹配,否则该上下文 菜单项不会显示。如果它是 ,则忽略此 检查。

targetURLPatterns

URLPatternURLPatternInput列表。 如果它不是 ,则除非上下文菜单目标的 URL 与其中一个列表URLPattern 匹配,否则该上下文 菜单项不会显示。如果它是 ,则忽略此检查。

注:Target 是 img/audio/video 标签的 "src" 属性 以及锚点标签的 "href"。

parentId

上下文菜单项的 ID。该 上下文菜单项可以出现在父项的 子菜单下。

title

菜单项的标题。除非 type 是 "separator",否则这是必需的。

type

菜单项的类型。

checked

如果 typecheckbox, 该上下文菜单项最初是否被选中。

enabled

上下文菜单项是否启用。

create(properties) 方法步骤为:

  1. p一个新 promise

  2. controlledframethis

  3. 返回 p并行运行以下步骤。

  4. contextMenusMapcontrolledframe上下文 菜单映射

  5. idproperties["id"]。

  6. 如果 contextMenusMap[id] 存在,则给定 controlledframepTypeError拒绝一个嵌入者 promise, 并中止这些步骤。

  7. contextMenusMap[id] 设置properties

  8. 给定 controlledframep解决一个嵌入者 promise

remove(id) 方法步骤为:

  1. p一个新 promise

  2. controlledframethis

  3. 返回 p并行运行以下步骤。

  4. contextMenusMapcontrolledframe上下文 菜单映射

  5. 移除 contextMenusMap[id]。

  6. 给定 controlledframep解决一个嵌入者 promise

removeAll() 方法步骤为:

  1. p一个新 promise

  2. controlledframethis

  3. 返回 p并行运行以下步骤。

  4. contextMenusMapcontrolledframe上下文 菜单映射

  5. 清空 contextMenusMap

  6. 给定 controlledframep解决一个嵌入者 promise

update(id, properties) 方法 步骤为:

  1. p一个新 promise

  2. controlledframethis

  3. 返回 p并行运行以下步骤。

  4. contextMenusMapcontrolledframe上下文 菜单映射

  5. 如果 contextMenusMap[id] 不存在,则给定 controlledframepTypeError拒绝一个嵌入者 promise, 并中止这些步骤。

  6. contextMenusMap[id] 设置properties

  7. 给定 controlledframep解决一个嵌入者 promise

本节是非规范性的。

ContextType 表示上下文菜单的上下文,可以是以下值:

frame

当用户在嵌套框架中上下文点击时适用,例如 iframe

selection

当文档的一部分被选中时适用。

link

当用户在链接上上下文点击时适用。

editable

当用户在可编辑元素上上下文点击时适用,例如 textarea

image

当用户在图像上上下文点击时适用。

video

当用户在 video 元素上上下文点击时适用。

audio

当用户在 audio 元素上上下文点击时适用。

page

当用户在页面中上下文点击,但其他页面上下文都不适用时适用(例如,该点击不在图像、 嵌套 iframe 或链接上)。

all

指定 all 等价于所有其他上下文的组合。

确定该上下文菜单项是否会被显示 ,给定一个上下文菜单项 item

  1. propertiesitemproperties

  2. elementitemmenu上下文元素

  3. controlledframeelement节点 navigablecontrolledFrameEmbedderParent

  4. 如果 controlledframe 为 null,则返回 false

  5. documentUrlcontrolledframe嵌入的 navigable活动文档URL

  6. targetUrl 为空字符串。

  7. 如果 elementHTMLImageElement 的实例,则将 targetUrl 设置为 elementsrc 属性。

  8. 如果 elementHTMLMediaElement 的实例,则将 targetUrl 设置为 elementsrc 属性。

  9. 如果 elementHTMLAnchorElement 的实例,则将 targetUrl 设置为 elementhref 属性。

  10. 如果 properties["contexts"] 不是

    1. matchesContext 为初始值为 false 的布尔值。

    2. 对于 properties["contexts"] 中的每个 context

      1. 如果 element 匹配 context,则将 matchesContext 设置为 true 并跳出;

        ContextType 的匹配行为尚未被指定,尽管上面的注释包含了一些期望行为的信息。

    3. 如果 matchesContextfalse,则返回 false

  11. 如果 properties["documentURLPatterns"] 不是

    1. matchesDocumentUrl 为初始值为 false 的布尔值。

    2. 对于 properties["documentURLPatterns"] 中的每个 urlPattern

      1. 如果 urlPattern 是一个 URLPatternInput, 则将 urlPattern 设置为给定 urlPattern 的 一个新的 URLPattern

      2. 如果给定 urlPatterndocumentUrl 匹配一个 URLPattern, 则将 matchesDocumentUrl 设置为 true 并跳出;

    3. 如果 matchesDocumentUrlfalse,则返回 false

  12. 如果 properties["targetURLPatterns"] 不是

    1. matchesTargetUrl 为初始值为 false 的布尔值。

    2. 对于 properties["targetURLPatterns"] 中的每个 urlPattern

      1. 如果 urlPattern 是一个 URLPatternInput, 则将 urlPattern 设置为给定 urlPattern 的 一个新的 URLPattern

      2. 如果给定 urlPatterntargetUrl 匹配一个 URLPattern,则 将 matchesTargetUrl 设置为 true 并跳出;

    3. 如果 matchesTargetUrlfalse,则返回 false

  13. 返回 true

5.1. 事件

ContextMenus 触发以下事件:

事件名称 接口 触发时机...
show Event 向用户显示上下文菜单时。
click ContextMenusClickEvent 用户选择一个上下文菜单项时。

ContextMenus 支持以下事件处理程序(以及它们 对应的事件处理程序事件类型)作为事件处理程序 IDL 属性

事件处理程序 事件处理程序事件类型
onshow show
onclick click

ContextMenus contextMenus 的一个或多个上下文菜单项被显示给用户时,向 contextMenus 分派一个 show 事件

当一个上下文菜单项 item 被用户选中时, 给定 item 分派一个 click 事件

分派一个 show 事件, 给定一个 ContextMenus contextMenus,向 contextMenus 分派一个新的、名为 showEvent
分派一个 click 事件, 给定一个上下文菜单项 item,运行以下 步骤:
  1. propertiesitemproperties

  2. menuitemmenu

  3. elementmenu上下文 元素

  4. event 为一个新的、名为 clickContextMenusClickEvent

  5. event["menuItem"] 设置为一个具有以下字段的新的 MenuItemDetails

    id

    itemid

    parentMenuId

    properties["parentId"]。

    checked

    上下文菜单项是否被选中。

    wasChecked

    复选框或单选项在被点击之前的状态。

  6. 设置 event 的以下字段:

    frameId

    element节点 navigableframeId

    frameURL

    element节点 navigableURL

    pageURL

    elementtraversable navigableURL

    editable

    所选 element 是否可编辑,例如文本输入框。

    linkURL

    如果 elementHTMLAnchorElement 的实例,则为 elementhref 属性

    mediaType

    如果存在,则基于 element,为 "image"、"video" 或 "audio" 之一。

    selectionText

    上下文选择的文本,如果有。

    srcURL

    element 的 "src" 属性,如果存在。

  7. 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 上的用户。

计划中的缓解措施:

一个 IWA 可能通过 Controlled Frame 嵌入另一个 IWA(或 自身),从而以某种方式操纵我们的 IWA 策略(例如,被 Controlled Frame 嵌入的 IWA 可能会因缺少 "controlled-frame" 策略控制特性而检测到自己正被嵌入)。

计划中的缓解措施:

Controlled Frame 可能获得对强大的 <controlledframe> 元素的访问权限。

不预期使用 Controlled Frame 的 IWA 可能尝试嵌入内容。

计划中的缓解措施:

IWA 可能尝试嵌入来自非 https scheme 的内容,例如 'http:' 或 'isolated-app:'

计划中的缓解措施:

恶意 Controlled Frame 可能访问嵌入者正在运行的进程(例如 Spectre 攻击)

计划中的缓解措施:

给定 "https origin" 的 Controlled Frame 可能与该 https origin 的用户自身存储数据 交互或产生干扰

计划中的缓解措施:

恶意 Controlled Frame 可能覆盖嵌入者存储的数据

计划中的缓解措施:

恶意 Controlled Frame 可能检测到自身被嵌入,并试图攻击嵌入者应用

计划中的缓解措施:

想法:

用户可能无法验证在 Controlled Frame 中查看的页面的源

想法:

Controlled Frame 可能利用过时浏览器引擎中的漏洞

已通过以下方式解决:

8.2. 隐私

Controlled Frame 与 Permissions Policy 和 Permissions 集成。你可以阅读更多关于 Permissions Policy § 12. Privacy and Security 的内容。你可以阅读更多关于 Permissions § E Security considerations 的内容。

对于 Controlled Frame,我们已识别出以下隐私考虑事项:

8.3. 可访问性

对于 Controlled Frame,我们已识别出以下可访问性考虑事项:

9. 致谢

以下人员为本文档的开发做出了贡献。

一致性

文档 约定

一致性要求通过描述性断言 与 RFC 2119 术语的组合来表达。 本文档规范性部分中的关键词 “MUST”、“MUST NOT”、“REQUIRED”、“SHALL”、“SHALL NOT”、“SHOULD”、“SHOULD NOT”、“RECOMMENDED”、 “MAY” 和 “OPTIONAL” 应按 RFC 2119 中所述进行解释。 然而,为了可读性, 这些词在本规范中并不全部以大写字母出现。

本规范的所有文本都是规范性的, 但明确标记为非规范性的章节、示例和注释除外。[RFC2119]

本规范中的示例以 “for example” 等词语引入, 或通过 class="example" 与规范性文本区分开来, 如下所示:

这是一个资料性示例的例子。

资料性注释以 “Note” 一词开头, 并通过 class="note" 与规范性文本区分开来, 如下所示:

Note,这是一个资料性注释。

索引

本规范定义的术语

由引用定义的术语

参考文献

规范性参考文献

[Console]
Dominic Farolino; Robert Kowalski; Terin Stock. Console 标准. 现行标准。URL:https://console.spec.whatwg.org/
[CSS-PAGE-FLOATS-3]
Johannes Wilm. CSS Page Floats. URL:https://drafts.csswg.org/css-page-floats/
[CSSOM-1]
Daniel Glazman; Emilio Cobos Álvarez. CSS 对象模型 (CSSOM). URL:https://drafts.csswg.org/cssom/
[DOM]
Anne van Kesteren. DOM 标准. 现行标准。 URL:https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript 语言规范. URL:https://tc39.es/ecma262/multipage/
[FENCED-FRAME]
Fenced Frame. 社区组报告草案。 URL:https://wicg.github.io/fenced-frame/
[FETCH]
Anne van Kesteren. Fetch 标准. 现行 标准。URL:https://fetch.spec.whatwg.org/
[FileAPI]
Marijn Kruisselbrink. File API. URL:https://w3c.github.io/FileAPI/
[GEOLOCATION]
Marcos Caceres; Reilly Grant. Geolocation. URL:https://w3c.github.io/geolocation/
[HTML]
Anne van Kesteren; et al. HTML 标准. 现行标准。URL:https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 标准. 现行标准。URL:https://infra.spec.whatwg.org/
[ISOLATED-CONTEXTS]
Isolated Contexts. 社区组报告草案。URL:https://wicg.github.io/isolated-web-apps/isolated-contexts.html
[MANIFEST-APP-INFO]
Aaron Gustafson. Web App Manifest - Application Information. URL:https://w3c.github.io/manifest-app-info/
[Permissions]
Marcos Caceres; Mike Taylor. Permissions. URL: https://w3c.github.io/permissions/
[Permissions-Policy]
Ian Clelland. Permissions Policy. URL:https://w3c.github.io/webappsec-permissions-policy/
[RFC2119]
S. Bradner. 用于 RFC 中表示要求级别的 关键词. 1997 年 3 月。最佳当前实践。URL:https://datatracker.ietf.org/doc/html/rfc2119
[RFC5280]
D. Cooper; et al. Internet X.509 公钥 基础设施证书和证书吊销列表(CRL)配置文件. URL:https://datatracker.ietf.org/doc/html/rfc5280
[RFC6234]
D. Eastlake 3rd; T. Hansen. US Secure Hash Algorithms(SHA 以及基于 SHA 的 HMAC 和 HKDF). URL:https://datatracker.ietf.org/doc/html/rfc6234
[STORAGE]
Anne van Kesteren. Storage 标准. 现行 标准。URL:https://storage.spec.whatwg.org/
[URL]
Anne van Kesteren. URL 标准. 现行标准。 URL:https://url.spec.whatwg.org/
[URLPATTERN]
Ben Kelly; Jeremy Roman; 宍戸俊哉 (Shunya Shishido). URL Pattern 标准. 现行标准。URL:https://urlpattern.spec.whatwg.org/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 标准. 现行 标准。URL:https://webidl.spec.whatwg.org/
[X.690]
信息技术 - ASN.1 编码规则: 基本编码规则(BER)、规范编码规则(CER)和可辨别编码规则(DER)规范. URL:https://www.itu.int/rec/T-REC-X.690
[XHR]
Anne van Kesteren. XMLHttpRequest 标准. 现行 标准。URL:https://xhr.spec.whatwg.org/

资料性参考文献

[COOKIES]
A. Barth. HTTP 状态管理机制. 2011 年 4 月。提议标准。URL:https://httpwg.org/specs/rfc6265.html
[CSS-CASCADE-5]
Elika Etemad; Miriam Suzanne; Tab Atkins Jr.. CSS 层叠与继承 Level 5. URL:https://drafts.csswg.org/css-cascade-5/
[High-Watermark-Permissions]
Robbie McElrath. Isolated Web Apps High Watermark Permissions 解释器. URL:https://github.com/WICG/isolated-web-apps/blob/main/Permissions.md
[HTTP-CACHING]
R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed.. HTTP 缓存. 2022 年 6 月。互联网 标准。URL:https://httpwg.org/specs/rfc9111.html
[Isolated-Web-Apps]
Reilly Grant. Isolated Web Apps 解释器. URL:https://github.com/WICG/isolated-web-apps/blob/main/README.md

IDL 索引

[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> scriptNameList);

    // Configuration methods.
    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 zoomMode);

    // Capture methods.
    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;
};

// 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;
};

dictionary ClearDataOptions {
  long since;
};

dictionary ClearDataTypeSet {
  boolean cache;
  boolean cookies;
  boolean fileSystems;
  boolean indexedDB;
  boolean localStorage;
  boolean persistentCookies;
  boolean sessionCookies;
};

enum ZoomMode {
  "per-origin",
  "per-view",
  "disabled"
};


// One of |code| or |file| must be specified but not both.
dictionary ImageDetails {
  DOMString format;
  DOMString quality;
};

[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;
};


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;
};


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;
};


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;
};


[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;
};


[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;
};


[Exposed=Window, IsolatedContext]
interface ContentLoadEvent : Event {
  constructor(DOMString type, optional EventInit eventInitDict = {});
};


[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;
};


[Exposed=Window, IsolatedContext]
interface LoadCommitEvent : Event {
  constructor(DOMString type, optional LoadCommitEventInit eventInitDict = {});
  readonly attribute LoadInfo loadInfo;
};

dictionary LoadCommitEventInit: EventInit {
  LoadInfo? loadInfo;
};


[Exposed=Window, IsolatedContext]
interface LoadStartEvent : Event {
  constructor(DOMString type, optional LoadStartEventInit eventInitDict = {});
  readonly attribute LoadInfo loadInfo;
};

dictionary LoadStartEventInit: EventInit {
  LoadInfo? loadInfo;
};


[Exposed=Window, IsolatedContext]
interface LoadStopEvent : Event {
  constructor(DOMString type, optional LoadStopEventInit eventInitDict = {});
};

dictionary LoadStopEventInit: EventInit {
};


[Exposed=Window, IsolatedContext]
interface LoadRedirectEvent : Event {
  constructor(DOMString type, optional LoadRedirectEventInit eventInitDict = {});
  readonly attribute LoadRedirectInfo loadRedirectInfo;
};

dictionary LoadRedirectEventInit: EventInit {
  LoadRedirectInfo? loadRedirectInfo;
};


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 includeHeaders = "none";
  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 {};

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 menuItem;

  // Details about the frame the context menu is opened within.
  readonly attribute long frameId;
  readonly attribute USVString frameURL;
  readonly attribute USVString pageURL;

  // Details about the element the context menu is opened within the context of.
  readonly attribute boolean editable;
  readonly attribute USVString? linkURL;
  readonly attribute DOMString? mediaType;
  readonly attribute DOMString? selectionText;
  readonly attribute USVString? srcURL;
};

议题索引

这些步骤是初始化新 navigable 中的 History.length 所必需的。这是 HTML 标准中已有的一个 议题
此算法不适用于 Shared 或 Service Workers,因为 controlledFrameEmbedderParent 只 定义在 navigable 上,并且 并不总是能从一个非 Window环境转到一个 navigable
ContextType 的匹配行为尚未指定,不过 上面的注释提供了一些关于期望行为的信息。