WebDriver BiDi

W3C 工作草案,

关于本文档的更多细节
此版本:
https://www.w3.org/TR/2026/WD-webdriver-bidi-20260629/
最新发布版本:
https://www.w3.org/TR/webdriver-bidi/
编辑草案:
https://w3c.github.io/webdriver-bidi/
先前版本:
历史:
https://www.w3.org/standards/history/webdriver-bidi/
实现报告:
https://wpt.fyi/results/webdriver/tests/bidi
测试套件:
https://github.com/web-platform-tests/wpt/tree/master/webdriver/tests/bidi
反馈:
GitHub
规范内联
编辑者:
James Graham (Mozilla)
Alex Rudenko (Google)
Maksim Sadym (Google)
频道:
irc.w3.org 上的 #webdriver
维基:
W3C WebDriver 维基

摘要

本文档定义了双向 WebDriver 协议,这是一种用于远程控制用户代理的机制。

本文档状态

本节描述了本文档在其发布时的状态。当前 W3C 出版物列表,以及本技术报告的最新修订版本,可在 W3C 标准与草案索引中找到。

讨论本规范时首选使用 GitHub Issues。或者,你也可以将评论发送到 Browser Testing and Tools Working Group 的 邮件列表 public-browser-tools-testing@w3.org归档)。

本文档由 Browser Testing and Tools Working Group 作为工作草案发布,并使用 推荐 标准轨道

作为工作草案发布并不意味着 W3C 及其成员对其背书。

这是一份草案文档,可能会在任何时候由其他文档更新、替换或废弃。 除作为进行中的工作外,不宜引用本文档。

本文档由一个根据 W3C 专利政策运作的小组制作。 W3C 维护了一份与该小组交付物相关的任何 专利披露的公开列表;该页面还包括 披露专利的说明。实际知晓某项专利且认为该专利包含必要权利要求的个人, 必须按照 W3C 专利政策第 6 节披露该信息。

本文档受 2025 年 8 月 18 日 W3C 流程文档管辖。

1. 引言

本节是非规范性的。

WebDriver 定义了一种用于 自省和 远程控制用户代理的协议。本规范通过 引入双向通信来扩展 WebDriver。相较于 WebDriver 严格的 命令/响应格式,这允许事件从 用户代理流式传输到控制软件,从而更好地匹配浏览器 DOM 的事件驱动本质。

2. 基础设施

本规范依赖 Infra Standard。[INFRA]

网络协议消息使用 CDDL 定义。[RFC8610]

本规范定义了一个等待 队列,它是一个映射

肯定有更好的 机制来做这种“等待事件”的事情。

当一个并行运行的算法 algorithm 等待一组 事件 eventsresume id 时:

  1. 暂停 algorithm 的执行。

  2. 断言:等待 队列不包含 resume id

  3. 等待 队列[resume id] 设置为(events, algorithm)。

要用给定的 nameidparameters恢复
  1. 如果等待队列不 包含 id,则返回。

  2. 令(events, algorithm)为等待队列[id]

  3. events 中的每个 event

    1. 如果 event 等于 name

      1. 等待队列中移除 id

      2. algorithm 被暂停的 位置恢复运行其中的步骤,并将 nameparameters 作为 等待的结果传入。

        我们是否应该有类似微任务的东西,以 确保它在事件循环上的任何其他任务之前 运行?

WebDriver 配置是一个具有以下内容的结构体

WebDriver 配置具有一个关联类型, 它 是一个类型。

WebDriver 配置要么是一个 其类型为该配置的关联类型的值,要么是 unset

Unset 是一个值,表示某个特定配置 尚未被设置。

注:此算法允许访问给定navigableWebDriver 配置,方式是依次检查 navigables、然后是 user contexts,最后是 global 中的值。 如果配置未设置,则返回 unset

要获取 WebDriver 配置 configuration 对于 navigable navigableWebDriver 配置值

  1. top-level traversablenavigable顶级 traversable

  2. 如果 configurationnavigables 包含 top-level traversable

    1. navigable configuration valueconfigurationnavigables[top-level traversable]。

    2. 如果 navigable configuration value 不是 unset,则返回 navigable configuration value

  3. user contextnavigable关联用户 上下文

  4. 如果 configurationuser contexts 包含 user context

    1. user context configuration valueconfigurationuser contexts[user context]。

    2. 如果 user context configuration value 不是 unset,则返回 user context configuration value

  5. 返回 configurationglobal

注:这是一个用于按 target 存储 WebDriver 配置的通用算法,target 可以是 navigable用户上下文,或者如果 target 为 null 或被省略,则全局存储。

要将 WebDriver 配置 configuration value 存储到可选 target 中, 其中 target 是一个navigable、 一个用户上下文,或在未提供时为 null:

  1. 如果 target 为 null,则将 configurationglobal 设置为 value

  2. 如果 target 是一个用户上下文,则将 configurationuser contexts[target] 设置为 value

  3. 如果 target 是一个navigable,则将 configurationnavigables[target] 设置为 value

注:此通用算法将 WebDriver 配置 存储在 globaluser contextsnavigables 中,具体取决于 command parameters 中是否存在 "userContexts" 和 "contexts"。这些 参数 是互斥的。如果两者都未提供,则配置会全局存储。

要针对给定的 command parameters 存储 WebDriver 配置 WebDriver 配置 configuration value

  1. 如果 command parameters 包含 "userContexts",且 command parameters 包含 "contexts",则返回带有错误 代码 invalid argument错误

  2. affected navigables 为空集合

  3. 如果 command parameters 包含 "contexts":

    1. navigables尝试command parameters["contexts"] 通过 id 获取有效顶级 traversables 的结果。

    2. 对于 navigables 中的每个 navigable

      1. navigable 追加affected navigables

      2. configurationvalue 存储navigable 中。

  4. 否则,如果 command parameters 包含 "userContexts":

    1. user contexts尝试command parameters["userContexts"] 获取有效用户上下文的结果。

    2. 对于 user contexts 中的每个 user context

      1. 对于所有其 关联用户上下文user context顶级 traversable列表中的每个 top-level traversable

        1. top-level traversable 追加affected navigables

      2. configurationvalue 存储user context 中。

  5. 否则:

    1. 对于所有顶级 traversable中的每个 top-level traversable,将 top-level traversable 追加affected navigables

    2. 存储 configurationvalue

  6. 返回 affected navigables

3. 协议

本节定义 WebDriver BiDi 协议的基本概念。这些术语不同于其在 传输层的表示。

协议使用 CDDL 定义来定义。为方便实现者,定义了两个单独的 CDDL 定义; 远端定义定义了 在本地端生成并由远端消费的消息格式,而 本地端 定义定义了在远端 生成并由本地端消费的消息格式

3.1. 定义

这是否应该作为 附录?

本节给出了 远端定义本地端定义的初始内容。 这些内容由本规范其余部分中定义的定义片段 进行扩充。

Remote end definition

Command = {
  id: js-uint,
  CommandData,
  Extensible,
}

CommandData = (
  BrowserCommand //
  BrowsingContextCommand //
  EmulationCommand //
  InputCommand //
  NetworkCommand //
  ScriptCommand //
  SessionCommand //
  StorageCommand //
  WebExtensionCommand
)

EmptyParams = {
   Extensible
}

Local end definition

Message = (
  CommandResponse /
  ErrorResponse /
  Event
)

CommandResponse = {
  type: "success",
  id: js-uint,
  result: ResultData,
  Extensible
}

ErrorResponse = {
  type: "error",
  id: js-uint / null,
  error: ErrorCode,
  message: text,
  ? stacktrace: text,
  Extensible
}

ResultData = (
  BrowserResult /
  BrowsingContextResult /
  EmulationResult /
  InputResult /
  NetworkResult /
  ScriptResult /
  SessionResult /
  StorageResult /
  WebExtensionResult
)

EmptyResult = {
  Extensible
}

Event = {
  type: "event",
  EventData,
  Extensible
}

EventData = (
  BrowsingContextEvent //
  InputEvent //
  LogEvent //
  NetworkEvent //
  ScriptEvent
)

EmptyResult 是一种没有必需字段的结果 类型, 用作不会产生结果数据的命令的返回类型。

远端定义本地端定义

Extensible = (*text => any)

js-int = -9007199254740991..9007199254740991
js-uint = 0..9007199254740991

3.2. 会话

WebDriver BiDi 扩展了 会话概念,该概念来自 WebDriver

会话具有一个 BiDi 标志,除非另有说明,否则该标志为 false。

BiDi 会话是一个 会话,其 BiDi 标志 被设置为 true。

活动 BiDi 会话列表由以下步骤给出:
  1. BiDi sessions 为一个新的列表

  2. 对于活动会话中的每个 session

    1. 如果 session 是一个 BiDi 会话,则将 session 追加到 BiDi sessions

  3. 返回 BiDi sessions

3.3. 模块

WebDriver BiDi 协议被组织为多个模块。

每个模块表示与用户 代理某一方面有关的一组相关 命令事件。例如,模块可能包含用于检查和 操作 DOM,或用于脚本执行的功能。

每个模块都有一个模块名称,它是一个字符串。模块中定义的命令 和事件的命令名称事件名称模块名称开头,后跟一个句点 "."。

包含命令的模块定义 远端定义 片段。它们会为该模块的命令CommandData 组中提供选择项,也可以定义 额外的定义属性。它们 也可以定义 本地端定义 片段,为该模块中命令的结果 在 ResultData 组中提供额外选择项。

包含事件的模块定义 本地端定义 片段,这些片段是该模块事件Event 组中的 选择项。

实现可以定义扩展模块。这些扩展模块必须具有一个 包含单个冒号 ":" 字符的模块名称。 冒号之前的 部分是前缀;对于给定实现专用的所有 扩展模块, 这通常是相同的,并且对于 给定实现应当是唯一的。

其他规范可以定义自己的 WebDriver-BiDi 模块来扩展该协议。 这类模块的名称不得包含冒号(:)字符, 也不得定义包含该字符的命令名称事件名称或属性 名称。

鼓励外部规范的作者添加新模块,而不是扩展 现有模块。如果希望扩展某个现有模块,最好将该 扩展直接整合到包含原始模块定义的规范中。

3.4. 命令

命令是一种异步 操作,由 本地端请求,并在远端运行, 最终将 结果或错误返回给本地端。 多个 命令可以同时运行,并且命令可能会 长时间运行。因此,命令可能会乱序完成。

每个命令由以下内容定义:

可以在没有活动会话的情况下运行的命令是静态 命令。除非在其定义中说明,否则命令不是静态命令。

当命令从本地端发送时,它们 具有命令 id。这是一个 标识符,本地端用它来识别来自特定 命令的响应。从远端 的角度看, 该标识符是不透明的,不能在内部用于识别命令。

注:这是因为命令 id 完全由本地端 控制,并且在一个会话的过程中不一定唯一。例如,一个本地端如果 忽略所有响应,就可以对每个命令使用相同的命令 id。

所有命令 名称的集合是一个集合,包含 所有已定义的命令名称,包括任何属于扩展模块的命令名称。

3.5. 错误

WebDriver BiDi 使用以下额外代码扩展了来自 WebDriver错误代码集合:

invalid web extension
尝试安装无效的 Web 扩展。
no such client window
尝试与未知的客户端窗口交互。
no such handle
尝试反序列化未知的 RemoteObjectReference
no such history entry
尝试导航到未知的会话历史条目
no such network collector
尝试移除未知的收集器
no such intercept
尝试移除未知的网络拦截
no such network data
尝试引用未知的网络数据
no such node
尝试反序列化未知的 SharedReference
no such request
尝试继续处理未知的请求
无此屏幕录制
试图停止未知的屏幕录制。
no such script
尝试移除未知的预加载脚本
no such storage partition
尝试访问不存在的存储分区中的数据。
no such user context
尝试引用未知的用户上下文
no such web extension
尝试引用未知的 Web 扩展。
unable to close browser
尝试关闭浏览器,但未能做到。
unable to set cookie
尝试创建 cookie,但用户代理拒绝了它。
underspecified storage partition
尝试与未充分指定的存储分区中的数据交互。
unable to set file input
尝试设置文件输入,但未能做到。
unavailable network data
尝试获取未被收集或已被逐出的网络数据。
ErrorCode = "invalid argument" /
            "invalid selector" /
            "invalid session id" /
            "invalid web extension" /
            "move target out of bounds" /
            "no such alert" /
            "no such network collector" /
            "no such element" /
            "no such frame" /
            "no such handle" /
            "no such history entry" /
            "no such intercept" /
            "no such network data" /
            "no such node" /
            "no such request" /
            "no such screencast" /
            "no such script" /
            "no such storage partition" /
            "no such user context" /
            "no such web extension" /
            "session not created" /
            "unable to capture screen" /
            "unable to close browser" /
            "unable to set cookie" /
            "unable to set file input" /
            "unavailable network data" /
            "underspecified storage partition" /
            "unknown command" /
            "unknown error" /
            "unsupported operation"

3.6. 事件

事件是一个通知,由 远端 发送给本地端,表示远端上发生了值得关注的事情。

BiDi 会话具有订阅,它是一个列表,包含订阅

BiDi 会话具有一个已知订阅 id,它是一个集合,包含 已发布给本地端但尚未被取消订阅的所有 订阅 id

订阅是一个结构体,由一个 订阅 id(一个字符串)、 事件名称(一个事件名称的集合)、 顶级 traversable id(一个集合,包含顶级 traversable的 ID) 和 用户上下文 id(一个集合,包含用户上下文的 ID)。

如果 subscription顶级 traversable id是空集合, 且 subscription用户上下文 id是空集合,则订阅 subscription全局的

给定 event namenavigables启用了某个事件的会话 集合为:

  1. sessions 为一个新的集合

  2. 对于活动 BiDi 会话中的每个 session

    1. 如果对于 sessionevent namenavigables事件 已启用, 则将 session 追加到 sessions

  3. 返回 sessions

要在给定 sessionevent namenavigables 的情况下判断某个事件 是否已启用

注:navigables 是一个集合,因为共享 worker 可以关联 多个上下文。

  1. top-level traversables 为使用 navigables 调用获取顶级 traversable 的结果。

  2. 对于 session订阅中的每个 subscription

    1. 如果 subscription事件名称包含 event name,则继续

    2. 如果 subscription全局的,则返回 true。

    3. 如果用户上下文 id不为空:

      1. 对于 top-level traversables 中的每个 navigable

        1. 如果 subscription用户上下文 id包含 navigable关联用户上下文用户上下文 id, 则返回 true。

    4. 否则:

      1. subscription top-level traversables 为用 subscription顶级 traversable id 调用通过 id 获取 navigables 的结果。

      2. 如果 top-level traversablessubscription top-level traversables交集不是,则返回 true。

  3. 返回 false。

给定 event namesession启用了某个事件的顶级 traversable 集合 为:

  1. result 为一个新的集合

  2. 对于 session订阅中的每个 subscription

    1. 如果 subscription事件名称不 包含 event name, 则继续

    2. 如果 subscription全局的

      1. 对于远端的顶级 traversable中的每个 traversable

        1. traversable 追加result

      2. 中断

    3. 否则,如果用户上下文 id不为空:

      1. 对于远端的顶级 traversable中的每个 traversable

        1. 如果 subscription用户上下文 id包含 traversable关联用户上下文用户上下文 id,则将 traversable 追加result

    4. 否则:

      1. top-level traversables 为用 subscription顶级 traversable id 调用通过 id 获取 navigables 的结果。

      2. top-level traversables 中的每一项追加result

  3. 返回 result

要在给定 name 的情况下获得一组 事件名称
  1. events 为空集合

  2. 如果 name 包含 U+002E(句点):

    1. 如果 name 是某个事件的事件名称,则将 name 追加到 events 并返回带有数据 events成功

    2. 返回一个带有错误代码 invalid argument错误

  3. 否则,将 name 解释为表示某个模块中的所有事件。 如果 name 不是模块名称,则返回一个错误,其 错误代码invalid argument

  4. 将名称为 name 的模块中每个事件事件 名称 追加到 events

  5. 返回带有数据 events成功

4. 传输

消息传输使用 WebSocket 协议提供。 [RFC6455]

注:按 WebSocket 协议的术语,本地端是 客户端,而远端是服务器 / 远程主机。

注:命令事件编码为消息的方式 类似于 JSON-RPC,但本规范并未规范性地 引用它。[JSON-RPC]远端的规范性要求 改为以精确处理模型的形式给出,而不对 本地端给出规范性要求。

WebSocket 监听器 是一个能够 接受传入 WebSocket 连接的网络端点。

WebSocket 监听器 具有一个host、一个port、一个secure flag,以及一个 WebSocket 资源 列表

当创建 WebSocket 监听器 listener 时,远端 必须开始在 listenerhostport 所给定的主机和端口上监听 WebSocket 连接。如果 listenersecure flag 已设置,则从 listener 建立的连接必须经过 TLS 加密。

远端具有一个集合,其中包含 WebSocket 监听器 活动 监听器,其初始为空。

远端具有一个集合,其中包含未与 会话关联的 WebSocket 连接,其初始为空。

WebSocket 连接是遵循 WebSocket 协议要求的网络连接

BiDi 会话具有一个集合,其中包含会话 WebSocket 连接,其元素是WebSocket 连接。这 初始为空。

BiDi 会话 session 与连接 关联 connection,如果 session会话 WebSocket 连接包含 connection

注:每个 WebSocket 连接至多与一个 BiDi 会话关联。

当客户端通过连接到活动监听器集合之一的 listener建立 WebSocket 连接 connection 时, 实现必须按照 WebSocket 服务器端要求继续进行,并在决定是否 接受传入连接时运行以下步骤:

  1. resource name读取客户端开启握手所得的资源名称。如果 resource name 不在 listenerWebSocket 资源列表中,则停止 运行这些步骤,并表现为所请求的服务不可 用。

  2. 如果 resource name 是字节字符串 "/session", 且实现支持仅 BiDi 会话

    1. 运行任何其他实现定义的步骤,以决定是否应当接受 该连接;如果不接受,则停止运行这些 步骤,并表现为所请求的服务不可用。

    2. 将该连接添加到未与会话关联的 WebSocket 连接

    3. 返回。

  3. resource name 获取 WebSocket 资源的会话 ID, 并令 session id 为该值。如果 session id 为 null,则 停止运行这些步骤,并表现为所请求的服务不可 用。

  4. 如果会话活跃会话列表中,并且 session id 是其会话 ID,则令 session 为该 会话。否则,停止运行这些步骤,并表现得如同 所请求的服务不可用。

  5. 运行任何其他实现定义的步骤,以决定是否 应接受该连接;如果不接受,则停止运行这些 步骤,并表现为所请求的服务不可用。

  6. 否则,将 connection 追加到 session会话 WebSocket 连接,并在服务器选择接受传入连接时,继续执行 WebSocket 服务器端要求

我们是否支持单个会话使用多于 1 个 连接?

当为 WebSocket 连接 connection 接收到 WebSocket 消息,其类型为 type 且数据为 data 时,远端 必须在给定 connectiontypedata 的情况下处理传入消息

当对 WebSocket 连接 connection 开始 WebSocket 关闭握手,或当该WebSocket 连接关闭时, 远端必须在给定 connection 的情况下处理连接 关闭

注:需要这两个条件,因为 WebSocket 连接可能在没有关闭握手的情况下被关闭。

要在给定会话 session 的情况下,构造 WebSocket 资源名称

  1. 如果 session 为 null,返回 "/session"

  2. 返回将字符串 "/session/" 与 session会话 ID 连接起来的结果。

要在给定WebSocket 监听器 listener会话 session 的情况下,构造 WebSocket URL

  1. resource name 为以 session 调用构造 WebSocket 资源名称 的结果。

  2. 返回一个WebSocket URI,其构造方式为:将 host 设置为 listener主机,port 设置为 listener端口,path 设置为 resource name;如果 listener安全标志已设置,则遵循 wss-URI 构造,否则遵循 ws-URL 构造。

要在给定 resource name 的情况下,获取 WebSocket 资源的会话 ID

  1. 如果 resource name 不是以字节字符串 "/session/" 开头,则返回 null。

  2. session idresource name 中跟在 "/session/" 前缀之后的字节。

  3. 如果 session id 不是 UUID 的字符串表示,则返回 null。

  4. 返回 session id

要在给定会话 session 的情况下,开始监听 WebSocket 连接
  1. 如果远端想要重用活跃监听器中的某个现有WebSocket 监听器,则令 listener 为该 监听器。否则,令 listener 为一个新的WebSocket 监听器,其具有 由实现定义的主机端口安全 标志,以及一个空的WebSocket 资源列表

  2. resource name 为以 session 调用构造 WebSocket 资源名称 的结果。

  3. resource name 追加到 listenerWebSocket 资源列表

  4. listener 追加远端活跃监听器

  5. 返回 listener

注:处理多个会话的中介节点可以使用一个 或多个 WebSocket 监听器。WebDriver 定义 端点节点一次最多支持一个会话,因此预期 它只会有单个监听器。

注:对于端点 节点,上述步骤中的host 通常会是 "localhost"。

要在给定 WebSocket 连接 connection、类型 type 和数据 data 的情况下处理 传入消息
  1. 如果 type 不是text,则在给定 connection、 null 和invalid argument 的情况下发送错误响应,最后 返回。

  2. 断言data 是一个标量值字符串,因为 WebSocket 处理 UTF-8 编码数据中的错误否则已经 会使 WebSocket 连接失败

    似乎没有内容 定义 UTF-8 错误使用什么状态码

  3. 如果存在一个BiDi 会话与连接关联 connection, 则令 session 为该会话。否则,如果 connection未与会话关联的 WebSocket 连接中,则令 session 为 null。否则,返回。

  4. parsed 为在给定 data 的情况下将 JSON 解析为 Infra 值的结果。如果这抛出异常,则在给定 connection、 null 和invalid argument 的情况下发送错误响应,并 最后返回。

  5. 如果 session 非 null 且不在活动会话中,则返回。

  6. parsed远端定义匹配。 如果这产生 匹配:

    1. matched 为表示匹配数据的映射

    2. 断言:matched 包含 "id"、"method" 和 "params"。

    3. command idmatched["id"]。

    4. methodmatched["method"]

    5. command命令名称method 的命令。

    6. 如果 session 为 null 且 command 不是静态命令,则 在给定 connectioncommand idinvalid session id 的情况下发送错误响应,并返回。

    7. 并行运行以下步骤:

      1. result 为对于 command,在给定 session命令参数 matched["params"] 的情况下运行远端步骤所得的结果

      2. 如果 result 是一个错误,则在给定 connectioncommand idresult错误代码的情况下发送 错误响应,并最后 返回。

      3. valueresult 的数据。

      4. 断言:value结果类型的定义匹配, 该结果类型对应于命令 名称method 的命令。

      5. 如果 method 是 "session.new",则令 session活动会话列表中的条目,其会话 ID等于 value 的 "sessionId" 属性;将 connection 追加session会话 WebSocket 连接,并 从未与会话关联的 WebSocket 连接中移除 connection

      6. response 为一个新的映射,它与 CommandResponse 产生式匹配,该产生式在 本地端定义 中,其 id 字段设置为 command idvalue 字段设置为 value

      7. serialized 为在给定 response 的情况下将 infra 值序列化为 JSON 字节的结果。

      8. connection发送 WebSocket 消息,该消息由 serialized 组成。

  7. 否则:

    1. command id 为 null。

    2. 如果 parsed 是一个映射, 且 parsed["id"] 存在并且是一个 大于或等于零的整数,则将 command id 设置为该整数。

    3. error codeinvalid argument

    4. 如果 parsed 是一个映射, 且 parsed["method"] 存在并且是一个 字符串,但 parsed["method"] 不在所有命令名称的集合中,则将 error code 设置为unknown command

    5. 在给定 connectioncommand iderror code 的情况下发送错误响应

要在给定设置对象 settings 的情况下获取相关 navigables

  1. related navigables 为空集合

  2. 如果 settings相关全局对象是一个 Window

    1. navigable相关全局对象关联 Document节点 navigable

    2. 如果 navigable 非 null,则将 navigable 追加到 related navigables

  3. 否则,如果 settings 所指定的全局对象是一个 WorkerGlobalScope, 则对于该全局对象所有者集合中的每个 owner

    1. navigable 为 null。

    2. 如果 owner 是一个Document,则将 navigable 设置为 owner节点 navigable

    3. 如果 navigable 非 null,则将 navigable 追加到 related navigables

  4. 返回 related navigables

要在给定一个 context id navigable ids列表的情况下通过 id 获取 navigables

  1. result 为空集合

  2. 对于 navigable ids 中的每个 navigable id

    1. 如果存在 id 为 navigable idnavigable,则令 navigable 为该 navigable,否则为 null。

    2. 如果 navigable 非 null,则将 navigable 追加result

  3. 返回 result

要在给定navigables navigables列表的情况下获取 顶级 traversables

  1. result 为空集合

  2. 对于 navigables 中的每个 navigable

    1. navigable追加顶级 traversableresult

  3. 返回 result

要在给定 context id navigable ids列表的情况下通过 id 获取有效 navigables

  1. result 为空集合

  2. 对于 navigable ids 中的每个 navigable id

    1. navigable尝试navigable id 获取 navigable的结果。

    2. navigable 追加result

  3. 返回带有数据 result成功

要在给定 context id navigable ids列表的情况下通过 id 获取有效顶级 traversables

  1. result 为空集合

  2. 对于 navigable ids 中的每个 navigable id

    1. navigable尝试navigable id 获取 navigable的结果。

    2. 如果 navigable 不是顶级 traversable,则返回带有错误代码 invalid argument错误

    3. navigable 追加result

  3. 返回带有数据 result成功

要在给定 sessionbody 的情况下发出事件
  1. 断言bodyEvent 产生式匹配。

  2. serialized 为在给定 body 的情况下将 infra 值序列化为 JSON 字节的结果。

  3. 对于 session会话 WebSocket 连接中的每个 connection

    1. connection发送 WebSocket 消息,该消息由 serialized 组成。

要在给定 WebSocket 连接 connectioncommand iderror code 的情况下发送错误 响应
  1. error data 为一个新的映射,与 本地端定义中的 ErrorResponse 产生式匹配, 其中 id 字段 设置为 command iderror 字段设置为 error codemessage 字段设置为一个实现定义的字符串, 包含对所发生错误的人类可读定义,并且 stacktrace 字段可选地设置为一个实现定义的 字符串,包含错误发生时活动栈帧的栈跟踪报告。

  2. response 为在给定 error data 的情况下将 infra 值序列化为 JSON 字节 的结果。

    注:command id 可以为 null,在 这种情况下,id 字段也会 被设置为 null,而不会从 response 中省略。

  3. connection发送 WebSocket 消息,该消息由 response 组成。

要在给定 WebSocket 连接 connection 的情况下处理连接 关闭

  1. 如果存在一个BiDi 会话与连接关联 connection

    1. session与连接关联 connectionBiDi 会话

    2. session会话 WebSocket 连接中移除 connection

  2. 否则,如果未与会话关联的 WebSocket 连接 包含 connection,则从该集合中移除 connection

注: 这不会结束任何会话

需要挂接到 会话结束,以允许 UA 在需要时关闭 监听器。

要在给定 session 的情况下关闭 WebSocket 连接

  1. 对于 session会话 WebSocket 连接中的每个 connection

    1. 使用 connection 开始 WebSocket 关闭握手

      注:这将导致 对 connection 运行处理连接关闭中的步骤, 这些步骤将清理与 connection 关联的资源。

4.1. 建立连接

WebDriver 客户端通过请求值为 true 的 WebSocket URL 能力,选择加入双向连接。

本规范定义的 WebDriver 新会话算法, 其参数为 sessioncapabilitiesflags,如下:
  1. 如果 flags 包含 "bidi",则返回。

  2. webSocketUrl 为从 capabilities 获取名为 "webSocketUrl" 的属性的结果。

  3. 如果 webSocketUrl 是 undefined,则返回。

  4. 断言webSocketUrl 为 true。

  5. listener 为在给定 session 的情况下开始监听 WebSocket 连接的结果。

  6. webSocketUrl 设置为用 listenersession 构造 WebSocket URL的结果。

  7. capabilities设置名为 "webSocketUrl" 的属性为 webSocketUrl

  8. sessionBiDi 标志设置为 true。

  9. 将 "bidi" 追加到 flags。

实现还应允许客户端建立一个 不是 HTTP 会话BiDi 会话。在这种情况下,WebSocket 服务器的 URL 通过带外方式传达。允许这样做的实现支持 仅 BiDi 会话。当这样的实现准备好接受 启动 WebDriver 会话的请求时,它必须:

  1. 在给定 null 的情况下开始监听 WebSocket 连接

5. 沙盒化脚本执行

自动化工具的一个常见需求是执行这样的脚本:它们可以 访问某个文档的 DOM,但没有关于包含该 文档的 navigable 中运行的脚本对 DOM API 所做任何更改的信息。

BiDi 会话具有一个沙盒映射,它是一个弱 映射,其中 键是 Window 对象,值是字符串与 SandboxWindowProxy 对象之间的映射。

注:这里对沙盒的定义,是试图 将现有实现的行为编纂成规范。它暴露了实现中 以前被规范视为内部的部分,尤其是 平台对象的内部状态(通常以浏览器 引擎主要实现语言中的原生对象来实现)与 ECMAScript 可见状态之间的 区别。由于现有沙盒 实现发生在引擎的低层,实现要在 所有细节上收敛到本规范可能是一个缓慢过程。在 此期间,鼓励实现者提供有关其与规范 差异的详细文档,并鼓励此特性的用户 显式测试在沙盒中运行的脚本是否能在所有实现中工作。

5.1. 沙盒 Realm

每个沙盒都是一个唯一的 ECMAScript Realm。但是,沙盒 realm 通过 SandboxProxy 对象提供对现有 Window realm 中平台对象的访问。

要在给定 namenavigable 的情况下获取或 创建沙盒 realm
  1. 如果 name 为空字符串,则返回带有 错误代码 invalid argument错误

  2. windownavigable活动窗口

  3. 如果沙盒映射不 包含 window,则将沙盒映射[window] 设置为新的映射

  4. sandboxes沙盒映射[window]。

  5. 如果 sandboxes 不包含 name,则将 sandboxes[name] 设置为用 navigable 调用创建沙盒 realm的结果。

  6. 返回带有数据 sandboxes[name] 的成功

要用 window 创建沙盒 realm

定义 沙盒 realm 的创建。这将返回一个 SandboxWindowProxy, 其包装 window

要在给定 target realm 的情况下获取沙盒 名称

  1. realms maps获取沙盒映射的值所得的结果。

  2. 对于 realms maps 中的每个 realms map

    1. 对于 realms map 中的每个 namerealm

      1. 如果 realmtarget realm,则返回 name

  3. 返回 null。

5.2. 沙盒代理对象

SandboxProxy 对象是一个特异对象,用于调解对 另一个 realm 中对象的沙盒化 访问。沙盒代理对象被设计为强制执行 以下限制:

不存在 SandboxProxy 接口对象。

详细定义 SandboxProxy 如何工作

要获取解包装的 object
  1. 只要 objectSandboxProxySandboxWindowProxy, 就将 object 设置为它的 被包装对象。

  2. 返回 object

5.3. SandboxWindowProxy

SandboxWindowProxy 是一个特异对象,表示由 SandboxProxy 对象包装的 Window 对象。这提供了对 Window 全局中该数据的沙盒化 访问。

定义它如何工作。

6. 用户上下文

用户上下文表示 远端内零个或多个 顶级 traversable的集合。 每个用户上下文都有 一个关联的存储 分区,因此远端数据不会在不同的用户上下文之间 共享。

目前还不清楚这是不是 正式定义用户上下文概念或其与存储交互的 最佳方式。

注:Infra 规范使用术语“user agent”来指代 与用户上下文相同的概念。然而,这与 “user agent”用来表示包含多个用户上下文的整个 Web 客户端这一用法 不兼容。虽然这种差异对 Web 内容不可见, 但它可通过 WebDriver 被观察到,因此我们避免使用该术语。

用户上下文具有一个用户上下文 id, 它是在用户上下文创建时设置的唯一字符串。

navigable 具有一个关联用户上下文,它是一个用户上下文

当新的顶级 traversable被创建时,其关联用户上下文 被设置为用户上下文集合中的某个用户上下文。

注:在某些情况下,用户上下文会在 顶级 traversable创建时由规范设置;但是在不存在此类 要求的情况下,关联用户上下文对于顶级 traversable是实现定义的。

我们是否应指定具有非 null opener 的顶级 traversable具有与其 opener 相同的关联用户上下文? 需要检查这是否是现有实现会强制执行的内容。

子 navigable关联用户上下文是 其 父级关联用户上下文

如果某个用户上下文不是任何 顶级 traversable关联 用户上下文,则它是一个空用户上下文

默认用户 上下文是一个用户 上下文,其用户上下文 id"default"

实现具有一个用户上下文集合,它是一个由用户上下文组成的集合。初始时,它 包含默认 用户上下文

实现可以在任何时候将新的用户上下文追加用户上下文集合, 例如响应用户操作。

注:这里的“任何时候”包括实现 启动期间,因此给定 实现可能总是在用户上下文集合中有多个条目。

实现可以在任何 时候从用户上下文集合移除任何空用户上下文,但 默认用户 上下文除外。然而,它们并非必须移除这类用户上下文。不是空用户上下文用户上下文不得从 用户 上下文集合中移除。

BiDi 会话具有一个 用户上下文到接受不安全 证书覆盖映射,它是 用户上下文与 boolean 之间的映射

BiDi 会话具有一个用户 上下文到代理配置映射,它是 用户上下文代理配置之间的映射

模拟网络条件结构体是一个具有以下内容的结构体

BiDi 会话具有模拟网络条件,它是 一个结构体,具有 一个名为 default network conditions,它是 一个 模拟网络条件结构体或 null;一个 名为 user context network conditions, 它 是用户 上下文模拟网络条件结构体之间的弱映射; 以及一个名为 navigable network conditions, 它是 navigable模拟 网络条件结构体之间的 弱映射。

用户上下文用户 上下文集合中被移除时,移除用户上下文订阅

移除 用户上下文订阅

  1. 对于活动会话中的每个 session

    1. subscriptions to remove 为一个集合

    2. 对于 session订阅中的每个 subscription

      1. 如果 subscription用户上下文 id 包含 navigable关联用户上下文用户上下文 id

        1. subscription用户上下文 id移除 navigable关联用户上下文用户上下文 id

        2. 如果 subscription用户上下文 id 为空:

          1. subscription 追加subscriptions to remove

    3. session订阅移除 subscriptions to remove

要在给定 user context id 的情况下获取用户上下文
  1. 对于用户上下文集合中的每个 user context

  2. 如果 user context用户上下文 id等于 user context id

    1. 返回 user context

  3. 返回 null。

要在给定 user context ids 的情况下获取有效用户 上下文

  1. result 为空集合

  2. 对于 user context ids 中的每个 user context id

    1. user context 设置为用 user context id 调用获取用户上下文的结果。

    2. 如果 user context 为 null,则返回带有 错误代码 no such user context错误

    3. user context 追加result

  3. 返回 result

7. 模块

7.1. session 模块

session 模块包含用于监控远端状态的命令和 事件。

7.1.1. 定义

远端定义

SessionCommand = (
  session.End //
  session.New //
  session.Status //
  session.Subscribe //
  session.Unsubscribe
)

本地端定义

SessionResult = (
  session.EndResult /
  session.NewResult /
  session.StatusResult /
  session.SubscribeResult /
  session.UnsubscribeResult
)
要在给定 session 的情况下结束会话
  1. 活动会话中移除 session

  2. 如果活动会话,则将 webdriver-active 标志 设置为 false。

要在给定 session 的情况下清理 会话

  1. 使用 session 关闭 WebSocket 连接

  2. 对于用户上下文集合中的每个 user context

    1. 移除 session用户上下文到接受不安全证书覆盖映射[user context]。

    2. 移除 session用户上下文到代理配置映射[user context]。

  3. 对于 session已阻塞请求映射中的每个 request id →(requestphaseresponse):

    1. 使用 "continue request"、request id 和(response、"incomplete")恢复

  4. 对于 session网络收集器中的每个 collector

    1. collector idcollector收集器

    2. 对于已收集的网络 数据中的每个 collected data,使用 collected datacollector id 从数据中移除收集器

  5. 对于 session屏幕录制映射中的每个 screencast recording

    1. 给定 screencast recording停止屏幕录制

    2. 屏幕录制映射移除 screencast recording

  6. 如果活动会话,则清理远端状态

  7. 执行任何特定于实现的清理步骤。

清理远端 状态
  1. 清空发送请求前映射

  2. 默认缓存行为设置为 "default"。

  3. 清空navigable 缓存行为映射

  4. 执行实现定义的步骤,以启用当前远端配置中通常启用的任何 特定于实现的资源缓存。

7.1.2. 类型

7.1.2.1. session.CapabilitiesRequest 类型
session.CapabilitiesRequest = {
  ? alwaysMatch: session.CapabilityRequest,
  ? firstMatch: [*session.CapabilityRequest]
}

session.CapabilitiesRequest 类型表示为会话请求的能力。

7.1.2.2. session.CapabilityRequest 类型

远端定义本地端定义

session.CapabilityRequest = {
  ? acceptInsecureCerts: bool,
  ? browserName: text,
  ? browserVersion: text,
  ? platformName: text,
  ? proxy: session.ProxyConfiguration,
  ? unhandledPromptBehavior: session.UserPromptHandler,
  Extensible
}

session.CapabilityRequest 类型表示一组特定的 请求能力。

WebDriver BiDi 定义了额外的 WebDriver 能力。下表列举了每个实现都必须为 WebDriver BiDi 支持的能力。

能力: WebSocket URL
键: "webSocketUrl"
值类型: boolean
描述: 定义当前会话对双向连接的支持。
"webSocketUrl" 能力的额外能力反序列化 算法,参数为 value,如下:
  1. 如果 value 不是 boolean,则返回带有代码 invalid argument错误

  2. 返回带有数据 value成功

"webSocketUrl" 能力的匹配能力序列化 算法, 参数为 value,如下:
  1. 如果 value 为 false,则返回带有数据 null 的成功

  2. 返回带有数据 true 的成功

7.1.2.3. session.ProxyConfiguration 类型

远端定义本地端定义

session.ProxyConfiguration = {
   session.AutodetectProxyConfiguration //
   session.DirectProxyConfiguration //
   session.ManualProxyConfiguration //
   session.PacProxyConfiguration //
   session.SystemProxyConfiguration
}

session.AutodetectProxyConfiguration = (
   proxyType: "autodetect",
   Extensible
)

session.DirectProxyConfiguration = (
   proxyType: "direct",
   Extensible
)

session.ManualProxyConfiguration = (
   proxyType: "manual",
   ? httpProxy: text,
   ? sslProxy: text,
   ? session.SocksProxyConfiguration,
   ? noProxy: [*text],
   Extensible
)

session.SocksProxyConfiguration = (
   socksProxy: text,
   socksVersion: 0..255,
)

session.PacProxyConfiguration = (
   proxyType: "pac",
   proxyAutoconfigUrl: text,
   Extensible
)

session.SystemProxyConfiguration = (
   proxyType: "system",
   Extensible
)

7.1.2.4. session.UserPromptHandler 类型

远端定义本地端定义

session.UserPromptHandler = {
  ? alert: session.UserPromptHandlerType,
  ? beforeUnload: session.UserPromptHandlerType,
  ? confirm: session.UserPromptHandlerType,
  ? default: session.UserPromptHandlerType,
  ? file: session.UserPromptHandlerType,
  ? prompt: session.UserPromptHandlerType,
}

session.UserPromptHandler 类型表示 用户提示处理程序的配置。

注:file 处理文件选择器。"accept" 和 "dismiss" 会关闭 选择器。"ignore" 会保持选择器打开。

7.1.2.5. session.UserPromptHandlerType 类型

远端定义本地端定义

session.UserPromptHandlerType = "accept" / "dismiss" / "ignore";

session.UserPromptHandlerType 类型表示 用户提示处理程序的行为。

7.1.2.6. session.Subscription 类型
session.Subscription = text

session.Subscription 类型表示唯一的订阅标识符。

7.1.2.7. session.SubscribeParameters 类型
session.SubscribeParameters = {
  events: [+text],
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

session.SubscribeParameters 类型表示 订阅一组特定事件的请求。

7.1.2.8. session.UnsubscribeByIDRequest 类型
session.UnsubscribeByIDRequest = {
  subscriptions: [+session.Subscription],
}

session.UnsubscribeByIDRequest 类型表示 移除由订阅 ID 标识的事件订阅的请求。

7.1.2.9. session.UnsubscribeByAttributesRequest 类型
session.UnsubscribeByAttributesRequest = {
  events: [+text],
}

session.UnsubscribeByAttributesRequest 类型表示 使用订阅属性取消订阅的请求。

7.1.3. 命令

7.1.3.1. session.status 命令

session.status 命令返回关于 远端是否处于可创建新会话状态的信息, 但也可以另外包含特定于实现的任意元信息。

这是一个静态命令

命令类型
session.Status = (
  method: "session.status",
  params: EmptyParams,
)
返回类型
session.StatusResult = {
  ready: bool,
  message: text,
}

给定 sessioncommand parameters 时,远端步骤为:

  1. body 为一个具有以下属性的新映射

    "ready"
    远端就绪状态
    "message"
    一个实现定义的字符串,用于解释远端就绪状态
  2. 返回带有数据 body成功

7.1.3.2. session.new 命令

session.new 命令允许创建新的 BiDi 会话

注:以这种方式创建的会话将不能 通过 HTTP 访问。

这是一个静态命令

命令类型
session.New = (
  method: "session.new",
  params: session.NewParameters
)

session.NewParameters = {
  capabilities: session.CapabilitiesRequest
}
返回类型
session.NewResult = {
  sessionId: text,
  capabilities: {
    acceptInsecureCerts: bool,
    browserName: text,
    browserVersion: text,
    platformName: text,
    setWindowRect: bool,
    userAgent: text,
    ? proxy: session.ProxyConfiguration,
    ? unhandledPromptBehavior: session.UserPromptHandler,
    ? webSocketUrl: text,
    Extensible
  }
}

给定 sessioncommand parameters 时,远端步骤为:

  1. 如果 session 不是 null,则返回一个错误,错误 代码为 session not created

  2. 如果实现因任何原因无法启动新会话,则返回 一个错误,错误代码为 session not created

  3. flags 为一个包含 "bidi" 的集合

  4. capabilities json 为使用 command parametersflags 尝试处理能力 所得的结果。

  5. capabilities 为用 capabilities json 调用将 JSON 派生的 JavaScript 值转换为 Infra 值的结果。

  6. session 为使用 capabilitiesflags 尝试创建会话所得的结果。

  7. sessionBiDi 标志设置为 true。

    注:此会话的连接将由调用者设置为当前连接。

  8. body 为一个新的映射, 它与 session.NewResult 产生式匹配, 其 sessionId 字段设置为 session会话 ID,并且 capabilities 字段设置为 capabilities

  9. 返回带有数据 body成功

7.1.3.3. session.end 命令

session.end 命令结束当前 会话

命令类型
session.End = (
  method: "session.end",
  params: EmptyParams
)

返回类型
session.EndResult = EmptyResult

给定 sessioncommand parameters 时,远端步骤为:

  1. 使用 session 结束会话

  2. 返回带有数据 null 的成功,并并行运行以下 步骤:

    1. 等到发送 WebSocket 消息步骤已使用 对此命令的 响应被调用。

      这 是相当不精确的语言,但希望意图很清楚: 在开始关闭连接之前,我们要先发送命令响应。

    2. 使用 session 清理会话

7.1.3.4. session.subscribe 命令

session.subscribe 命令会全局地或针对一组 navigable 启用某些事件。

这需要 泛化,以便也适用于 realm。

命令类型
session.Subscribe = (
  method: "session.subscribe",
  params: session.SubscribeParameters
)
返回类型
session.SubscribeResult = {
  subscription: session.Subscription,
}
给定 sessioncommand parameters 时,远端步骤为:
  1. event names 为空集合

  2. 对于 command parameters["events"] 中的每个条目 name,令 event namesevent names尝试name 获得一组 事件名称的结果的并集

  3. input user context ids 为用 command parameters[userContexts] 创建集合所得的结果。

  4. input context ids 为用 command parameters[contexts] 创建集合所得的结果。

  5. 如果 input user context ids 非空且 input context ids 非空, 则返回带有错误 代码 invalid argument错误

  6. subscription navigables 为一个集合

  7. top-level traversable context ids 为一个集合

  8. 如果 input context ids 非空:

    1. navigables尝试input context ids 通过 id 获取有效 navigables的结果。

    2. subscription navigables 设置为用 navigables 调用获取 顶级 traversables的结果。

    3. 对于 subscription navigables 中的每个 navigable

      1. navigablenavigable id 追加top-level traversable context ids

  9. 否则,如果 input user context ids 非空:

    1. 对于 input user context ids 中的每个 user context id

      1. user context 为用 user context id 调用获取用户上下文的结果。

      2. 如果 user context 为 null,则返回带有错误代码 no such user context错误

      3. 对于所有其关联用户上下文user context顶级 traversable列表中的每个 top-level traversable

        1. top-level traversable 追加subscription navigables

  10. 否则,将 subscription navigables 设置为远端中所有 顶级 traversable组成的集合

  11. subscription 为一个订阅,其 订阅 id设置为 UUID 的字符串表示, 事件名称设置为 event names顶级 traversable id设置为 top-level traversable context ids,并且 用户上下文 id设置为 input user context ids

  12. subscribe step events 为一个新的映射

  13. 对于 event names 中的每个 event name

    1. 如果事件(其事件 名称event name)没有定义远端订阅步骤, 则继续;

    2. existing navigables 为使用 sessionevent name 调用启用了某个事件的顶级 traversable 集合的结果。

    3. subscribe step events[event name] 设置为 subscription navigablesexisting navigables差集

  14. subscription 追加到 session订阅

  15. subscription订阅 id追加到 session已知订阅 id

  16. 使用以下小于算法,按升序排序 subscribe step events;给定两个键为 event name oneevent name two 的条目:

    1. event one 为名称为 event name one事件

    2. event two 为名称为 event name two事件

    3. 如果 event one订阅 优先级小于 event two 的订阅优先级,则返回 true,否则返回 false。

  17. 如果 subscription全局的,则令 include global 为 true, 否则令 include global 为 false。

  18. 对于 subscribe step events 中的每个 event namenavigables

    1. 事件(其事件 名称event name)运行远端订阅步骤,给定 sessionnavigablesinclude global

  19. body 为一个新的映射, 它与 session.SubscribeResult 产生式匹配, 其 subscription 字段设置为 subscription订阅 id

  20. 返回带有数据 body成功

7.1.3.5. session.unsubscribe 命令

session.unsubscribe 命令会全局地或针对一组 navigable 禁用事件。

这需要 泛化,以便也适用于 realm。

命令类型
session.Unsubscribe = (
  method: "session.unsubscribe",
  params: session.UnsubscribeParameters,
)

session.UnsubscribeParameters = session.UnsubscribeByAttributesRequest / session.UnsubscribeByIDRequest
返回类型
session.UnsubscribeResult = EmptyResult
给定 sessioncommand parameters 时,远端步骤为:
  1. 如果 command parameters包含 "subscriptions":

    注:该条件意味着 command parameters 与 session.UnsubscribeByAttributesRequest 产生式匹配。

    1. event names 为空集合

    2. 对于 command parameters["events"] 中的每个条目 name, 令 event namesevent names尝试name 获得 一组事件名称所得结果的并集

    3. new subscriptions 为一个列表

    4. matched events 为一个集合

    5. 对于 session订阅中的每个 subscription

      1. 如果 subscription事件名称event names交集是一个空集合

        1. subscription 追加new subscriptions

        2. 继续

      2. 如果 subscription 不是全局的

        1. subscription 追加new subscriptions

        2. 继续

      3. subscription event namessubscription事件名称克隆

      4. 对于 event names 中的每个 event name

        1. 如果 subscription event names 包含 event name

          1. event name 追加matched events

          2. subscription event names移除 event name

      5. 如果 subscription event names 非空:

        1. cloned subscription 为一个订阅,其 订阅 id设置 为 subscription订阅 id事件名称设置为一个新的 集合,其中包含 subscription event names

        2. cloned subscription 追加new subscriptions

    6. 如果 matched events等于 event names,则返回带有 错误代码 invalid argument错误

    7. session订阅设置为 new subscriptions

  2. 否则:

    1. subscriptions 为用 command parameters[subscriptions] 创建 集合所得的结果。

    2. unknown subscription idssubscriptionssession已知订阅 id之间的差集

    3. 如果 unknown subscription ids 非空:

      1. 返回带有错误代码 invalid argument错误

    4. subscriptions to remove 为空集合

    5. 对于 session订阅中的每个 subscription

      1. 如果 subscriptions 包含 subscription订阅 id

        1. subscription 追加subscriptions to remove

    6. session已知订阅 id设置为 session已知订阅 idsubscriptions之间的差集

    7. session订阅移除 subscriptions to remove 中的每一项。

  3. 返回带有数据 null 的成功

7.2. browser 模块

browser 模块包含用于 管理远端浏览器进程的命令。

7.2.1. 定义

远端定义

BrowserCommand = (
  browser.Close //
  browser.CreateUserContext //
  browser.GetClientWindows //
  browser.GetUserContexts //
  browser.RemoveUserContext //
  browser.SetClientWindowState //
  browser.SetDownloadBehavior
)

本地端定义

BrowserResult = (
  browser.CloseResult /
  browser.CreateUserContextResult /
  browser.GetClientWindowsResult /
  browser.GetUserContextsResult /
  browser.RemoveUserContextResult /
  browser.SetClientWindowStateResult /
  browser.SetDownloadBehaviorResult
)

7.2.2. 窗口

每个顶级 traversable都关联到单个客户端 窗口,该窗口表示一个矩形区域,其中包含 用于在其可见性状态为 "visible" 时渲染该顶级 traversable活动文档视口,以及与显示该 traversable 相关联的任何浏览器特定用户界面元素 (例如任何 URL 栏、工具栏或 OS 窗口装饰)。

客户端窗口具有一个客户端窗口 id,它是唯一 标识该窗口的字符串。

客户端窗口具有一个x 坐标,它是 Web 暴露屏幕区域左边缘与窗口左边缘之间的 CSS 像素数,若这对于某个 特定窗口没有意义则为零。

客户端窗口具有一个y 坐标,它是 Web 暴露屏幕区域上边缘与窗口上边缘之间的 CSS 像素数,若这对于某个 特定窗口没有意义则为零。

客户端窗口具有一个宽度,它是 窗口矩形的宽度,以 CSS 像素计。

客户端窗口具有一个高度,它是 窗口矩形的高度,以 CSS 像素计。

最大化 客户端窗口 window,实现应当要么 执行与平台最大化 window 概念相对应的步骤,要么 定位 window,使其x 坐标尽可能接近 0,其y 坐标尽可能接近 0, 其宽度尽可能接近 Web 暴露屏幕区域的宽度,且其高度尽可能接近 Web 暴露屏幕区域的高度。如果支持这两个选项中的任一个, 则支持最大化客户端窗口

最小化 客户端窗口 window,实现应当要么 执行与平台最小化 window 概念相对应的步骤,要么 以其他方式隐藏 window,使得与 window 关联的 顶级 traversable中的所有活动文档都具有 "hidden" 的可见性状态,并且 window宽度高度都尽可能接近 0。如果支持这两个 选项中的任一个,则支持最小化客户端窗口

还原 客户端窗口 window,实现应确保它 既不处于平台定义的最大化状态,也不处于平台定义的 最小化状态,并且如果存在一个或多个与 window 关联的顶级 traversable, 其中至少一个具有处于 "visible" 状态的活动文档。如果支持这一点,则支持还原客户端 窗口

要在给定 window 的情况下获取 客户端窗口状态

  1. documents 为空列表

  2. visible documents 为空列表

  3. 对于每个顶级 traversable traversable

    1. 如果 traversable客户端窗口不是 window,则 继续。

    2. documenttraversable活动文档

    3. document 追加documents

    4. 如果 document可见性状态为 "visible", 则将 document 追加visible documents

  4. 对于 visible documents 中的每个 document

    1. 如果 document全屏元素不是 null,则返回 "fullscreen"。

  5. 如果 visible documentsdocuments 不是 ,或者如果 window 以其他方式处于特定于 OS 的 最小化状态,则返回 "minimized"。

    注:这通常但不一定意味着 window宽度高度等于 0。

  6. 如果 window 处于特定于 OS 的最大化状态,则返回 "maximized"。

    注:这通常但不一定意味着 window宽度等于Web 暴露屏幕区域的宽度,并且 window高度等于 Web 暴露屏幕区域的高度。

  7. 返回 "normal"。

要在给定 windowstate 的情况下设置 客户端窗口状态

  1. current state 为使用 window 获取客户端窗口状态的结果。

  2. 如果 current state 是 "fullscreen"、"maximized" 或 "minimized",且等于 state,则返回带有数据 null 的成功

  3. 在以下条件及其关联步骤列表中,运行第一个关联条件为 true 的步骤集:

    "fullscreen"
    如果不支持全屏,则返回带有错误代码 unsupported operation错误
    "normal"
    如果对于 window支持还原客户端窗口, 则返回带有 错误代码 unsupported operation错误
    "maximize"
    如果对于 window支持最大化客户端窗口, 则返回带有 错误代码 unsupported operation错误
    "minimize"
    如果对于 window支持最小化客户端窗口, 则返回带有 错误代码 unsupported operation错误
  4. documents 为空列表

  5. 对于每个顶级 traversable traversable

    1. 如果 traversable 的关联客户端窗口不是 window,则 继续。

    2. documenttraversable活动文档

    3. document 追加到 documents

  6. 如果 documents,则返回 带有错误 代码 no such client window错误

  7. 如果 current state 是 "fullscreen":

    1. 对于 documents 中的每个 document

      1. 使用 document 完全退出全屏

        注:对于窗口中并非全屏的 文档,这是无操作。

  8. 如果 current state 是 "maximized" 或 "minimized":

    1. 还原客户端窗口 window

  9. 根据 state 的值进行切换:

    "fullscreen"
    1. 对于 documents 中的每个 document

      1. 如果 document可见性状态为 "visible", 则使用 documentdocument element使元素全屏

      2. 中断

    "maximize"
    1. 最大化客户端窗口 window
    "minimize"
    1. 最小化客户端窗口 window
  10. 返回带有数据 null 的成功

7.2.3. 类型

7.2.3.1. browser.ClientWindow 类型
browser.ClientWindow = text;

browser.ClientWindow 唯一标识一个客户端窗口

7.2.3.2. browser.ClientWindowInfo 类型
browser.ClientWindowInfo = {
  active: bool,
  clientWindow: browser.ClientWindow,
  height: js-uint,
  state: "fullscreen" / "maximized" / "minimized" / "normal",
  width: js-uint,
  x: js-int,
  y: js-int,
}

browser.ClientWindowInfo 类型表示 客户端窗口的属性。

要在给定 client window 的情况下获取客户端 窗口信息
  1. client window idclient window客户端窗口 id

  2. state 为使用 client window 调用获取客户端窗口状态的结果。

  3. 如果 client window 能够接收从操作系统传送来的键盘输入, 则令 active 为 true,否则令 active 为 false。

    注:这可能意味着某个顶级 traversable(其客户端窗口client window)具有系统焦点,也可能意味着浏览器自身的 用户界面当前具有焦点。

  4. client window info 为一个映射, 它与 browser.ClientWindowsInfo 产生式匹配,其 clientWindow 字段设置为 client window idstate 字段设置为 statex 字段设置为 client windowx 坐标y 字段设置为 client windowy 坐标width 字段设置 为 client window宽度height 字段 设置为 client window高度,且 active 字段设置为 active

  5. 返回 client window info

7.2.3.3. browser.UserContext 类型
browser.UserContext = text;

browser.UserContext 唯一标识一个用户 上下文

7.2.3.4. browser.UserContextInfo 类型
browser.UserContextInfo = {
  userContext: browser.UserContext
}

browser.UserContextInfo 类型表示用户上下文的属性。

7.2.4. 命令

7.2.4.1. browser.close 命令

browser.close 命令终止所有 WebDriver 会话,并清理远程浏览器实例中的自动化状态。

命令类型
browser.Close = (
  method: "browser.close",
  params: EmptyParams,
)
返回类型
browser.CloseResult = EmptyResult
给定 sessioncommand parameters 时,远端步骤为:
  1. 使用 session 结束会话

  2. 如果活动会话不是,实现可以 返回带有错误 代码 unable to close browser错误,然后 并行运行以下步骤:

    1. 等到发送 WebSocket 消息步骤已使用 对此命令的 响应被调用。

    2. 使用 session 清理会话

    注:当浏览器具有多个自动化 会话时的行为目前未指定。可能是任何会话都可以关闭 浏览器,也可能只有最后一个打开的会话才能实际关闭浏览器, 或者只有第一个启动的会话可以。此行为可能会在本规范的未来版本中 完全指定。

  3. 对于活动会话中的每个 active session

    1. 结束 会话 active session

    2. 使用 active session 清理会话

  4. 返回带有数据 null 的成功,并并行运行以下步骤。

    1. 等到发送 WebSocket 消息步骤已使用 对此命令的 响应被调用。

    2. 使用 session 清理会话

    3. 在不提示卸载的情况下关闭任何顶级 traversable

    4. 执行实现定义的步骤,以清理与自动化控制下的远端关联的资源。

      注:例如,这可能包括 干净地关闭与自动化控制下的浏览器关联的任何 OS 级 进程、移除临时 状态(例如远端在自动化控制期间创建的用户配置文件数据), 或关闭WebSocket 监听器。由于 浏览器和操作系统之间存在差异,无法在这里详细 指定本地端可依赖的精确不变式。

7.2.4.2. browser.createUserContext 命令

browser.createUserContext 命令创建一个 用户上下文

命令类型
browser.CreateUserContext = (
  method: "browser.createUserContext",
  params: browser.CreateUserContextParameters,
)

browser.CreateUserContextParameters = {
  ? acceptInsecureCerts: bool,
  ? proxy: session.ProxyConfiguration,
  ? unhandledPromptBehavior: session.UserPromptHandler
}
返回类型
browser.CreateUserContextResult = browser.UserContextInfo

给定 sessioncommand parameters 时,远端步骤为:

  1. user context 为一个新的用户上下文

  2. 如果 command parameters 包含 "acceptInsecureCerts":

    注:如果设置了 "acceptInsecureCerts", 它会覆盖 接受不安全 TLS 标志的行为。

    1. acceptInsecureCertscommand parameters["acceptInsecureCerts"]:

    2. 如果 acceptInsecureCerts 为 true,且端点节点不支持 接受不安全 TLS 连接,则返回带有 错误代码 unsupported operation错误

    3. session用户上下文到接受不安全证书覆盖映射[user context] 设置acceptInsecureCerts

  3. 如果 command parameters 包含 "unhandledPromptBehavior", 则将未处理提示行为覆盖 映射[user context] 设置command parameters["unhandledPromptBehavior"]。

  4. 如果 command parameters 包含 "proxy":

    1. proxy configurationcommand parameters["proxy"]。

    2. 如果远端无法按用户 上下文配置代理设置, 或无法用 proxy configuration 配置代理,则返回带有 错误代码 unsupported operation错误

    3. session用户上下文到代理 配置映射[user context] 设置proxy configuration

  5. user context 追加用户上下文集合

  6. user context info 为一个映射, 它与 browser.UserContextInfo 产生式匹配,其 userContext 字段设置为 user context用户上下文 id

  7. 返回带有数据 user context info成功

7.2.4.3. browser.getClientWindows 命令

browser.getClientWindows 命令返回 客户端窗口列表。

命令类型
browser.GetClientWindows = (
  method: "browser.getClientWindows",
  params: EmptyParams,
)
返回类型
browser.GetClientWindowsResult = {
  clientWindows: [ * browser.ClientWindowInfo]
}

远端步骤为:

  1. client window ids 为空集合

  2. client windows 为空列表

  3. 对于每个顶级 traversable traversable

    1. client windowtraversable 的关联客户端 窗口

    2. client window idclient window客户端窗口 id

    3. 如果 client window ids 包含 client window id,则继续。

    4. client window id 追加client window ids

    5. client window info 为使用 client window 调用获取 客户端窗口信息的结果。

    6. client window info 追加client windows

  4. result 为一个映射, 它与 browser.GetClientWindowsResult 产生式匹配,其 clientWindows 字段设置为 client windows

  5. 返回带有数据 result成功

7.2.4.4. browser.getUserContexts 命令

browser.getUserContexts 命令返回 用户上下文列表。

命令类型
browser.GetUserContexts = (
  method: "browser.getUserContexts",
  params: EmptyParams,
)
返回类型
browser.GetUserContextsResult = {
  userContexts: [ + browser.UserContextInfo]
}

远端步骤为:

  1. user contexts 为空列表

  2. 对于用户上下文集合中的每个 user context

    1. user context info 为一个映射, 它与 browser.UserContextInfo 产生式匹配,其 userContext 字段设置为 user context用户 上下文 id

    2. user context info 追加user contexts

  3. result 为一个映射, 它与 browser.GetUserContextsResult 产生式匹配,其 userContexts 字段设置为 user contexts

  4. 返回带有数据 result成功

7.2.4.5. browser.removeUserContext 命令

browser.removeUserContext 命令关闭一个 用户上下文及其中的所有 navigable,且不运行 beforeunload 处理程序。

命令类型
browser.RemoveUserContext = (
  method: "browser.removeUserContext",
  params: browser.RemoveUserContextParameters
)

browser.RemoveUserContextParameters = {
  userContext: browser.UserContext
}
返回类型
browser.RemoveUserContextResult = EmptyResult

给定 command parameters 时,远端步骤为:

  1. user context idcommand parameters["userContext"]。

  2. 如果 user context id"default",则返回带有错误代码 invalid argument错误

  3. user context 设置为用 user context id 调用获取用户上下文的结果。

  4. 如果 user context 为 null,则返回带有错误代码 no such user context错误

  5. 对于每个顶级 traversable navigable

    1. 如果 navigable关联用户上下文user context

      1. 在不提示卸载的情况下关闭 navigable

  6. 用户上下文集合移除 user context

  7. 返回带有数据 null 的成功

7.2.4.6. browser.setClientWindowState 命令

browser.setClientWindowState 命令设置 客户端 窗口的尺寸。

命令类型
browser.SetClientWindowState = (
  method: "browser.setClientWindowState",
  params: browser.SetClientWindowStateParameters
)

browser.SetClientWindowStateParameters = {
  clientWindow: browser.ClientWindow,
  (browser.ClientWindowNamedState // browser.ClientWindowRectState)
}

browser.ClientWindowNamedState = (
  state: "fullscreen" / "maximized" / "minimized"
)

browser.ClientWindowRectState = (
  state: "normal",
  ? width: js-uint,
  ? height: js-uint,
  ? x: js-int,
  ? y: js-int,
)
返回类型
browser.SetClientWindowStateResult = browser.ClientWindowInfo

给定 sessioncommand parameters 时,远端步骤为:

  1. 如果实现完全不支持设置客户端窗口状态, 则返回带有错误 代码 unsupported operation错误

  2. 如果存在一个客户端 窗口,其客户端窗口 idcommand parameters["clientWindow"],则令 client window 为该客户端窗口。 否则返回带有错误 代码 no such client window错误

  3. 尝试使用 client windowcommand parameters["state"] 设置客户端窗口状态

  4. 如果 command parameters["state"] 是 "normal":

    1. 如果 command parameters 包含 "x",并且 实现支持定位客户端窗口,则将 client windowx 坐标设置为尽可能接近 command parameters["x"] 的值。

    2. 如果 command parameters 包含 "y",并且 实现支持定位客户端窗口,则将 client windowy 坐标设置为尽可能接近 command parameters["y"] 的值。

    3. 如果 command parameters 包含 "width",并且 实现支持调整客户端窗口大小,则将 client window宽度设置为尽可能接近 command parameters["width"] 的值。

    4. 如果 command parameters 包含 "width",并且 实现支持调整客户端窗口大小,则将 client window宽度设置为尽可能接近 command parameters["width"] 的值。

  5. client window info 为使用 client window 调用获取客户端窗口信息的结果。

  6. 返回带有数据 client window info成功

注:为简单起见,这里将所有客户端窗口 操作都建模为 同步。因此,返回的客户端窗口尺寸预期是 窗口达到其新状态之后的尺寸。

7.2.4.7. browser.setDownloadBehavior 命令

下载行为 结构体是一个具有以下内容的结构体

远端具有一个下载行为,它是一个结构体,具有一个 名为 default download behavior,它是一个 下载 行为结构体或 null,以及一个名为 user context download behavior,它是 用户上下文下载 行为结构体之间的弱映射。

命令类型
browser.SetDownloadBehavior = (
  method: "browser.setDownloadBehavior",
  params: browser.SetDownloadBehaviorParameters
)

browser.SetDownloadBehaviorParameters = {
  downloadBehavior: browser.DownloadBehavior / null,
  ? userContexts: [+browser.UserContext]
}

browser.DownloadBehavior = {
  (
    browser.DownloadBehaviorAllowed //
    browser.DownloadBehaviorDenied
  )
}

browser.DownloadBehaviorAllowed = (
  type: "allowed",
  destinationFolder: text
)

browser.DownloadBehaviorDenied = (
  type: "denied"
)
返回类型
browser.SetDownloadBehaviorResult = EmptyResult
要在给定 navigable 的情况下获取下载 行为
  1. user contextnavigable关联用户 上下文

  2. 如果下载 行为user context download behavior 包含 user context,则返回下载行为user context download behavior[user context]。

  3. 返回下载 行为default download behavior

给定 sessioncommand parameters 时,远端步骤为:

  1. 如果 command parameters["downloadBehavior"] 为 null,则令 download behavior 为 null。

  2. 否则:

    1. 如果 command parameters["downloadBehavior"]["type"] 是 "allowed",则令 allowed 为 true,否则令 allowed 为 false。

    2. 如果 command parameters["downloadBehavior"] 包含 "destinationFolder",则令 destinationFoldercommand parameters["downloadBehavior"]["destinationFolder"], 否则令 destinationFolder 为 null。

    3. download behavior 为一个下载 行为结构体,其 allowed 设置为 allowed, 且 destinationFolder 设置 为 destinationFolder

  3. 如果实现不支持所需的 download behavior,则返回 带有错误 代码 unsupported operation错误

  4. 如果 command parametersuserContexts 字段存在:

    1. user contexts尝试command parameters["userContexts"] 获取有效用户上下文 所得的结果。

    2. 对于 user contexts 中的每个 user context

      1. 如果 download behavior 为 null,则从下载行为user context download behavior移除 user context

      2. 否则,将下载 行为user context download behavior[user context] 设置download behavior

  5. 否则,将下载行为default download behavior设置为 download behavior

  6. 返回带有数据 null 的成功

7.3. browsingContext 模块

browsingContext 模块包含与navigable相关的命令和 事件。

注:由于历史原因,此模块称为 browsingContext 而不是 navigable,并且协议使用术语 context 来指代 navigable,尤其是作为命令 和响应参数中的字段时。

导航进度使用一个不可变结构体 WebDriver BiDi 导航状态来传达,它具有以下

id
该导航的导航 id,或者当导航在取得进展前被 取消时为 null。
status
一个状态码,其值为 "canceled"、 "pending" 或 "complete"。
url
导航中正在加载的 URL
suggestedFilename
如果导航是下载,则为建议的文件名,否则为 null。
downloadedFilepath
如果导航是已完成的下载,且下载文件可用,则为已下载文件的 绝对文件路径,否则为 null。
downloadResponse
如果导航是下载,则为响应, 否则为 null。

7.3.1. 定义

远端定义

BrowsingContextCommand = (
  browsingContext.Activate //
  browsingContext.CaptureScreenshot //
  browsingContext.Close //
  browsingContext.Create //
  browsingContext.GetTree //
  browsingContext.HandleUserPrompt //
  browsingContext.LocateNodes //
  browsingContext.Navigate //
  browsingContext.Print //
  browsingContext.Reload //
  browsingContext.SetBypassCSP //
  browsingContext.SetViewport //
  browsingContext.StartScreencast //
  browsingContext.StopScreencast //
  browsingContext.TraverseHistory
)

本地端定义

BrowsingContextResult = (
  browsingContext.ActivateResult /
  browsingContext.CaptureScreenshotResult /
  browsingContext.CloseResult /
  browsingContext.CreateResult /
  browsingContext.GetTreeResult /
  browsingContext.HandleUserPromptResult /
  browsingContext.LocateNodesResult /
  browsingContext.NavigateResult /
  browsingContext.PrintResult /
  browsingContext.ReloadResult /
  browsingContext.SetBypassCSPResult /
  browsingContext.SetViewportResult /
  browsingContext.StartScreencastResult /
  browsingContext.StopScreencastResult /
  browsingContext.TraverseHistoryResult
)

BrowsingContextEvent = (
  browsingContext.ContextCreated //
  browsingContext.ContextDestroyed //
  browsingContext.DomContentLoaded //
  browsingContext.DownloadEnd //
  browsingContext.DownloadWillBegin //
  browsingContext.FragmentNavigated //
  browsingContext.HistoryUpdated //
  browsingContext.Load //
  browsingContext.NavigationAborted //
  browsingContext.NavigationCommitted //
  browsingContext.NavigationFailed //
  browsingContext.NavigationStarted //
  browsingContext.UserPromptClosed //
  browsingContext.UserPromptOpened
)

远端具有device pixel ratio 覆盖,它是 navigable与 device pixel ratio 覆盖之间的弱映射。其初始为空。

注:此映射不会在最终会话 结束时清除;即 device pixel ratio 覆盖会比任何 WebDriver 会话存活更久。

viewport 尺寸是一个具有以下内容的结构体

viewport 配置是一个具有以下内容的结构体

未处理 提示行为结构体是一个具有以下内容的结构体

远端具有viewport 覆盖映射,它是用户上下文viewport 配置之间的弱映射。

远端具有locale 覆盖映射,它是 navigable用户上下文与字符串之间的弱映射。

screen settings 是一个 结构体,具有 一个名为 height,它是整数; 一个名为 width,它是整数; 一个名为 x,它是整数; 一个名为 y,它是整数。

远端具有screen settings 覆盖,它是一个结构体,具有 一个名为 user context screen settings, 它是用户 上下文screen settings之间的弱映射, 以及一个名为 navigable screen settings, 它是navigablescreen settings之间的弱映射。

远端具有timezone 覆盖映射,它是 navigable用户上下文与字符串之间的弱映射。

远端具有一个未处理提示行为覆盖映射, 它是 用户上下文未处理提示行为结构体之间的 弱映射。

远端具有scripting enabled 覆盖映射,它是 navigable用户上下文与 boolean 之间的弱映射。

一个远程端具有一个 下载 ID 映射,它是 响应和下载 ID 之间的弱映射。它初始为空。

一个 屏幕录制流顶级可遍历的视口的抽象流,由一个 视频轨道组成, 其包含该顶级可遍历的文档视口的已渲染视觉输出, 以及可选的一个 音频轨道,其包含该 顶级可遍历的文档的音频输出。

一个 BiDi 会话具有一个 屏幕录制映射,它是一个映射,其中键是 UUID,值是 屏幕录制; 后者是一个具有 一个名为 stream结构体,该项是一个屏幕录制流, 一个名为 path,该项是字符串, 一个名为 state,该项是 "recording"、"stopping"、"stopped" 之一, 以及一个名为 writeError,该项是字符串或 null。

要在给定屏幕录制 recordingmime type 的情况下,启动屏幕录制
  1. 并行运行以下步骤:

    1. 开始使用 mime typerecordingstream进行编码, 生成连续的编码数据块,作为字节 序列。 当 recordingstate 为 "recording" 时, 以实现定义的间隔生成一个新块。

    2. 对于为 recording 生成的每个块 bytes,运行以下 步骤:

      1. bytes 追加到 recordingpath处的文件。 如果失败:

        1. recordingwriteError 设为一个 描述写入失败的实现定义字符串。

        2. 给定 recording停止屏幕录制

要在给定屏幕录制 recording 的情况下,停止屏幕录制
  1. 如果 recordingstate 不是 "recording",则 返回。

  2. recordingstate 设为 "stopping"。

  3. 停止为 recording 生成新块,刷新任何剩余的已编码 数据作为最后一个块(按启动屏幕录制中的方式处理), 停止从 recordingstream 捕获,并 释放其 视频轨道以及(如果存在)其 音频轨道,然后将 recordingstate 设为 "stopped"。

  4. 等待,直到 recordingstate 为 "stopped"。

7.3.2. 类型

7.3.2.1. browsingContext.BrowsingContext 类型

远端定义本地端定义

browsingContext.BrowsingContext = text;

每个navigable都具有一个关联的navigable id, 它是唯一标识该 navigable 的字符串。它会在 navigable 创建时被隐式设置。对于具有关联 WebDriver 窗口句柄的 navigable,navigable id 必须与 窗口句柄相同。

每个navigable还具有一个关联存储分区, 它是其用于持久化数据的存储 分区

每个navigable还具有一个关联的original opener, 它是导致该 navigable 打开的navigable 或 null,初始设置为 null。

要在给定 navigable id 的情况下获取 navigable
  1. 如果 navigable id 为 null,则返回带有数据 null 的成功

  2. 如果不存在navigable idnavigable id 的 navigable,则返回 带有错误 代码 no such frame错误

  3. navigable 为 id 为 navigable idnavigable

  4. 返回带有数据 navigable成功

7.3.2.2. browsingContext.Info 类型

本地端定义

browsingContext.InfoList = [*browsingContext.Info]

browsingContext.Info = {
  children: browsingContext.InfoList / null,
  clientWindow: browser.ClientWindow,
  context: browsingContext.BrowsingContext,
  originalOpener: browsingContext.BrowsingContext / null,
  url: text,
  userContext: browser.UserContext,
  ? parent: browsingContext.BrowsingContext / null,
}

browsingContext.Info 类型表示 navigable 的属性。

要在给定 navigable 的情况下获取子 navigable

TODO:使其按文档顺序返回列表

  1. child navigables 为一个集合, 包含所有作为 navigable子 navigable的 navigable。

  2. 返回 child navigables

要在给定 navigablemax depthinclude parent id 的情况下获取 navigable 信息
  1. navigable idnavigablenavigable id

  2. parent navigablenavigable父级

  3. 如果 parent navigable 非 null,则令 parent idparent navigablenavigable id。否则令 parent id 为 null。

  4. documentnavigable活动文档

  5. url 为在给定 documentURL的情况下运行 URL 序列化器所得的结果。

    注:这包括 URL 的片段组成部分。

  6. child infos 为 null。

  7. 如果 max depth 为 null,或 max depth 大于 0:

    1. child navigables 为给定 navigable 时调用获取子 navigable的结果。

    2. 如果 max depth 非 null,则令 child depthmax depth - 1, 否则为 null。

    3. child infos 设置为空列表

    4. 对于 child navigables 中的每个 child navigable

      1. info 为给定 child navigablechild depth 和 false 时调用获取 navigable 信息的结果。

      2. info 追加到 child infos

  8. user contextnavigable关联用户 上下文

  9. 如果 navigableoriginal opener 非 null, 则令 opener idnavigableoriginal openernavigable id, 否则为 null。

  10. top-level traversablenavigable顶级 traversable

  11. client window idtop-level traversable 的关联客户端窗口客户端窗口 id

  12. navigable info 为一个映射, 它与 browsingContext.Info 产生式匹配,其中 context 字段设置为 navigable id;如果 include parent idtrue,则 parent 字段设置为 parent id,否则不设置; url 字段设置为 urluserContext 字段设置 为 user context用户上下文 idoriginalOpener 字段 设置为 opener idchildren 字段设置为 child infos;且 clientWindow 字段设置为 client window id

  13. 返回 navigable info

要在给定 navigablerequestwait condition, 以及可选的 history handling(默认值:"default")和 ignore cache(默认值:false)的情况下 等待导航
  1. navigation id 为一个基于真正随机数或 伪随机数的 UUID 的字符串表示。

  2. 用资源 request 导航 navigable, 并使用 navigable活动文档作为来源 Document, 导航时使用 navigation id navigation id历史处理行为 history handling。如果 ignore cache 为 true, 则该导航不得从 HTTP 缓存加载资源。

    准确 指定 ignore cache 标志如何工作。这需要 考虑是否只有资源的首次加载会绕过缓存 (即这是否类似于最初清除缓存然后像 通常一样继续),或者不是由 HTML 解析器直接加载的资源 (例如由脚本或样式表发起的加载)是否也会绕过缓存。

  3. 令(event receivednavigation status)为在给定 «"navigation started", "navigation failed", "fragment navigated"» 和 navigation id 的情况下进行 await 的结果。

  4. 断言:navigation statusidnavigation id

  5. 如果 navigation statusstatus 是 "complete":

    1. body 为一个映射, 它与 browsingContext.NavigateResult 产生式匹配,其中 navigation 字段设置为 navigation id,且 url 字段设置为在给定 navigation statusurl时运行 URL 序列化器所得的结果。

    2. 返回带有数据 body成功

    注:如果导航仅导致片段 改变,就是这种情况。

  6. 如果 navigation statusstatus 是 "canceled", 则返回带有错误 代码 unknown error错误

    TODO:这是在这里处理错误的正确方式吗?

  7. 断言:navigation statusstatus 是 "pending",并且 navigation id 不是 null。

  8. 如果 wait condition 是 "committed",则令 event name 为 "committed"。

  9. 否则,如果 wait condition 是 "interactive",则令 event name 为 "domContentLoaded"。

  10. 否则,令 event name 为 "load"。

  11. 令(event receivedstatus)为在给定 «event name, "download started", "navigation aborted", "navigation failed"» 和 navigation id 的情况下进行 await 的结果。

  12. 如果 event received 是 "navigation failed", 则返回带有错误 代码 unknown error错误

    我们在这里用 错误暴露了足够多关于失败内容和原因的信息吗? 我们想要什么错误代码?本地端是否会解析实现定义的字符串 来弄清楚实际出了什么问题,从而造成问题?

  13. body 为一个映射, 它与 browsingContext.NavigateResult 产生式匹配,其中 navigation 字段设置为 status 的 id,且 url 字段设置为在给定 status 的 url 时运行 URL 序列化器所得的结果。

  14. 返回带有数据 body成功

7.3.2.3. browsingContext.Locator 类型

远端定义本地端定义

browsingContext.Locator = (
   browsingContext.AccessibilityLocator /
   browsingContext.CssLocator /
   browsingContext.ContextLocator /
   browsingContext.InnerTextLocator /
   browsingContext.XPathLocator
)

browsingContext.AccessibilityLocator = {
   type: "accessibility",
   value: {
    ? name: text,
    ? role: text,
   }
}

browsingContext.CssLocator = {
   type: "css",
   value: text
}

browsingContext.ContextLocator = {
  type: "context",
  value: {
    context: browsingContext.BrowsingContext,
  }
}

browsingContext.InnerTextLocator = {
   type: "innerText",
   value: text,
   ? ignoreCase: bool
   ? matchType: "full" / "partial",
   ? maxDepth: js-uint,
}

browsingContext.XPathLocator = {
   type: "xpath",
   value: text
}

browsingContext.Locator 类型提供关于在文档中 定位节点的策略的详细信息。

7.3.2.4. browsingContext.Navigation 类型

远端定义本地端定义

browsingContext.Navigation = text;

browsingContext.Navigation 类型是唯一标识正在进行的 导航的字符串。

TODO:链接到 HTML 规范中的定义。

7.3.2.5. browsingContext.Download 类型

远程端定义本地端定义

browsingContext.Download = text;

browsingContext.Download 类型是标识下载的唯一字符串。

7.3.2.6. browsingContext.NavigationInfo 类型

本地端定义

browsingContext.BaseNavigationInfo = (
  context: browsingContext.BrowsingContext,
  navigation: browsingContext.Navigation / null,
  timestamp: js-uint,
  url: text,
  ? userContext: browser.UserContext,
)

browsingContext.NavigationInfo = {
  browsingContext.BaseNavigationInfo
}

browsingContext.NavigationInfo 类型提供正在进行的导航的详细信息。

要在给定navigable navigable导航状态 navigation status 的情况下 获取 导航信息
  1. navigable idnavigablenavigable id

  2. navigation idnavigation statusid

  3. timestamp 为表示当前 UTC 日期和 时间的时间值

  4. urlnavigation statusurl

  5. user context idnavigable关联用户上下文用户上下文 id

  6. 返回一个与 browsingContext.NavigationInfo 产生式匹配的映射,其中 context 字段设置为 navigable idnavigation 字段设置为 navigation idtimestamp 字段设置为 timestampurl 字段设置为在给定 url 的情况下运行 URL 序列化器所得的结果,且 userContext 字段设置为 user context id

7.3.2.7. browsingContext.ReadinessState 类型
browsingContext.ReadinessState = "none" / "interactive" / "complete"

browsingContext.ReadinessState 类型表示导航命令将返回时的 文档加载阶段。

7.3.2.8. browsingContext.UserPromptType 类型

远程端定义本地端定义

browsingContext.UserPromptType = "alert" / "beforeunload" / "confirm" / "prompt";

browsingContext.UserPromptType 类型表示可能的用户 提示类型。

7.3.3. 命令

7.3.3.1. browsingContext.activate 命令

browsingContext.activate 命令会激活并聚焦给定的 顶级 traversable

命令类型
browsingContext.Activate = (
  method: "browsingContext.activate",
  params: browsingContext.ActivateParameters
)

browsingContext.ActivateParameters = {
  context: browsingContext.BrowsingContext
}
返回类型
browsingContext.ActivateResult = EmptyResult

给定 command parameters 时,远端步骤为:

  1. navigable idcommand parameters["context"] 字段的值。

  2. navigable 为使用 navigable id 尝试获取 navigable的结果。

  3. 如果 navigable 不是顶级 traversable,则返回带有错误 代码 invalid argument错误

  4. 返回使用 navigable 调用激活 navigable的结果。

要在给定 navigable 的情况下激活 navigable
  1. 运行特定于实现的步骤,使 navigable系统可见性状态变为visible。如果这不可能,则返回带有错误代码 unsupported operation错误

    注:这可能会产生副作用,使当前 visiblenavigable变为hidden

    注:这可能会通过导致窗口取消最小化, 或通过与改变系统可见性状态相关的其他副作用,来改变底层 OS 状态。

  2. 运行特定于实现的步骤,在 navigable 未聚焦时将系统焦点设置到 navigable 上。

    注:除非其他规范强制要求,否则这不会改变文档的聚焦区域

  3. 返回带有数据 null 的成功

7.3.3.2. browsingContext.captureScreenshot 命令

browsingContext.captureScreenshot 命令 捕获给定 navigable 的图像,并以 Base64 编码字符串形式返回。

命令类型
browsingContext.CaptureScreenshot = (
  method: "browsingContext.captureScreenshot",
  params: browsingContext.CaptureScreenshotParameters
)

browsingContext.CaptureScreenshotParameters = {
  context: browsingContext.BrowsingContext,
  ? origin: ("viewport" / "document") .default "viewport",
  ? format: browsingContext.ImageFormat,
  ? clip: browsingContext.ClipRectangle,
}

browsingContext.ImageFormat = {
   type: text,
   ? quality: 0.0..1.0,
}

browsingContext.ClipRectangle = (
  browsingContext.BoxClipRectangle /
  browsingContext.ElementClipRectangle
)

browsingContext.ElementClipRectangle = {
  type: "element",
  element: script.SharedReference
}

browsingContext.BoxClipRectangle = {
   type: "box",
   x: float,
   y: float,
   width: float,
   height: float
}
返回类型
browsingContext.CaptureScreenshotResult = {
  data: text
}
要在给定 rect 的情况下规范化矩形

注:这确保所得矩形具有 正的宽度尺寸高度尺寸

  1. xrectx 坐标

  2. yrecty 坐标

  3. widthrect宽度尺寸

  4. heightrect高度尺寸

  5. 如果 width 小于 0,则将 x 设置为 x + width,然后 将 width 设置为 -width

  6. 如果 height 小于 0,则将 y 设置为 y + height,然后 将 height 设置为 -height

  7. 返回一个新的 DOMRectReadOnly, 其x 坐标xy 坐标y宽度尺寸width,且高度尺寸height

要在给定 rect1rect2 的情况下求矩形 交集
  1. rect1 为用 rect1 调用规范化矩形的结果。

  2. rect2 为用 rect2 调用规范化矩形的结果。

  3. x1_0rect1x 坐标

  4. x2_0rect2x 坐标

  5. x1_1rect1x 坐标加上 rect1宽度尺寸

  6. x2_1rect2x 坐标加上 rect2宽度尺寸

  7. x_0 为 «x1_0, x2_0» 的最大元素。

  8. x_1 为 «x1_1, x2_1» 的最小元素。

  9. y1_0rect1y 坐标

  10. y2_0rect2y 坐标

  11. y1_1rect1y 坐标加上 rect1高度尺寸

  12. y2_1rect2y 坐标加上 rect2高度尺寸

  13. y_0 为 «y1_0, y2_0» 的最大元素。

  14. y_1 为 «y1_1, y2_1» 的最小元素。

  15. 如果 x_1 小于 x_0,则令 width 为 0。否则令 widthx_1 - x_0

  16. 如果 y_1 小于 y_0,则令 height 为 0。否则令 heighty_1 - y_0

  17. 返回一个新的 DOMRectReadOnly, 其x 坐标x_0y 坐标y_0宽度尺寸width,且高度尺寸height

要在给定 documentrect 的情况下将 document 渲染到 canvas
  1. ratio 为在给定 document默认视图的情况下确定 device pixel ratio所得的结果。

  2. paint widthrect宽度尺寸乘以 ratio, 四舍五入到最接近的整数,使其与 rect 在设备像素中的宽度 相匹配。

  3. paint heightrect高度尺寸乘以 ratio, 四舍五入到最接近的整数,使其与 rect 在设备像素中的高度 相匹配。

  4. canvas 为新的 HTMLCanvasElement, 其 widthpaint widthheightpaint height

  5. canvas context 为用 canvas 和 null 运行 2D 上下文创建算法 所得的结果。

  6. canvas上下文模式设置为2D

  7. 完成特定于实现的步骤,其等价于将 framebuffer 中表示 documentrect 覆盖区域的区域绘制到 canvas context,使 framebuffer 中的每个像素对应于 canvas context 中的一个像素,其中视口坐标中的(rectx 坐标recty 坐标)对应于 canvas context 中的 (0,0),而(rectx 坐标 + rect宽度尺寸recty 坐标 + rect高度尺寸)对应于(paint widthpaint height)。

  8. 返回 canvas

要在给定 canvasformat 的情况下将 canvas 编码为 Base64
  1. 如果 format 不是 null,则令 typeformattype 字段,且令 qualityformatquality 字段。

  2. 否则,令 type 为 "image/png",并令 qualityundefined

  3. filecanvas 在给定 typequality 的情况下的位图作为文件的序列化

  4. encoded stringfileforgiving-base64 编码

  5. 返回带有数据 encoded string 的成功。

要在给定 documentorigin 的情况下获取 origin 矩形
  1. 如果 origin"viewport"

    1. viewportdocument视觉视口

    2. viewport rect 为一个 DOMRectReadOnly, 其x 坐标viewportpage lefty 坐标viewportpage top宽度尺寸viewport width,且高度尺寸viewport height。

    3. 返回带有数据 viewport rect成功

  2. 断言:origin"document"

  3. document elementdocumentdocument element

  4. document rect 为一个 DOMRectReadOnly, 其x 坐标为 0,y 坐标为 0,宽度尺寸document elementscroll height, 且高度尺寸document elementscroll width

  5. 返回带有数据 document rect成功

给定 sessioncommand parameters 时,远端步骤为:

  1. navigable idcommand parameterscontext 字段的值, 如果存在的话;否则为 null。

  2. navigable 为使用 navigable id 尝试获取 navigable 所得的结果。

  3. 如果实现因任何原因无法捕获 navigable 的屏幕截图, 则返回带有错误 代码 unsupported operation错误

  4. documentnavigable活动文档

  5. 在下次为 document 调用运行动画帧回调算法之后立即:

    这应当 以某种更明确的方式集成到更新渲染算法中。

  6. origincommand parameterscontext 字段的值,如果存在的话;否则为 "viewport"。

  7. origin rect 为在给定 origindocument 的情况下 尝试获取 origin 矩形 所得的结果。

  8. clip rectorigin rect

  9. 如果 command parameters 包含 "clip":

    1. clipcommand parameters["clip"]。

    2. 运行第一个匹配条件下的步骤:

      clipbrowsingContext.ElementClipRectangle 产生式匹配:
      1. environment settings环境设置对象, 其 相关全局对象关联 Documentdocument

      2. realmenvironment settingsrealm 执行上下文的 Realm 组件。

      3. element 为用 clip["element"]、realmsession 尝试反序列化远程 引用所得的结果。

      4. 如果 element 没有实现 Element, 则返回带有错误代码 no such element错误

      5. 如果 element节点文档不是 document,则返回带有 错误代码 no such element错误

      6. viewport rect 为在给定 "viewport" 和 document 的情况下调用获取 origin 矩形的结果。

      7. element rect 为针对 element 获取边界框所得的结果。

      8. clip rect 为一个 DOMRectReadOnly, 其x 坐标element rect["x"] + viewport rect["x"], y 坐标element rect["y"] + viewport rect["y"],width 为 element rect["width"], 且 height 为 element rect["height"]。

      clipbrowsingContext.BoxClipRectangle 产生式匹配:
      1. clip xclip["x"] 加上 origin rectx 坐标

      2. clip yclip["y"] 加上 origin recty 坐标

      3. clip rect 为一个 DOMRectReadOnly, 其x 坐标clip xy 坐标clip y,width 为 clip["width"],且 height 为 clip["height"]。

  10. 注:所有坐标现在都从文档的 origin 开始测量。

  11. rectorigin rectclip rect矩形交集

  12. 如果 rect宽度尺寸为 0,或 rect高度尺寸为 0, 则返回带有错误代码 unable to capture screen错误

  13. canvas 为用 documentrect 将 document 渲染到 canvas所得的结果。

  14. formatcommand parametersformat 字段。

  15. encoding result 为用 canvasformat 尝试将 canvas 编码为 Base64所得的结果。

  16. body 为一个与 browsingContext.CaptureScreenshotResult 产生式匹配的映射,其中 data 字段设置为 encoding result

  17. 返回带有数据 body成功

7.3.3.3. browsingContext.close 命令

browsingContext.close 命令会关闭一个 顶级 traversable

命令类型
browsingContext.Close = (
  method: "browsingContext.close",
  params: browsingContext.CloseParameters
)

browsingContext.CloseParameters = {
  context: browsingContext.BrowsingContext,
  ? promptUnload: bool .default false
}
返回类型
browsingContext.CloseResult = EmptyResult
给定 command parameters 时,远端步骤为:
  1. navigable idcommand parameterscontext 字段的值。

  2. prompt unloadcommand parameterspromptUnload 字段的值。

  3. navigable 为用 navigable id 尝试获取 navigable 所得的结果。

  4. 断言:navigable 不是 null。

  5. 如果 navigable 不是顶级 traversable,则返回带有 错误代码 invalid argument错误

  6. 如果 prompt unload 为 true:

    1. 关闭 navigable

  7. 否则:

    1. 在不提示卸载的情况下关闭 navigable

  8. 返回带有数据 null 的成功

关于关闭最后一个 顶级 traversable时的行为,目前有一个开放的 讨论。我们可以预期关闭浏览器、关闭会话,或将其留给实现决定。[w3c/webdriver-bidi Issue #170]

7.3.3.4. browsingContext.create 命令

browsingContext.create 命令会创建一个新的 navigable,位于新标签页或新窗口中,并返回其 navigable id

命令类型
browsingContext.Create = (
  method: "browsingContext.create",
  params: browsingContext.CreateParameters
)

browsingContext.CreateType = "tab" / "window"

browsingContext.CreateParameters = {
  type: browsingContext.CreateType,
  ? referenceContext: browsingContext.BrowsingContext,
  ? background: bool .default false,
  ? userContext: browser.UserContext
}
返回类型
browsingContext.CreateResult = {
  context: browsingContext.BrowsingContext,
  ? userContext: browser.UserContext
}
给定 command parameters 时,远端步骤为:
  1. typecommand parameterstype 字段的值。

  2. reference navigable idcommand parametersreferenceContext 字段的值(如果存在),否则为 null。

  3. 如果 reference navigable id 不为 null,则令 reference navigable尝试使用 reference navigable id 获取可导航的结果。否则令 reference navigable 为 null。

  4. 如果 reference navigable 不为 null,且不是顶级可遍历, 则返回带有错误码 无效参数错误

  5. 如果实现由于任何原因无法创建新的顶级可遍历,则返回带有错误 码 不支持的操作错误

  6. 如果 reference navigable 为 null,则令 user context默认用户上下文,否则令其为 reference navigable关联用户 上下文

  7. user context idcommand parametersuserContext 字段的值(如果存在), 否则为 null。

  8. 如果 user context id 不为 null,则将 user context 设为 尝试使用 user context id 获取用户上下文的结果。

  9. 如果 user context 为 null,则返回带有错误码 无此用户 上下文错误

  10. 如果实现由于任何原因无法创建具有关联用户上下文 user context 的新顶级可遍历,则返回带有 错误 码 不支持的操作错误

  11. traversable 为尝试以 null 和空字符串运行创建新的顶级可遍历步骤, 并将新创建的顶级可遍历关联用户上下文设为 user context 的结果。 新顶级可遍历会在哪个 OS 窗口中创建,取决于 typereference navigable

    • 如果 type 为 "tab",且实现支持在同一 OS 窗口中存在多个顶级可遍历

      • 新的顶级可遍历应复用 现有 OS 窗口(如果有)。

      • 如果 reference navigable 不为 null,则新的顶级可遍历应复用包含 reference navigable 的窗口(如果有)。如果 OS 窗口内的顶级可遍历具有确定的顺序, 则新的顶级可遍历应在该顺序中紧接在 reference navigable顶级可遍历之后。

    • 如果 type 为 "window",且实现支持在不同 OS 窗口中存在多个顶级可遍历,则创建的 顶级可遍历应位于新的 OS 窗口中。

    • 否则,如何向用户呈现该顶级可遍历的细节由实现定义。

  12. 如果 command parametersbackground 字段的值为 false:

    1. activate result 为使用新创建的可导航激活可导航的结果。

    2. 如果 activate result错误, 则返回 activate result

    注:如果 background 为 true,则不要为创建的可导航调用聚焦步骤

  13. body 为一个匹配 browsingContext.CreateResult 产生式的映射, 其中 context 字段设为 traversable可导航 ID, 且 userContext 属性设为 traversable关联用户上下文用户 上下文 ID

  14. 返回带有数据 body成功

7.3.3.5. browsingContext.getTree 命令

browsingContext.getTree 命令返回一个 包含给定父级本身在内的所有后代 navigable 的树, 或在未提供父级时返回所有顶级 context。

命令类型
browsingContext.GetTree = (
  method: "browsingContext.getTree",
  params: browsingContext.GetTreeParameters
)

browsingContext.GetTreeParameters = {
  ? maxDepth: js-uint,
  ? root: browsingContext.BrowsingContext,
}
返回类型
browsingContext.GetTreeResult = {
  contexts: browsingContext.InfoList
}
给定 sessioncommand parameters 时,远端步骤为:
  1. root idcommand parametersroot 字段的值, 如果存在的话;否则为 null。

  2. max depthcommand parametersmaxDepth 字段的值,如果存在的话;否则为 null。

  3. navigables 为空列表

  4. 如果 root id 不是 null,则将给定 root id尝试获取 navigable所得的结果追加到 navigables。 否则将所有顶级 traversable追加到 navigables

  5. navigables infos 为空列表

  6. 对于 navigables 中的每个 navigable

    1. info 为给定 navigablemax depth 和 true 时调用获取 navigable 信息所得的结果。

    2. info 追加到 navigables infos

  7. body 为一个与 browsingContext.GetTreeResult 产生式匹配的映射, 其中 contexts 字段设置为 navigables infos

  8. 返回带有数据 body成功

7.3.3.6. browsingContext.handleUserPrompt 命令

browsingContext.handleUserPrompt 命令允许关闭打开的提示

命令类型
browsingContext.HandleUserPrompt = (
  method: "browsingContext.handleUserPrompt",
  params: browsingContext.HandleUserPromptParameters
)

browsingContext.HandleUserPromptParameters = {
  context: browsingContext.BrowsingContext,
  ? accept: bool,
  ? userText: text,
}
返回类型
browsingContext.HandleUserPromptResult = EmptyResult

给定 sessioncommand parameters 时,远端步骤为:

  1. navigable idcommand parameterscontext 字段的值。

  2. navigable 为用 navigable id 尝试获取 navigable 所得的结果。

  3. acceptcommand parametersaccept 字段的值,如果存在的话;否则为 true。

  4. userTextcommand parametersuserText 字段的值,如果存在的话;否则为空字符串。

  5. 如果 navigable 当前显示的是由调用 alert 产生的简单对话框,则 确认该提示。

    否则,如果 navigable 当前显示的是由调用 confirm 产生的简单对话框,则当 accept 为 true 时肯定响应, 或当 accept 为 false 时 否定响应。

    否则,如果 navigable 当前显示的是由调用 prompt 产生的简单对话框,则当 accept 为 true 时用字符串值 userText 响应,或当 accept 为 false 时中止。

    否则,如果 navigable 当前显示的是作为提示卸载步骤的一部分的提示,则当 accept 为 true 时确认该 导航,否则 拒绝该导航。

    否则,返回带有错误 代码 no such alert错误

  6. 返回带有数据 null 的成功

7.3.3.7. browsingContext.locateNodes 命令

browsingContext.locateNodes 命令返回 与指定定位器匹配的所有节点列表。

命令类型
browsingContext.LocateNodes = (
  method: "browsingContext.locateNodes",
  params: browsingContext.LocateNodesParameters
)

browsingContext.LocateNodesParameters = {
   context: browsingContext.BrowsingContext,
   locator: browsingContext.Locator,
   ? maxNodeCount: (js-uint .ge 1),
   ? serializationOptions: script.SerializationOptions,
   ? startNodes: [ + script.SharedReference ]
}
返回类型
browsingContext.LocateNodesResult = {
    nodes: [ * script.NodeRemoteValue ]
}
要在给定 navigablecontext nodesselectormaximum returned node countsession 的情况下使用 CSS 定位节点
  1. returned nodes 为空列表

  2. parse result 为给定 selector解析选择器所得的结果。

  3. 如果 parse result 为 failure,则返回带有错误代码 invalid selector错误

  4. 对于 context nodes 中的每个 context node

    1. elements 为用 parse resultnavigable活动文档,并使用 作用域根 context node针对树匹配选择器所得的结果。

    2. 对于 elements 中的每个 element

      1. element 追加returned nodes

      2. 如果 maximum returned node count 不是 null,且 returned nodes大小等于 maximum returned node count, 则返回带有数据 returned nodes成功

  5. 返回带有数据 returned nodes成功

要在给定 navigable 的情况下定位容器 元素
  1. returned nodes 为空列表

  2. 如果 navigable容器不是 null, 则将 navigable容器追加到 returned nodes

  3. 返回 returned nodes

要在给定 navigablecontext nodesselectormaximum returned node count 的情况下使用 XPath 定位节点

注:由于 XPath 规范处于无人维护状态,本算法被表述为像是在调用 XPath DOM API。 然而,应将其理解为等价于直接访问底层算法的规范内部调用, 而不经过 ECMAScript 运行时。

  1. returned nodes 为空列表

  2. 对于 context nodes 中的每个 context node

    1. evaluate result 为在 navigable活动文档上调用 evaluate,并以 selectorcontext node、null、 ORDERED_NODE_SNAPSHOT_TYPE 和 null 作为实参所得的结果。如果这抛出一个 "SyntaxError" DOMException,则返回带有 错误代码 invalid selector错误; 否则,如果这抛出任何其他异常,则返回带有 错误代码 unknown error错误

    2. index 为 0。

    3. length 为从 evaluate result 获取 snapshotLength 属性所得的结果。

    4. index 小于 length 时,重复:

      1. node 为以 evaluate result 作为 this、以 index 作为实参调用 snapshotItem所得的结果。

      2. node 追加returned nodes

      3. 如果 maximum returned node count 不是 null,且 returned nodes大小等于 maximum returned node count, 则返回带有数据 returned nodes成功

      4. index 设置为 index + 1。

  3. 返回带有数据 returned nodes成功

要在给定 context nodesselectormax depthmatch typeignore casemaximum returned node count 的情况下使用 inner text 定位节点
  1. 如果 selector 是空字符串,则返回带有错误代码 invalid selector错误

  2. returned nodes 为空列表

  3. 如果 ignore case 为 false,则令 search textselector。否则, 令 search text 为按 Unicode 默认大小写转换算法selector 执行 toUppercase所得的结果。

  4. 对于 context nodes 中的每个 context node

    1. 如果 context node 实现了 DocumentDocumentFragment

      注:遍历 document 或 document fragment 时,max depth 有意不减少,以使使用 documentdocument.documentElement 的搜索结果等价。

      1. child nodes 为空列表

      2. 对于 context node子节点中的每个节点 child

        1. child 追加child nodes

      3. 用在给定 child nodesselectormax depthmatch typeignore casemaximum returned node count 的情况下尝试使用 inner text 定位节点 所得的结果扩展 returned nodes

    2. 如果 context node 没有实现 HTMLElement, 则继续

    3. node inner text 为以 context node 作为 this 值调用 innerText getter 步骤所得的结果。

    4. 如果 ignore case 为 false,则令 node textnode inner text。否则, 令 node text 为按 Unicode 默认大小写转换算法node inner text 执行 toUppercase所得的结果。

    5. 如果 search textnode text码点子字符串, 则执行以下步骤:

      1. child nodes 为空列表,并且 对于 context node子节点中的每个节点 child

        1. child 追加child nodes

      2. 如果 child nodes大小等于 0,或 max depth 等于 0, 则执行以下步骤:

        1. 如果 match type"full"node text search text, 则将 context node 追加returned nodes

        2. 否则,如果 match type"partial",则将 context node 追加returned nodes

      3. 否则,执行以下步骤:

        1. 如果 max depth 为 null,则令 child max depth 为 null, 否则为 max depth - 1。

        2. child node matches 为用 child nodesselectorchild max depthmatch typeignore casemaximum returned node count 调用使用 inner text 定位节点所得的结果。

        3. 如果 child node matches大小等于 0 且 match type"partial",则将 context node 追加到 returned nodes。否则,用 child node matches 扩展 returned nodes

  5. 如果 maximum returned node count 不是 null,则移除 returned nodes 中索引大于或等于 maximum returned node count 的所有条目。

  6. 返回带有数据 returned nodes成功

要在给定 context nodesselectormaximum returned node countreturned nodes 的情况下使用无障碍属性收集节点
  1. 如果 returned nodes 为 null:

    1. returned nodes 设置为空列表

  2. 对于 context nodes 中的每个 context node

    1. match 为 true。

    2. 如果 context node 实现了 Element

      1. 如果 selector 包含 "role":

        1. rolecontext node计算角色

        2. 如果 selector["role"] 不是 role

          1. match 设置为 false。

      2. 如果 selector 包含 "name":

        1. namecontext node可访问名称

        2. 如果 selector["name"] 不是 name

          1. match 设置为 false。

    3. 否则,将 match 设置为 false。

    4. 如果 match 为 true:

      1. 如果 maximum returned node count 不是 null,且 returned nodes大小等于 maximum returned node count, 则中断

      2. context node 追加returned nodes

    5. child nodes 为空列表,并且对于 context node子节点中的每个节点 child

      1. 如果 child 实现了 Element, 则将 child 追加child nodes

    6. 尝试child nodesselectormaximum returned node countreturned nodes 使用无障碍属性收集节点

  3. 返回 returned nodes

要在给定 context nodesselectormaximum returned node count 的情况下使用无障碍属性定位节点
  1. 如果 selector包含 "role",且 selector包含 "name",则返回 带有错误 代码 invalid selector错误

  2. 返回用 context nodesselectormaximum returned node count 和 null 调用使用无障碍属性收集节点所得的结果。

给定 sessioncommand parameters 时,远端步骤为:
  1. navigable idcommand parameters["context"]。

  2. navigable 为用 navigable id 尝试获取 navigable 所得的结果。

  3. 断言:navigable 不是 null。

  4. realm 为用 navigablenavigable id 和 null 尝试从 navigable 获取 realm 所得的结果。

  5. locatorcommand parameters["locator"]。

  6. 如果 command parameters 包含 "startNodes",则令 start nodes parametercommand parameters["startNodes"]。 否则令 start nodes parameter 为 null。

  7. 如果 command parameters 包含 "maxNodeCount",则令 maximum returned node countcommand parameters["maxNodeCount"]。 否则,令 maximum returned node count 为 null。

  8. context nodes 为空列表

  9. 如果 start nodes parameter 为 null,则将 navigable活动文档追加context nodes。否则,对于 start nodes parameter 中的每个 serialized start node

    1. start node 为给定 serialized start noderealmsession尝试反序列化共享引用所得的结果。

    2. start node 追加context nodes

  10. 断言 context nodes大小大于 0。

  11. typelocator["type"]。

  12. 在以下条件及其关联步骤列表中,运行第一个其关联条件为 true 的 步骤集合:

    type 是字符串 "css"
    1. selectorlocator["value"]。

    2. result nodes 为给定 navigablecontext nodesselectormaximum returned nodes尝试使用 css 定位节点所得的结果。

    type 是字符串 "xpath"
    1. selectorlocator["value"]。

    2. result nodes 为给定 navigablecontext nodesselectormaximum returned nodes尝试使用 xpath 定位节点所得的结果。

    type 是字符串 "innerText"
    1. selectorlocator["value"]。

    2. 如果 locator 包含 maxDepth,则令 max depthlocator["maxDepth"]。否则,令 max depth 为 null。

    3. 如果 locator 包含 ignoreCase,则令 ignore caselocator["ignoreCase"]。否则,令 ignore case 为 false。

    4. 如果 locator 包含 matchType,则令 match typelocator["matchType"]。否则,令 match type 为 "full"。

    5. result nodes 为给定 context nodesselectormax depthmatch typeignore casemaximum returned node count尝试使用 inner text 定位节点所得的结果。

    type 是字符串 "accessibility"
    1. selectorlocator["value"]。

    2. result nodes 为给定 context nodesselectormaximum returned node count使用无障碍属性定位节点所得的结果。

    type 是字符串 "context"
    1. 如果 start nodes parameter 不是 null, 则返回带有错误代码 "invalid argument" 的错误

    2. selectorlocator["value"]。

    3. context idselector["context"]。

    4. child navigable 为用 context id 尝试获取 navigable 所得的结果。

    5. 如果 child navigable父级不是 navigable, 则返回带有错误代码 "invalid argument" 的错误

    6. result nodes 为给定 child navigable定位容器元素所得的结果。

    7. 断言:对于 result nodes 中的每个 nodenode节点 navigablenavigable

  13. 断言:maximum returned node count 为 null,或 result nodes大小小于或等于 maximum returned node count

  14. 如果 command parameters 包含 "serializationOptions", 则令 serialization optionscommand parameters["serializationOptions"]。 否则,令 serialization options 为一个与 script.SerializationOptions 产生式匹配、且各字段 设置为其默认值的映射

  15. result ownership 为 "none"。

  16. serialized nodes 为空列表

  17. 对于 result nodes 中的每个 result node

    1. serialized node 为用 result nodeserialization optionsresult ownership、一个新的映射作为 serialization internal map、realmsession 序列化为远程值所得的结果。

    2. serialized node 追加serialized nodes

  18. result 为一个与 browsingContext.LocateNodesResult 产生式匹配的映射, 其 nodes 字段设置为 serialized nodes

  19. 返回带有数据 result成功

7.3.3.8. browsingContext.navigate 命令

browsingContext.navigate 命令将一个 navigable 导航到给定 URL。

命令类型
browsingContext.Navigate = (
  method: "browsingContext.navigate",
  params: browsingContext.NavigateParameters
)

browsingContext.NavigateParameters = {
  context: browsingContext.BrowsingContext,
  url: text,
  ? wait: browsingContext.ReadinessState,
}
返回类型
browsingContext.NavigateResult = {
  navigation: browsingContext.Navigation / null,
  url: text,
}
给定 sessioncommand parameters 时,远端步骤为:
  1. navigable idcommand parameterscontext 字段的值。

  2. navigable 为用 navigable id 尝试获取 navigable 所得的结果。

  3. 断言:navigable 不是 null。

  4. wait condition 为 "committed"。

  5. 如果 command parameters 包含 waitcommand parameters[wait] 不是 "none", 则将 wait condition 设置为 command parameters[wait]。

  6. urlcommand parametersurl 字段的值。

  7. documentnavigable活动文档

  8. basedocument基 URL

  9. url record 为以 基 URL baseURL 解析器应用于 url所得的结果。

  10. 如果 url record 为 failure,则返回带有错误代码 invalid argument错误

  11. request 为一个新的 request,其 URL 为 url record

  12. 返回用 navigablerequestwait condition 调用等待导航所得的结果。

7.3.3.9. browsingContext.print 命令

browsingContext.print 命令 创建文档的分页表示,并将其作为 表示为 Base64 编码字符串的 PDF 文档返回。

命令类型
browsingContext.Print = (
  method: "browsingContext.print",
  params: browsingContext.PrintParameters
)

browsingContext.PrintParameters = {
  context: browsingContext.BrowsingContext,
  ? background: bool .default false,
  ? margin: browsingContext.PrintMarginParameters,
  ? orientation: ("portrait" / "landscape") .default "portrait",
  ? page: browsingContext.PrintPageParameters,
  ? pageRanges: [*(js-uint / text)],
  ? scale: (0.1..2.0) .default 1.0,
  ? shrinkToFit: bool .default true,
}

browsingContext.PrintMarginParameters = {
  ? bottom: (float .ge 0.0) .default 1.0,
  ? left: (float .ge 0.0) .default 1.0,
  ? right: (float .ge 0.0) .default 1.0,
  ? top: (float .ge 0.0) .default 1.0,
}

; Minimum size is 1pt x 1pt. Conversion follows from
; https://www.w3.org/TR/css3-values/#absolute-lengths
browsingContext.PrintPageParameters = {
  ? height: (float .ge 0.0352) .default 27.94,
  ? width: (float .ge 0.0352) .default 21.59,
}
返回类型
browsingContext.PrintResult = {
  data: text
}

带有 sessioncommand parameters远程端步骤如下:

  1. navigable idcommand parameterscontext 字段的值。

  2. navigable尝试使用 navigable id 获取 可导航的结果。

  3. 如果实现由于任何原因无法提供 navigable 的分页表示,则返回带有错误码 不支持的操作错误

  4. margincommand parametersmargin 字段的值(如果存在),否则为一个匹配 browsingContext.PrintMarginParameters 且字段设为 其默认值的映射

  5. page sizecommand parameterspage 字段的值(如果存在),否则为一个匹配 browsingContext.PrintPageParameters 且字段设为 其默认值的映射

注:最小页面尺寸为 1 点,按照绝对长度, 即 (2.54 / 72) cm。

  1. page rangescommand parameterspageRanges 字段的值(如果存在), 否则为空列表

  2. documentnavigable活动文档

  3. 在下一次为 document 调用运行动画帧回调 算法之后立即:

    这应当以某种更明确的方式 集成到更新渲染算法中。

    1. pdf data 为采用 UA 特定步骤生成 document 的分页表示的结果,其中 CSS 媒体类型设为 print,编码为 PDF,并具有以下纸张设置:

      属性
      宽度,单位 cm 如果 command parameters["orientation"] 为 "portrait",则为 page size["width"],否则为 page size["height"]
      高度,单位 cm 如果 command parameters["orientation"] 为 "portrait",则为 page size["height"],否则为 page size["width"]
      上边距,单位 cm margin["top"]
      下边距,单位 cm margin["bottom"]
      左边距,单位 cm margin["left"]
      右边距,单位 cm margin["right"]

      此外,UA 应应用以下格式化提示:

      如果 command parameters["scale"] 不等于 1
      按因子 command parameters["scale"] 缩放内容大小
      如果 command parameters["background"] 为 false:
      抑制背景图像输出
      如果 command parameters["shrinkToFit"] 为 true:
      调整内容大小以匹配页面宽度,覆盖内容中指定的任何页面 宽度
    2. 如果 page ranges 不是, 则令 pages尝试使用 page rangespdf data 中包含的页数解析页面范围的结果,然后从 pdf data 中移除 任何其从 1 开始的索引未包含在 pages 中的页面。

    3. encoding result 为对 pdf data 调用Base64 编码的结果。

    4. encoded dataencoding result 的数据。

    5. body 为一个匹配 browsingContext.PrintResult 产生式的映射, 其中 data 字段设为 encoded data

    6. 返回带有数据 body成功

7.3.3.10. browsingContext.reload 命令

browsingContext.reload 命令重载一个 navigable。

命令类型
browsingContext.Reload = (
  method: "browsingContext.reload",
  params: browsingContext.ReloadParameters
)

browsingContext.ReloadParameters = {
  context: browsingContext.BrowsingContext,
  ? ignoreCache: bool,
  ? wait: browsingContext.ReadinessState,
}
返回类型
browsingContext.ReloadResult = browsingContext.NavigateResult
给定 command parameters 时,远端步骤为:
  1. navigable idcommand parameterscontext 字段的值。

  2. navigable 为用 navigable id 尝试获取 navigable 所得的结果。

  3. 断言:navigable 不是 null。

  4. ignore cachecommand parametersignoreCache 字段的值(如果存在),否则为 false。

  5. wait condition 为 "committed"。

  6. 如果 command parameters 包含 waitcommand parameters[wait] 不是 "none", 则将 wait condition 设置为 command parameters[wait]。

  7. documentnavigable活动文档

  8. urldocumentURL

  9. request 为一个新的 request,其 URL 为 url

  10. 返回用 navigablerequestwait condition、历史处理 "reload" 和 ignore cache ignore cache 调用等待导航所得的结果。

7.3.3.11. browsingContext.setBypassCSP 命令

browsingContext.setBypassCSP 命令允许绕过 Content Security Policy 的强制执行。

注:启用 CSP 绕过时,所有 CSP 指令都会被 绕过,包括通常会阻止 eval()、new Function()、内联脚本和资源 加载的指令。

命令类型
browsingContext.SetBypassCSP = (
  method: "browsingContext.setBypassCSP",
  params: browsingContext.SetBypassCSPParameters
)

browsingContext.SetBypassCSPParameters = {
  bypass: true / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
browsingContext.SetBypassCSPResult = EmptyResult

远端具有一个绕过 CSP 配置,它是 WebDriver 配置,其关联类型为 boolean。

给定 navigable navigable 时,WebDriver BiDi CSP 被绕过步骤为:

  1. top-level traversablenavigable顶级 traversable

  2. bypass CSP enabled 为针对 top-level traversable绕过 CSP 配置调用获取 WebDriver 配置值所得的结果。

  3. 断言:bypass CSP enabledtrueunset

  4. 如果 bypass CSP enabledunset,则返回 false。

  5. 返回 true。

给定 command parameters 时,远端步骤为:

  1. bypasscommand parameters["bypass"]。

  2. 如果 bypass 为 null,则将 bypass 设置为 unset

  3. 尝试command parameters 存储 WebDriver 配置 绕过 CSP 配置 bypass

  4. 返回带有数据 null 的成功

7.3.3.12. browsingContext.setViewport 命令

browsingContext.setViewport 命令修改给定顶级 traversable 上的特定 viewport 特征(例如 viewport width 和 viewport height)。

命令类型
browsingContext.SetViewport = (
  method: "browsingContext.setViewport",
  params: browsingContext.SetViewportParameters
)

browsingContext.SetViewportParameters = {
  ? context: browsingContext.BrowsingContext,
  ? viewport: browsingContext.Viewport / null,
  ? devicePixelRatio: (float .gt 0.0) / null,
  ? userContexts: [+browser.UserContext],
}

browsingContext.Viewport = {
  width: js-uint,
  height: js-uint,
}
返回类型
browsingContext.SetViewportResult = EmptyResult
要在给定 navigabledevice pixel ratio 的情况下设置 device pixel ratio 覆盖
  1. 如果 device pixel ratio 不是 null:

    1. 对于当前加载在指定 navigable 中的document

      1. 当运行从 source set 选择图像源步骤时, 在选择图像时,表现得如同实现的像素密度被设置为 device pixel ratio

      2. resolution 媒体特性而言,表现得如同 实现的 resolution 是按页面缩放缩放的 device pixel ratio dppx。

    2. device pixel ratio 覆盖[navigable] 设置device pixel ratio

      注:这会因 § 8.3.1 确定 device pixel ratio 的补丁而生效。

  2. 否则:

    1. 对于当前加载在指定 navigable 中的document

      1. 当运行从 source set 选择图像源步骤时,使用实现的默认行为, 不带有这些步骤先前调用所作的任何更改。

      2. resolution 媒体特性而言,使用 实现的默认行为, 不带有这些步骤先前调用所作的任何更改。

    2. device pixel ratio 覆盖移除 navigable

  3. 对当前加载在指定 navigable 中的document运行求值媒体查询并报告变化

要在给定 navigable navigableviewport viewport 的情况下 设置 viewport
  1. 如果 viewport 不是 null,则将 navigable布局视口的宽度设置为 viewportwidth(以 CSS 像素计),并且 将 navigable布局视口的高度设置为 viewportheight(以 CSS 像素计)。

  2. 否则,将 navigable布局视口设置为 实现定义的默认值。

在新的 navigable navigable 中创建 document 之后, 且在调用运行 WebDriver BiDi 预加载脚本算法之前:

TODO:改为将其移作 html 规范中的一个钩子。

  1. user contextnavigable关联用户 上下文

  2. 如果 navigable顶级 traversable

    1. navigable 更新 geolocation 覆盖

    2. navigable 更新模拟 forced colors 主题

    3. 如果 screen orientation 覆盖映射 包含 user context, 则用 navigablescreen orientation 覆盖 映射[user context] 设置模拟 screen orientation

  3. 如果 viewport 覆盖映射 包含 user context

    1. 如果 navigable顶级 traversable,且 viewport 覆盖映射[user context] 的 viewport 不是 null:

      1. navigableviewport 覆盖映射[user context] 的 viewport 设置 viewport

    2. 如果 viewport 覆盖映射[user context] 的devicePixelRatio 不是 null:

      1. navigableviewport 覆盖映射[user context] 的 devicePixelRatio 设置 device pixel ratio 覆盖

  4. navigable 更新 scrollbar type 覆盖

给定 command parameters 时,远端步骤为:

  1. 如果实现因任何原因无法用给定 command parameters 调整布局视口 参数,则返回带有错误 代码 unsupported operation错误

  2. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "context", 则返回带有错误 代码 invalid argument错误

  3. navigables 为一个集合

  4. 如果 command parameterscontext 字段存在:

    1. navigable idcommand parameterscontext 字段的值。

    2. navigable 为用 navigable id 尝试获取 navigable所得的结果。

    3. 如果 navigable 不是顶级 traversable,则返回带有 错误代码 invalid argument错误

    4. navigable 追加navigables

  5. 否则,如果 command parametersuserContexts 字段存在:

    1. user contexts 为用 command parameters["userContexts"] 尝试获取有效用户上下文所得的结果。

    2. 对于 user contexts 中的每个 user context

      1. viewport 覆盖映射[user context] 设置为一个结构体。

      2. 如果 command parameters 包含 "viewport":

        1. viewport 覆盖 映射[user context] 的viewport 设置为 command parameters["viewport"]。

      3. 如果 command parameters 包含 "devicePixelRatio":

        1. viewport 覆盖 映射[user context] 的devicePixelRatio 设置为 command parameters["devicePixelRatio"]。

      4. 对于所有顶级 traversable的列表中 其关联用户上下文user context 的每个 top-level traversable

        1. top-level traversable 追加navigables

  6. 否则,返回带有错误 代码 invalid argument错误

  7. 如果 command parameters 包含 viewport 字段:

    1. viewportcommand parameters["viewport"]。

    2. 对于 navigables 中的每个 navigable

      1. navigableviewport 设置 viewport

      2. navigable活动文档运行 CSSOM View § 13.1 Resizing viewports 步骤。

  8. 如果 command parameters 包含 devicePixelRatio 字段:

    1. device pixel ratiocommand parameters["devicePixelRatio"]。

    2. 对于 navigables 中的每个 navigable

      1. 对于 navigable 和所有后代 navigable

        1. navigabledevice pixel ratio 设置 device pixel ratio 覆盖

  9. 返回带有数据 null 的成功

7.3.3.13. browsingContext.startScreencast 命令

browsingContext.startScreencast 命令 启动给定可导航的屏幕录制,并将其写入文件。

注:远程端 创建并写入屏幕录制文件,但不会删除它。 清理该文件留给本地端。在 某些配置中这可能不 可行——例如,如果远程端 对文件系统具有读/写访问权限,但 本地端只有只读访问权限。

命令类型
browsingContext.StartScreencast = (
  method: "browsingContext.startScreencast",
  params: browsingContext.StartScreencastParameters
)

browsingContext.StartScreencastParameters = {
  context: browsingContext.BrowsingContext,
  ? mimeType: text,
  ? video: browsingContext.MediaTrackConstraints,
  ? audio: bool .default false,
}

browsingContext.MediaTrackConstraints = {
   ? width: js-uint,
   ? height: js-uint,
   ? frameRate: js-uint,
}

返回类型
browsingContext.StartScreencastResult = {
   screencast: browsingContext.Screencast,
   path: text
}

browsingContext.Screencast = text
给定 sessioncommand parameters远端步骤如下:
  1. navigable idcommand parameters["context"]。

  2. navigable 为用 navigable id 尝试获取 navigable 的结果。

  3. 如果 navigable 不是顶级可遍历对象,则返回带有 错误码 invalid argument错误

  4. 如果 command parameters 包含 mimeType 字段:

    1. mime typecommand parameters["mimeType"]。

  5. 否则,将 mime type 设置为实现定义的默认格式。

  6. 如果实现由于任何原因无法录制 navigable 的屏幕录像, 则返回带有 错误 码 unsupported operation错误

  7. stream 为用于 navigable 的一个新的屏幕录制流,按如下方式构造:

    1. 创建一个 video track,它必须是浏览器显示表面的实时捕获, 该显示表面是相关全局对象关联 `Document`navigable视口

    2. 如果 command parameters 包含 "video":

      1. videocommand parameters["video"]。

      2. 如果 video 包含 width

        1. 用户代理必须在硬件能力和其他已指定约束允许的情况下, 尝试获取宽度尽可能接近 video["width"] 的媒体。

      3. 如果 video 包含 height

        1. 用户代理必须在硬件能力和其他已指定约束允许的情况下, 尝试获取高度尽可能接近 video["height"] 的媒体。

      4. 如果 video 包含 frameRate

        1. 用户代理必须在硬件能力和其他已指定约束允许的情况下, 尝试获取帧率尽可能接近 video["frameRate"] 的媒体。

    3. video track 设置stream[video track]。

    4. 如果 command parameters["audio"] 为 true:

      1. 创建一个 audio track,它包含由下列文档的总和产生的合并音频: 相关全局对象关联 `Document`navigable活动文档,以及相关全局对象关联 `Document`navigable 的嵌套浏览上下文中的所有活动文档

      2. audio track 设置stream[audio track]。

    5. 如果实现无法产生 stream,则返回带有 错误码 unknown error错误

  8. path 为将存储录制内容的实现定义文件路径。

  9. screencastUUID 的字符串表示。

  10. recording 为一个新的屏幕录制记录,其 streamstreampathpathstate 为 "recording"、 writeError 为 null。

  11. session屏幕录制记录映射[screencast] 设置为 recording

  12. 给定 recordingmime type启动屏幕录制记录

  13. body 为一个新的映射, 其匹配 browsingContext.StartScreencastResult, 其中 screencast 字段设置为 screencast,且 path 字段设置为 path

  14. 返回带有数据 body成功

7.3.3.14. browsingContext.stopScreencast 命令

browsingContext.stopScreencast 命令 停止屏幕录制。

命令类型
browsingContext.StopScreencast = (
  method: "browsingContext.stopScreencast",
  params: browsingContext.StopScreencastParameters
)

browsingContext.StopScreencastParameters = {
  screencast: browsingContext.Screencast
}
返回类型
browsingContext.StopScreencastResult = {
   path: text,
   ? error: text
}
给定 sessioncommand parameters远程端步骤如下:
  1. screencastcommand parameters 中 "screencast" 字段的值。

  2. 如果 session屏幕录制映射包含 screencast,则返回带有错误码 无此 屏幕录制错误

  3. screencast recordingsession屏幕 录制映射[screencast]。

  4. 给定 screencast recording停止屏幕录制

  5. session屏幕录制映射移除 screencast

  6. errorscreencast recordingwriteError

  7. pathscreencast recordingpath

  8. body 为一个新的映射, 它匹配 browsingContext.StopScreencastResult, 其中 path 字段设为 path,如果 error 不为 null,则 error 字段设为 error,否则省略该字段。

  9. 返回带有数据 body成功

7.3.3.15. browsingContext.traverseHistory 命令

browsingContext.traverseHistory 命令 按 delta 遍历给定 navigable 的历史。

命令类型
browsingContext.TraverseHistory = (
  method: "browsingContext.traverseHistory",
  params: browsingContext.TraverseHistoryParameters
)

browsingContext.TraverseHistoryParameters = {
  context: browsingContext.BrowsingContext,
  delta: js-int,
}
返回类型
browsingContext.TraverseHistoryResult = EmptyResult
带有 command parameters远程端步骤如下:
  1. navigable尝试使用 command parameters["context"] 获取 可导航的结果。

  2. 如果 navigable 不是顶级可遍历,则返回带有 错误码 无效参数错误

  3. 断言:navigable 不是 null。

  4. deltacommand parameters["delta"]。

  5. resume id 为唯一字符串。

  6. navigable会话历史遍历队列排队一个任务,以运行 以下步骤:

    1. all steps 为针对 navigable 获取所有已使用历史步骤的结果。

    2. current indexnavigable当前会话历史步骤all steps 中的索引。

    3. target indexcurrent index 加上 delta

    4. 如果 all steps[target index] 不存在, 则令 valid entry 为 false,否则为 true。

    5. 使用 "check history"、resume idvalid entry 恢复

  7. is valid entry 为使用 «"check history"» 和 resume id 进行等待的结果。

  8. 如果 is valid entry 为 false,则返回带有错误 码 无此历史条目错误

  9. 给定 deltanavigable按增量遍历历史

    按照当前写法,该算法存在 竞态条件,因为当我们尝试导航时,目标会话历史条目可能已经不 存在。一旦我们支持等待历史导航完成,就可以更 稳健地处理这一点。

  10. TODO:支持等待历史遍历完成。

  11. body 为一个匹配 browsingContext.TraverseHistoryResult 产生式的映射

  12. 返回带有数据 body成功

给定 contextnavigation status navigation status 时,WebDriver BiDi page show 步骤为:

我们是否想暴露 `browsingContext.pageShow 事件?在这种情况下,我们需要 每当即将发出 `pageshow` 时调用它,而不仅仅是在 bfcache 恢复时调用,并且还要向数据中添加 persisted 状态。

  1. navigation idnavigation statusid

  2. 用 "page show"、navigation idnavigation status 恢复

给定 contextnavigation status navigation status 时,WebDriver BiDi pop state 步骤为:

  1. navigation idnavigation statusid

  2. 用 "pop state"、navigation idnavigation status 恢复

7.3.4. 事件

7.3.4.1. browsingContext.contextCreated 事件
事件类型
browsingContext.ContextCreated = (
 method: "browsingContext.contextCreated",
 params: browsingContext.Info
)

要在给定 sessionnavigable 的情况下递归发出 context created 事件

  1. sessionnavigable 发出 context created 事件

  2. 对于 navigable 的每个子 navigable child

    1. 给定 sessionchild 递归发出 context created 事件

要在给定 sessionnavigable 的情况下发出 context created 事件

  1. params 为给定 navigable、0 和 true 时调用获取 navigable 信息所得的结果。

  2. body 为一个与 browsingContext.ContextCreated 产生式匹配的映射, 其 params 字段设置为 params

  3. sessionbody 发出事件

远端事件触发器是给定 navigable navigablenavigable opener navigable 时的WebDriver BiDi navigable created 步骤:

  1. 如果提供了 opener navigable,则将 navigable原始 opener设置为 opener navigable

  2. 如果以 navigable 调用的navigable 缓存行为为 "bypass", 则执行实现定义的步骤,以禁用源自 navigable 的网络请求的任何实现特定资源缓存。

  3. related navigables 为一个包含 navigable集合

  4. 对于给定 "browsingContext.contextCreated" 和 related navigables事件已启用的会话集合 中的每个 session

    1. 给定 sessionnavigable 发出 context created 事件

给定 sessionnavigablesinclude global 时,远端订阅步骤(其 订阅优先级为 1)为:

  1. 对于 navigables 中的每个 navigable

    1. 给定 sessionnavigable 递归发出 context created 事件

7.3.4.2. browsingContext.contextDestroyed 事件
事件类型
browsingContext.ContextDestroyed = (
 method: "browsingContext.contextDestroyed",
 params: browsingContext.Info
)
远端事件触发器为:

远端事件触发器是给定 navigable navigable 时的WebDriver BiDi navigable destroyed 步骤:

  1. params 为给定 navigable、null 和 true 时调用获取 navigable 信息所得的结果。

  2. body 为一个与 browsingContext.ContextDestroyed 产生式匹配的映射, 其 params 字段设置为 params

  3. related navigables 为一个集合, 如果 navigable父级不是 null,则包含该父级; 否则为空集合

  4. 对于给定 "browsingContext.contextDestroyed" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

    2. subscriptions to remove 为一个集合

    3. 对于 session订阅中的每个 subscription

      1. 如果 subscription顶级 traversable ids 包含 navigablenavigable id

        1. subscription顶级 traversable ids移除 navigablenavigable id

        2. 如果 subscription顶级 traversable ids为空:

          1. subscription 追加subscriptions to remove

    4. session订阅移除 subscriptions to remove

尚不清楚我们是否 应当只针对具有活动文档的 browsing context 触发此事件;导航也可能导致 context 变得不可访问,但由于 bfcache 尚未被丢弃。

7.3.4.3. browsingContext.navigationStarted 事件
事件类型
browsingContext.NavigationStarted = (
 method: "browsingContext.navigationStarted",
 params: browsingContext.NavigationInfo
)
远端事件触发器是 给定 navigable navigablenavigation status navigation status 时的WebDriver BiDi navigation started 步骤:
  1. params 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. body 为一个与 browsingContext.NavigationStarted 产生式匹配的映射, 其 params 字段设置为 params

  3. navigation idnavigation statusid

  4. related navigables 为一个包含 navigable集合

  5. 用 "navigation started"、navigation idnavigation status 恢复

  6. 对于给定 "browsingContext.navigationStarted" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.4. browsingContext.fragmentNavigated 事件
事件类型
browsingContext.FragmentNavigated = (
 method: "browsingContext.fragmentNavigated",
 params: browsingContext.NavigationInfo
)
远端事件触发器是 给定 navigable navigablenavigation status navigation status 时的WebDriver BiDi fragment navigated 步骤:
  1. params 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. body 为一个与 browsingContext.FragmentNavigated 产生式匹配的映射, 其 params 字段设置为 params

  3. navigation idnavigation statusid

  4. related navigable 为一个包含 navigable集合

  5. 用 "fragment navigated"、navigation idnavigation status 恢复

  6. 对于给定 "browsingContext.fragmentNavigated" 和 related navigable事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.5. browsingContext.historyUpdated 事件
事件类型
browsingContext.HistoryUpdated = (
  method: "browsingContext.historyUpdated",
  params: browsingContext.HistoryUpdatedParameters
)

browsingContext.HistoryUpdatedParameters = {
  context: browsingContext.BrowsingContext,
  timestamp: js-uint,
  url: text,
  ? userContext: browser.UserContext
}
远程端事件触发器是给定可导航 navigableWebDriver BiDi 历史已更新步骤:
  1. url 为运行URL 序列化器的结果, 给定 navigable活动浏览上下文活动文档URL

  2. user context idnavigable关联用户 上下文用户 上下文 ID

  3. timestamp 为一个时间值,表示 UTC 中的当前日期 和时间。

  4. params 为一个匹配 browsingContext.HistoryUpdatedParameters 产生式的映射, 其中 url 字段设为 urltimestamp 字段设为 timestampcontext 字段设为 navigable可导航 ID,且 userContext 字段设为 user context id

  5. body 为一个匹配 browsingContext.HistoryUpdated 产生式的映射, 其中 params 字段设为 params

  6. related browsing contexts 为一个集合, 包含 navigable活动浏览上下文

  7. 对于给定 "browsingContext.historyUpdated" 和 related browsing contexts启用了事件的会话集合中的每个 session

    1. 使用 sessionbody 发出 事件

7.3.4.6. browsingContext.domContentLoaded 事件
事件类型
browsingContext.DomContentLoaded = (
 method: "browsingContext.domContentLoaded",
 params: browsingContext.NavigationInfo
)
远端事件触发器是 给定 navigable navigablenavigation status navigation status 时的WebDriver BiDi DOM content loaded 步骤:
  1. params 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. body 为一个与 browsingContext.DomContentLoaded 产生式匹配的映射, 其 params 字段设置为 params

  3. related navigables 为一个包含 navigable集合

  4. navigation idnavigation statusid

  5. 用 "domContentLoaded"、navigation idnavigation status 恢复

  6. 对于给定 "browsingContext.domContentLoaded" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.7. browsingContext.load 事件
事件类型
browsingContext.Load = (
 method: "browsingContext.load",
 params: browsingContext.NavigationInfo
)
远端事件触发器是给定 navigable navigablenavigation status navigation status 时的WebDriver BiDi load complete 步骤:
  1. params 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. body 为一个与 browsingContext.Load 产生式匹配的映射, 其 params 字段设置为 params

  3. related navigables 为一个包含 navigable集合

  4. navigation idnavigation statusid

  5. 用 "load"、navigation idnavigation status 恢复

  6. 对于给定 "browsingContext.load" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.8. browsingContext.downloadWillBegin 事件
事件类型
browsingContext.DownloadWillBegin = (
 method: "browsingContext.downloadWillBegin",
 params: browsingContext.DownloadWillBeginParams
)

browsingContext.DownloadWillBeginParams = {
  download: browsingContext.Download,
  suggestedFilename: text,
  browsingContext.BaseNavigationInfo
}
远程端事件触发器是给定可导航 navigable导航状态 navigation statusWebDriver BiDi 下载将开始步骤:
  1. navigation info 为给定 navigablenavigation status 获取导航 信息的结果。

  2. downloadUUID 的字符串表示。

  3. 下载 ID 映射[navigation statusdownloadResponse] 设置download

  4. params 为一个匹配 browsingContext.DownloadWillBeginParams 产生式的映射, 其中 context 字段设为 navigation info["context"], navigation 字段设为 navigation info["navigation"], timestamp 字段设为 navigation info["timestamp"],url 字段设为 navigation info["url"],download 字段设为 downloadsuggestedFilename 字段设为 navigation statussuggestedFilename

  5. body 为一个匹配 browsingContext.DownloadWillBegin 产生式的映射, 其中 params 字段设为 params

  6. navigation idnavigation statusid

  7. related navigables 为一个集合, 包含 navigable

  8. 使用 "download started"、navigation idnavigation status 恢复

  9. 对于给定 "browsingContext.downloadWillBegin" 和 related navigables启用了事件的会话集合中的每个 session

    1. 使用 sessionbody 发出 事件

  10. download behavior 为使用 navigable 获取下载行为的结果。

  11. 返回 download behavior

7.3.4.9. browsingContext.downloadEnd 事件
事件类型
browsingContext.DownloadEnd = (
  method: "browsingContext.downloadEnd",
  params: browsingContext.DownloadEndParams
)

browsingContext.DownloadEndParams = {
  (
    browsingContext.DownloadCanceledParams //
    browsingContext.DownloadCompleteParams
  )
}

browsingContext.DownloadCanceledParams = (
  status: "canceled",
  download: browsingContext.Download,
  browsingContext.BaseNavigationInfo
)

browsingContext.DownloadCompleteParams = (
  status: "complete",
  download: browsingContext.Download,
  filepath: text / null,
  browsingContext.BaseNavigationInfo
)
远程端事件触发器是给定 可导航 navigable导航 状态 navigation statusWebDriver BiDi 下载结束步骤:
  1. navigation info 为给定 navigablenavigation status 获取导航 信息的结果。

  2. 断言 navigation info["status"] 等于 "complete" 或 "canceled"。

  3. download responsenavigation statusdownloadResponse

  4. 如果下载 ID 映射包含 download response,则令 download下载 ID 映射[download response],否则令 downloadUUID 的字符串表示。

  5. 如果 navigation info["status"] 为 "complete",则令 params 为一个匹配 browsingContext.DownloadCompleteParams 产生式的映射,其中 download 字段 设为 downloadfilepath 字段设为 navigation statusdownloadedFilepathcontext 字段设为 navigation info["context"], navigation 字段设为 navigation info["navigation"], timestamp 字段设为 navigation info["timestamp"],且 url 字段设为 navigation info["url"]。

    注:对于已完成的下载,如果由于任何原因无法获得文件路径, filepath 可以为 null。

  6. 否则,令 params 为一个匹配 browsingContext.DownloadCanceledParams 产生式的映射, 其中 download 字段 设为 downloadcontext 字段设为 navigation info["context"], navigation 字段设为 navigation info["navigation"], timestamp 字段设为 navigation info["timestamp"],且 url 字段设为 navigation info["url"]。

  7. body 为一个匹配 browsingContext.DownloadEnd 产生式的映射, 其中 params 字段设为 params

  8. related navigables 为一个集合, 包含 navigable

  9. 对于给定 "browsingContext.downloadEnd" 和 related navigables启用了事件的会话集合中的每个 session

    1. 使用 sessionbody 发出 事件

7.3.4.10. browsingContext.navigationAborted 事件
事件类型
browsingContext.NavigationAborted = (
 method: "browsingContext.navigationAborted",
 params: browsingContext.NavigationInfo
)
远端事件触发器是 给定 navigable navigablenavigation status navigation status 时的WebDriver BiDi navigation aborted 步骤:
  1. params 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. body 为一个与 browsingContext.NavigationAborted 产生式匹配的映射, 其 params 字段设置为 params

  3. navigation idnavigation statusid

  4. related navigables 为一个包含 navigable集合

  5. 用 "navigation aborted"、navigation idnavigation status 恢复

  6. 对于给定 "browsingContext.navigationAborted" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.11. browsingContext.navigationCommitted 事件
事件类型
browsingContext.NavigationCommitted = (
 method: "browsingContext.navigationCommitted",
 params: browsingContext.NavigationInfo
)
远端事件触发器是 给定 navigable navigablenavigation status navigation status 时的WebDriver BiDi navigation committed 步骤:
  1. params 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. body 为一个与 browsingContext.NavigationCommitted 产生式匹配的映射, 其 params 字段设置为 params

  3. related navigables 为一个包含 navigable集合

  4. navigation idnavigation statusid

  5. 用 "navigation committed"、navigation idnavigation status 恢复

  6. 对于给定 "browsingContext.navigationCommitted" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.12. browsingContext.navigationFailed 事件
事件类型
browsingContext.NavigationFailed = (
 method: "browsingContext.navigationFailed",
 params: browsingContext.NavigationInfo
)
远端事件触发器是 给定 navigable navigablenavigation status navigation status 时的WebDriver BiDi navigation failed 步骤:
  1. params 为给定 navigablenavigation status 时调用获取 navigation 信息所得的结果。

  2. body 为一个与 browsingContext.NavigationFailed 产生式匹配的映射, 其 params 字段设置为 params

  3. navigation idnavigation statusid

  4. related navigables 为一个包含 navigable集合

  5. 用 "navigation failed"、navigation idnavigation status 恢复

  6. 对于给定 "browsingContext.navigationFailed" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.13. browsingContext.userPromptClosed 事件
事件类型
browsingContext.UserPromptClosed = (
  method: "browsingContext.userPromptClosed",
  params: browsingContext.UserPromptClosedParameters
)

browsingContext.UserPromptClosedParameters = {
  context: browsingContext.BrowsingContext,
  accepted: bool,
  type: browsingContext.UserPromptType,
  ? userContext: browser.UserContext,
  ? userText: text
}
远端事件触发器是给定 Window window、字符串 type、boolean accepted 和可选 text user text (默认值:null)时的WebDriver BiDi user prompt closed 步骤。
  1. navigablewindownavigable

  2. navigable idnavigablenavigable id

  3. user context idnavigable关联用户 上下文用户 上下文 id

  4. params 为一个与 browsingContext.UserPromptClosedParameters 产生式匹配的映射,其 context 字段设置为 navigable iduserContext 字段设置为 user context idaccepted 字段设置为 acceptedtype 字段设置为 type,且如果 user text 不是 null,则将 userText 字段设置为 user text,否则省略。

  5. body 为一个与 BrowsingContextUserPromptClosedEvent 产生式匹配的映射, 其 params 字段设置为 params

  6. related navigables 为一个包含 navigable集合

  7. 对于给定 "browsingContext.userPromptClosed" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

7.3.4.14. browsingContext.userPromptOpened 事件
事件类型
browsingContext.UserPromptOpened = (
  method: "browsingContext.userPromptOpened",
  params: browsingContext.UserPromptOpenedParameters
)

browsingContext.UserPromptOpenedParameters = {
  context: browsingContext.BrowsingContext,
  handler: session.UserPromptHandlerType,
  message: text,
  type: browsingContext.UserPromptType,
  ? userContext: browser.UserContext,
  ? defaultValue: text
}
要在给定 typenavigable 的情况下获取 navigable 的用户提示处理器
  1. user contextnavigable关联用户 上下文

  2. 如果 未处理提示行为覆盖 映射 包含 user context

    1. unhandled prompt behavior override未处理提示行为 覆盖映射[user context]。

    2. 如果 unhandled prompt behavior override[type] 不是 null,则返回 unhandled prompt behavior override[type]。

    3. 如果 unhandled prompt behavior override["default"] 不是 null, 则返回 unhandled prompt behavior override["default"]。

  3. handler configuration 为以 type 调用获取提示处理器所得的结果。

  4. 返回 handler configurationhandler

远端事件触发器是给定 Window window、字符串 type、字符串 message 和可选 text default value (默认值:null)时的WebDriver BiDi user prompt opened 步骤。
  1. navigablewindownavigable

  2. navigable idnavigablenavigable id

  3. user context idnavigable关联用户 上下文用户 上下文 id

  4. handler 为以 typenavigable 调用获取 navigable 的用户提示处理器所得的结果。

  5. params 为一个与 browsingContext.UserPromptOpenedParameters 产生式匹配的映射,其 context 字段设置为 navigable iduserContext 字段设置为 user context idtype 字段设置为 typemessage 字段设置为 message,如果 default value 不是 null,则将 defaultValue 字段设置为 default value,否则省略, 并将 handler 字段设置为 handler

  6. body 为一个与 browsingContext.UserPromptOpened 产生式匹配的映射, 其 params 字段设置为 params

  7. related navigables 为一个包含 navigable集合

  8. 对于给定 "browsingContext.userPromptOpened" 和 related navigables事件已启用的会话集合 中的每个 session

    1. sessionbody 发出 事件

  9. 如果 handler 是 "ignore",则将 handler 设置为 "none"。

  10. 返回 handler

7.4. emulation 模块

emulation 模块包含与浏览器 API 模拟相关的命令和事件。

7.4.1. 定义

remote end definition

EmulationCommand = (
  emulation.SetForcedColorsModeThemeOverride //
  emulation.SetGeolocationOverride //
  emulation.SetLocaleOverride //
  emulation.SetNetworkConditions //
  emulation.SetScreenOrientationOverride //
  emulation.SetScreenSettingsOverride //
  emulation.SetScriptingEnabled //
  emulation.SetScrollbarTypeOverride //
  emulation.SetTimezoneOverride //
  emulation.SetTouchOverride //
  emulation.SetUserAgentOverride
)

EmulationResult = (
  emulation.SetForcedColorsModeThemeOverrideResult /
  emulation.SetGeolocationOverrideResult /
  emulation.SetLocaleOverrideResult /
  emulation.SetScreenOrientationOverrideResult /
  emulation.SetScriptingEnabledResult /
  emulation.SetScrollbarTypeOverrideResult /
  emulation.SetTimezoneOverrideResult /
  emulation.SetTouchOverrideResult /
  emulation.SetUserAgentOverrideResult
)

一个 BiDi 会话具有一个模拟用户代理,它是一个具有 一个名为 默认用户代理结构体,该项是字符串或 null; 一个名为 用户上下文用户代理,该项是 用户上下文与 字符串之间的弱映射;以及一个名为 可导航用户代理,该项是 可导航与字符串之间的弱映射。

一个 BiDi 会话具有 模拟 maxTouchPoints,它是一个结构体,具有 一个名为 default,该项是整数或 null,初始为 null; 一个名为 user contexts,该项是 用户上下文与整数之间的弱映射, 初始为空; 以及一个名为 navigables,该项是 可导航与整数之间的弱映射,初始为空。

屏幕 方向覆盖是一个具有以下内容的结构体

一个远程端具有一个 屏幕方向覆盖映射,它是 用户上下文屏幕 方向覆盖之间的弱 映射。

7.4.2. 命令

7.4.2.1. emulation.setForcedColorsModeThemeOverride 命令

emulation.setForcedColorsModeThemeOverride 命令修改给定顶级 traversables 或用户上下文上的 forced colors mode 主题特征。

命令类型
emulation.SetForcedColorsModeThemeOverride = (
  method: "emulation.setForcedColorsModeThemeOverride",
  params: emulation.SetForcedColorsModeThemeOverrideParameters
)

emulation.SetForcedColorsModeThemeOverrideParameters = {
  theme: emulation.ForcedColorsModeTheme / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.ForcedColorsModeTheme = "light" / "dark"
返回类型
emulation.SetForcedColorsModeThemeOverrideResult = EmptyResult

注:对应的 CSS 规范中的枚举映射,请查看 ForcedColorsModeAutomationTheme

远端具有一个forced colors mode theme override 配置,它是 WebDriver 配置,其关联类型为字符串。

要为 navigable navigable 更新模拟 forced colors 主题
  1. theme 为针对 navigableforced colors mode theme override 配置调用获取 WebDriver 配置值所得的结果。

  2. 断言:theme 是 "light"、"dark" 或 unset

  3. 如果 themeunset,则将 theme 设置为 "none"。

  4. navigabletheme 设置模拟 forced colors 主题数据

带有 command parameters远程端步骤如下:

  1. themecommand parameters["theme"]。

  2. 如果 theme 为 null,则将 theme 设为未设置

  3. 如果实现不支持设置 theme,则返回带有错误 码 不支持的操作错误

  4. affected navigables尝试command parameters 存储 WebDriver 配置 强制颜色模式主题 覆盖配置 theme 的结果。

  5. 对于 affected navigables 中的每个 navigable

    1. navigable 更新模拟的强制颜色 主题

  6. 返回带有数据 null 的成功

7.4.2.2. emulation.setGeolocationOverride 命令

emulation.setGeolocationOverride 命令修改 给定顶级 traversables 或用户上下文上的 geolocation 特征。

命令类型
emulation.SetGeolocationOverride = (
  method: "emulation.setGeolocationOverride",
  params: emulation.SetGeolocationOverrideParameters
)

emulation.SetGeolocationOverrideParameters = {
  (
    (coordinates: emulation.GeolocationCoordinates / null) //
    (error: emulation.GeolocationPositionError)
  ),
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.GeolocationCoordinates = {
   latitude: -90.0..90.0,
   longitude: -180.0..180.0,
   ? accuracy: (float .ge 0.0) .default 1.0,
   ? altitude: float / null .default null,
   ? altitudeAccuracy: (float .ge 0.0) / null .default null,
   ? heading: (0.0...360.0) / null .default null,
   ? speed: (float .ge 0.0) / null .default null,
}

emulation.GeolocationPositionError = {
   type: "positionUnavailable"
}
返回类型
emulation.SetGeolocationOverrideResult = EmptyResult

地理位置 覆盖是一个具有以下内容的结构体

一个远程端具有一个 地理位置覆盖配置,它是 WebDriver 配置,并具有关联类型 地理位置覆盖

要为可导航 navigable 更新 地理位置覆盖
  1. emulated position data 为获取 navigable地理位置覆盖配置WebDriver 配置值的结果。

  2. 如果 emulated position data未设置,则将 emulated position data 设为 null。

  3. 使用 navigableemulated position data 设置模拟位置数据

带有 command parameters远端步骤如下:

  1. 如果 command parameters 包含 "coordinates",并且 command parameters["coordinates"] 包含 "altitudeAccuracy",且 command parameters["coordinates"] 不包含 "altitude",则返回带有错误码 invalid argument错误

  2. 如果 command parameters 包含 "error":

    1. 断言 command parameters["error"]["type"] 等于 "positionUnavailable"。

    2. emulated position data 为一个匹配 GeolocationPositionError 产生式的映射, 其中 code 字段设置为 POSITION_UNAVAILABLE, 且 message 字段设置为空字符串。

      注:根据 geolocation 规范,message 会被 实现忽略。

  3. 否则,令 emulated position datacommand parameters["coordinates"]。

  4. 如果 emulated position data 为 null,则将 emulated position data 设置为 unset

  5. affected navigables 为用 command parameters 尝试存储 WebDriver 配置 geolocation override configuration emulated position data 的结果。

  6. 对于 affected navigables 的每个 navigable

    1. navigable 更新地理位置覆盖

  7. 返回带有数据 null 的成功

7.4.2.3. emulation.setLocaleOverride 命令

emulation.setLocaleOverride 命令修改 给定顶级 traversables 或用户上下文上的 locale。

命令类型
emulation.SetLocaleOverride = (
  method: "emulation.setLocaleOverride",
  params: emulation.SetLocaleOverrideParameters
)

emulation.SetLocaleOverrideParameters = {
  locale: text / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetLocaleOverrideResult = EmptyResult

给定一个环境设置对象 environment settings 时,WebDriver BiDi 模拟语言步骤为:

  1. related navigables 为给定 environment settings 获取相关 navigable的结果。

  2. 对于 related navigables 的每个 navigable

    1. top-level traversablenavigable顶级可遍历对象

    2. user contexttop-level traversable关联 用户上下文

    3. 如果 locale 覆盖映射 包含 top-level traversable,则返回 locale 覆盖映射[top-level traversable]。

    4. 如果 locale 覆盖映射 包含 user context,则返回 locale 覆盖映射[user context]。

  3. 返回 null

带有 command parameters远端步骤如下:

  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 码 invalid argument错误

  2. 如果 command parameters包含 "userContexts" 且 command parameters包含 "contexts", 则返回带有错误 码 invalid argument错误

  3. emulated localecommand parameters["locale"]。

  4. 如果 emulated locale 不为 null,且 IsStructurallyValidLanguageTag(emulated locale) 返回 false,则返回带有错误 码 invalid argument错误

  5. navigables 为一个集合

  6. 如果 command parameterscontexts 字段存在:

    1. navigables 为用 command parameters["contexts"] 尝试 通过 ID 获取有效顶级 可遍历对象的结果。

  7. 否则:

    1. 断言 command parametersuserContexts 字段存在。

    2. user contexts 为用 command parameters["userContexts"] 尝试 获取有效用户上下文 的结果。

    3. 对于 user contexts 的每个 user context

      1. 如果 emulated locale 为 null,则从 locale 覆盖映射移除 user context

      2. 否则,将 locale 覆盖映射[user context] 设置emulated locale

      3. 对于所有顶级可遍历对象中其关联用户上下文user context 的列表的每个 top-level traversable

        1. top-level traversable 追加navigables

  8. 对于 navigables 的每个 navigable

    1. 如果 emulated locale 为 null,则从 locale 覆盖映射移除 navigable

    2. 否则,将 locale 覆盖映射[navigable] 设置emulated locale

  9. 返回带有数据 null 的成功

7.4.2.4. emulation.setNetworkConditions 命令

emulation.setNetworkConditions 命令 为给定浏览上下文或用户上下文模拟特定的网络条件。

命令类型
emulation.SetNetworkConditions = (
  method: "emulation.setNetworkConditions",
  params: emulation.SetNetworkConditionsParameters
)

emulation.SetNetworkConditionsParameters = {
  networkConditions: emulation.NetworkConditions / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.NetworkConditions = emulation.NetworkConditionsOffline

emulation.NetworkConditionsOffline = {
  type: "offline"
}
返回类型
emulation.SetNetworkConditionsResult = EmptyResult

应用网络 条件

  1. 对于每个 WebSocket 对象 webSocket

    1. realmwebSocket相关 Realm

    2. environment settings 为其 realm execution context 的 Realm 组件 是 realm环境设置对象

    3. 如果以 environment settings 调用WebDriver BiDi 网络离线 所得的结果为 true:

      1. 使 WebSocket 连接失败 webSocket

  2. 对于每个 WebTransport 对象 webTransport

    1. realmwebSocket相关 Realm

    2. environment settings 为其 realm execution context 的 Realm 组件 是 realm环境设置对象

    3. 如果以 environment settings 调用WebDriver BiDi 网络 离线所得的结果为 true:

      1. 清理 WebTransport webTransport

带有 command parameterssession远端步骤如下:

  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "context", 则返回带有错误 码 invalid argument错误

  2. emulated network conditions 为 null。

  3. 如果 command parameters["networkConditions"] 不为 null,且 command parameters["networkConditions"]["type"] 等于 "offline",则将 emulated network conditions 设置为一个新的 模拟网络条件结构,其 offline 设置为 true。

  4. 如果 command parameterscontexts 字段存在:

    1. navigables 为用 command parameters["contexts"] 尝试 通过 ID 获取有效顶级 可遍历对象的结果。

    2. 对于 navigables 的每个 navigable

      1. 如果 emulated network conditions 为 null,则从 session模拟网络 条件navigable 网络条件移除 navigable

      2. 否则,将 session模拟网络 条件navigable 网络条件[navigable] 设置emulated network conditions

  5. 如果 command parametersuserContexts 字段存在:

    1. user contexts 为用 command parameters["userContexts"] 尝试 获取有效用户上下文 的结果。

    2. 对于 user contexts 的每个 user context

      1. 如果 emulated network conditions 为 null,则从 session模拟网络 条件用户 上下文网络条件移除 user context

      2. 否则,将 session模拟网络 条件用户 上下文网络条件[user context] 设置emulated network conditions

  6. 如果 command parameters包含 "userContexts" 且 command parameters包含 "context", 则将 session模拟网络条件默认网络 条件设置emulated network conditions

  7. 应用网络条件

  8. 返回带有数据 null 的成功

7.4.2.5. emulation.setScreenSettingsOverride 命令

emulation.setScreenSettingsOverride 命令 模拟给定顶级 traversables 或用户上下文的Web 暴露屏幕区域Web 暴露可用屏幕区域

命令类型
emulation.SetScreenSettingsOverride = (
  method: "emulation.setScreenSettingsOverride",
  params: emulation.SetScreenSettingsOverrideParameters
)

emulation.ScreenArea = {
  width: js-uint,
  height: js-uint
}

emulation.SetScreenSettingsOverrideParameters = {
  screenArea: emulation.ScreenArea / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetScreenSettingsOverrideResult = EmptyResult

给定navigable navigable 时,WebDriver BiDi 模拟可用屏幕 区域步骤为:

  1. top-level traversablenavigable顶级可遍历对象

  2. user contexttop-level traversable关联用户 上下文

  3. 如果 屏幕设置覆盖 包含 top-level traversable,则返回 屏幕设置覆盖[top-level traversable]。

  4. 如果 屏幕设置覆盖 包含 user context,则返回 屏幕设置覆盖[user context]。

  5. 返回 null

给定navigable navigable 时,WebDriver BiDi 模拟总屏幕区域步骤 为:

  1. top-level traversablenavigable顶级可遍历对象

  2. user contexttop-level traversable关联用户 上下文

  3. 如果 屏幕设置覆盖 包含 top-level traversable,则返回 屏幕设置覆盖[top-level traversable]。

  4. 如果 屏幕设置覆盖 包含 user context,则返回 屏幕设置覆盖[user context]。

  5. 返回 null

带有 command parameters远端步骤如下:

  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 码 invalid argument错误

  2. 如果 command parameters包含 "userContexts" 且 command parameters包含 "contexts", 则返回带有错误 码 invalid argument错误

  3. emulated screen areacommand parameters["screenArea"]。

  4. 如果 emulated screen area 不为 null:

    1. emulated screen area["x"] 设置为 0。

    2. emulated screen area["y"] 设置为 0。

  5. navigables 为一个集合

  6. 如果 command parameterscontexts 字段存在:

    1. navigables 为用 command parameters["contexts"] 尝试 通过 ID 获取有效顶级 可遍历对象的结果。

    2. targetnavigable 屏幕 设置

    3. 对于 navigables 的每个 navigable

      1. 如果 emulated screen area 为 null,则从 target移除 navigable

      2. 否则,将 target[navigable] 设置emulated screen area

    4. 返回带有数据 null 的成功

  7. 否则:

    1. 断言 command parametersuserContexts 字段存在。

    2. user contexts 为用 command parameters["userContexts"] 尝试 获取有效用户上下文 的结果。

    3. target用户上下文 屏幕设置

    4. 对于 user contexts 的每个 user context

      1. 如果 emulated screen area 为 null,则从 target移除 user context

      2. 否则,将 target[user context] 设置emulated screen area

    5. 返回带有数据 null 的成功

7.4.2.6. emulation.setScreenOrientationOverride 命令

emulation.setScreenOrientationOverride 命令 模拟给定顶级可遍历或用户上下文的屏幕方向

命令类型
emulation.SetScreenOrientationOverride = (
  method: "emulation.setScreenOrientationOverride",
  params: emulation.SetScreenOrientationOverrideParameters
)

emulation.ScreenOrientationNatural = "portrait" / "landscape"
emulation.ScreenOrientationType = "portrait-primary" / "portrait-secondary" / "landscape-primary" / "landscape-secondary"

emulation.ScreenOrientation = {
  natural: emulation.ScreenOrientationNatural,
  type: emulation.ScreenOrientationType
}

emulation.SetScreenOrientationOverrideParameters = {
  screenOrientation: emulation.ScreenOrientation / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetScreenOrientationOverrideResult = EmptyResult

要在给定 navigableemulated screen orientation 的情况下,设置 模拟屏幕方向

将此算法移至 屏幕方向规范。

  1. 如果 emulated screen orientation 为 null:

    1. navigable当前方向角设为 实现定义的默认值。

    2. navigable当前方向类型设为 实现定义的默认值。

  2. 否则:

    1. emulated orientation typeemulated screen orientation["type"]。

    2. emulated orientation angleemulated orientation type 关联的角度,适用于具有 emulated screen orientation["natural"] 方向的屏幕,如屏幕方向值 列表中所定义。

    3. 当前方向角设为 emulated orientation angle

    4. 当前方向类型设为 emulated orientation type

  3. 使用 navigable活动文档运行屏幕方向变更步骤

带有 command parameters远端步骤如下:

  1. 如果实现由于任何原因无法使用给定的 command parameters 调整屏幕方向 参数,则返回带有错误 码 unsupported operation错误

  2. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 码 invalid argument错误

  3. 如果 command parameters包含 "userContexts" 且 command parameters包含 "contexts", 则返回带有错误 码 invalid argument错误

  4. emulated screen orientationcommand parameters["screenOrientation"]。

  5. navigables 为一个集合

  6. 如果 command parameterscontexts 字段存在:

    1. navigables 为用 command parameters["contexts"] 尝试 通过 ID 获取有效顶级 可遍历对象的结果。

  7. 否则,如果 command parametersuserContexts 字段 存在:

    1. user contexts 为用 command parameters["userContexts"] 尝试 获取有效用户上下文 的结果。

    2. 对于 user contexts 的每个 user context

      1. 如果 emulated screen orientation 为 null,则从 screen orientation overrides map移除 user context

      2. 否则,将 screen orientation overrides map[user context] 设置emulated screen orientation

      3. 对于所有顶级可遍历对象中其关联用户上下文user context 的列表的每个 top-level traversable

        1. top-level traversable 追加navigables

  8. 对于 navigables 的每个 navigable

    1. user contextnavigable关联 用户上下文

    2. 如果 emulated screen orientation 为 null,且 screen orientation overrides map 包含 user context,则用 navigablescreen orientation overrides map[user context] 设置模拟屏幕方向

    3. 否则,用 navigableemulated screen orientation 设置模拟屏幕方向

  9. 返回带有数据 null 的成功

7.4.2.7. emulation.setUserAgentOverride 命令

emulation.setUserAgentOverride 命令会修改 给定顶级可遍历、用户上下文或全局的 User-Agent。

命令类型
emulation.SetUserAgentOverride = (
  method: "emulation.setUserAgentOverride",
  params: emulation.SetUserAgentOverrideParameters
)

emulation.SetUserAgentOverrideParameters = {
  userAgent: text / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetUserAgentOverrideResult = EmptyResult
给定 环境设置对象 environment settingsWebDriver BiDi 模拟 User-Agent步骤如下:
  1. related navigables 为使用 environment settings 获取相关 可导航的结果。

  2. 对于每个 navigablerelated navigables

    1. top-level navigablenavigable顶级可遍历

    2. user contexttop-level navigable关联 用户上下文

    3. 对于活动 BiDi 会话中的每个 session

      1. 如果 session模拟用户代理可导航用户 代理包含 top-level navigable,则返回 session模拟用户代理可导航用户 代理[top-level navigable]。

    4. 对于活动 BiDi 会话中的每个 session

      1. 如果 session模拟用户代理用户上下文用户 代理 包含 user context,则返回 session模拟用户代理用户上下文用户 代理[user context]。

  3. 对于活动 BiDi 会话中的每个 session

    1. default emulated user agentsession模拟用户代理默认用户代理

    2. 如果 default emulated user agent 不为 null,则返回 default emulated user agent

  4. 返回 null。

给定 sessioncommand parameters远端步骤如下:

  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 码 invalid argument错误

  2. emulated user agentcommand parameters["userAgent"]。

  3. 如果 command parameters 包含 "contexts":

    1. navigables 为用 command parameters["contexts"] 尝试 通过 ID 获取有效顶级 可遍历对象的结果。

    2. 对于 navigables 的每个 navigable

      1. 如果 emulated user agent 为 null,则从 session模拟用户代理navigable 用户 代理移除 navigable

      2. 否则,将 session模拟用户代理navigable 用户 代理[navigable] 设置emulated user agent

    3. 返回带有数据 null 的成功

  4. 如果 command parameters 包含 "userContexts":

    1. user contexts 为用 command parameters["userContexts"] 尝试 获取有效用户上下文 的结果。

    2. 对于 user contexts 的每个 user context

      1. 如果 emulated user agent 为 null,则从 session模拟用户代理用户上下文用户 代理移除 user context

      2. 否则,将 session模拟用户代理用户上下文用户 代理[user context] 设置emulated user agent

    3. 返回带有数据 null 的成功

  5. session模拟用户 代理默认用户代理设置emulated user agent

  6. 返回带有数据 null 的成功

7.4.2.8. emulation.setScriptingEnabled 命令

emulation.setScriptingEnabled 命令模拟 在网页上禁用 JavaScript。

命令类型
emulation.SetScriptingEnabled = (
  method: "emulation.setScriptingEnabled",
  params: emulation.SetScriptingEnabledParameters
)

emulation.SetScriptingEnabledParameters = {
  enabled: false / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetScriptingEnabledResult = EmptyResult

注:仅支持模拟已禁用的 Javascript。

给定 环境设置对象 settingsWebDriver BiDi 脚本已启用步骤如下:
  1. navigablesettings相关全局对象关联 Document节点可导航

  2. top-level traversablenavigable顶级可遍历

  3. 如果脚本启用覆盖映射包含 top-level traversable,则返回 脚本启用覆盖 映射[top-level traversable]

  4. user contexttop-level traversable关联用户 上下文

  5. 如果脚本启用覆盖映射包含 user context,则返回 脚本启用覆盖映射[user context]。

  6. 返回 true。

带有 command parameters远端步骤如下:

  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 码 invalid argument错误

  2. 如果 command parameters包含 "userContexts" 且 command parameters包含 "contexts", 则返回带有错误 码 invalid argument错误

  3. emulated scripting enabled statuscommand parameters["enabled"]。

  4. 如果 command parameterscontexts 字段存在:

    1. navigables 为用 command parameters["contexts"] 尝试 通过 ID 获取有效顶级 可遍历对象的结果。

    2. 对于 navigables 的每个 navigable

      1. 如果 emulated scripting enabled status 为 null,则从 scripting enabled overrides map移除 navigable

      2. 否则,将 scripting enabled overrides map[navigable] 设置emulated scripting enabled status

  5. 如果 command parametersuserContexts 字段存在:

    1. user contexts 为用 command parameters["userContexts"] 尝试 获取有效用户上下文 的结果。

    2. 对于 user contexts 的每个 user context

      1. 如果 emulated scripting enabled status 为 null,则从 scripting enabled overrides map移除 user context

      2. 否则,将 scripting enabled overrides map[user context] 设置emulated scripting enabled status

  6. 返回带有数据 null 的成功

7.4.2.9. emulation.setScrollbarTypeOverride 命令

emulation.setScrollbarTypeOverride 命令 修改 给定顶级可遍历、用户上下文或全局的滚动条类型。

命令类型
emulation.SetScrollbarTypeOverride = (
  method: "emulation.setScrollbarTypeOverride",
  params: emulation.SetScrollbarTypeOverrideParameters
)

emulation.SetScrollbarTypeOverrideParameters = {
  scrollbarType: "classic" / "overlay" / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetScrollbarTypeOverrideResult = EmptyResult

一个远程端具有一个 滚动条类型覆盖配置, 它是具有关联类型字符串的 WebDriver 配置

要为可导航 navigable 更新 滚动条类型覆盖
  1. scrollbar type override 为获取 navigable滚动条类型覆盖配置WebDriver 配置值的结果。

  2. 断言:scrollbar type override 为 "classic"、 "overlay" 或 未设置

  3. 如果 scrollbar type override 为 "classic",则运行实现定义的步骤,使 navigable活动文档使用经典滚动条并返回。

  4. 如果 scrollbar type override 为 "overlay",则运行实现定义的 步骤,使 navigable活动文档使用覆盖滚动条并返回。

  5. 断言:scrollbar type override未设置

  6. 运行实现定义的步骤,使 navigable活动文档 使用实现定义的默认滚动条类型。

给定 command parameters远程端步骤如下:

  1. scrollbar type overridecommand parameters["scrollbarType"]。

  2. 如果 scrollbar type override 为 null,则将 scrollbar type override 设为 未设置

  3. 如果实现不支持设置 scrollbar type override,则返回带有错误码 不支持的操作错误

  4. affected navigables尝试command parameters 存储 WebDriver 配置 滚动条类型覆盖 配置 scrollbar type override 的结果。

  5. 对于 affected navigables 中的每个 navigable

    1. navigable 更新滚动条类型覆盖

  6. 返回带有数据 null 的成功

7.4.2.10. emulation.setTimezoneOverride 命令

emulation.setTimezoneOverride 命令会修改 给定顶级可遍历或用户上下文的时区。

命令类型
emulation.SetTimezoneOverride = (
  method: "emulation.setTimezoneOverride",
  params: emulation.SetTimezoneOverrideParameters
)

emulation.SetTimezoneOverrideParameters = {
  timezone: text / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetTimezoneOverrideResult = EmptyResult
SystemTimeZoneIdentifier 算法是实现 定义的。WebDriver-BiDi 远端必须有一个运行以下 步骤的实现:
  1. emulated timezone 为 null。

  2. realm当前 Realm Record

  3. environment settings 为其 领域执行上下文的 Realm 组件是 realm环境设置对象

  4. related navigables 为给定 environment settings 获取相关 navigable的结果。

  5. 对于 related navigables 的每个 navigable

    1. top-level traversablenavigable顶级可遍历对象

    2. user contexttop-level traversable关联 用户上下文

    3. 如果 时区覆盖映射 包含 top-level traversable,则将 emulated timezone 设置为 时区覆盖映射[top-level traversable]。

    4. 否则,如果 时区覆盖映射 包含 user context,则将 emulated timezone 设置为 时区覆盖映射[user context]。

  6. 如果 emulated timezone 不为 null,则返回 emulated timezone

  7. 返回符合 SystemTimeZoneIdentifier 规范要求的 实现定义步骤的结果。

带有 command parameters远端步骤如下:

  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 码 invalid argument错误

  2. 如果 command parameters包含 "userContexts" 且 command parameters包含 "contexts", 则返回带有错误 码 invalid argument错误

  3. emulated timezonecommand parameters["timezone"]。

  4. 如果 emulated timezone 不为 null,且 IsTimeZoneOffsetString(emulated timezone) 返回 false,并且 AvailableNamedTimeZoneIdentifiers包含 emulated timezone,则返回带有错误码 invalid argument错误

  5. navigables 为一个集合

  6. 如果 command parameterscontexts 字段存在:

    1. navigables 为用 command parameters["contexts"] 尝试 通过 ID 获取有效顶级 可遍历对象的结果。

  7. 否则:

    1. 断言 command parametersuserContexts 字段存在。

    2. user contexts 为用 command parameters["userContexts"] 尝试 获取有效用户上下文 的结果。

    3. 对于 user contexts 的每个 user context

      1. 如果 emulated timezone 为 null,则从 时区覆盖映射移除 user context

      2. 否则,将 时区 覆盖映射[user context] 设置emulated timezone

      3. 对于所有顶级可遍历对象中其关联用户上下文user context 的列表的每个 top-level traversable

        1. top-level traversable 追加navigables

  8. 对于 navigables 的每个 navigable

    1. 如果 emulated timezone 为 null,则从 时区覆盖映射移除 navigable

    2. 否则,将 时区 覆盖映射[navigable] 设置emulated timezone

  9. 返回带有数据 null 的成功

7.4.2.11. emulation.setTouchOverride 命令

emulation.setTouchOverride 命令模拟 网页上的已启用触摸输入。

命令类型
emulation.SetTouchOverride = (
  method: "emulation.setTouchOverride",
  params: emulation.SetTouchOverrideParameters
)

emulation.SetTouchOverrideParameters = {
  maxTouchPoints: (js-uint .ge 1) / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
emulation.SetTouchOverrideResult = EmptyResult
给定 环境设置对象 environment settingsWebDriver BiDi 模拟最大触摸点数步骤如下:
  1. related navigables 为使用 environment settings 获取相关 可导航的结果。

  2. 对于 related navigables 中的每个 navigable

    1. top-level navigablenavigable顶级可遍历

    2. user contexttop-level navigable关联 用户上下文

    3. 对于活动 BiDi 会话中的每个 session

      1. 如果 session模拟 maxTouchPointsnavigables 包含 top-level navigable,则返回 session模拟 maxTouchPointsnavigables[top-level navigable]。

    4. 对于活动 BiDi 会话中的每个 session

      1. 如果 session模拟 maxTouchPointsuser contexts 包含 user context,则返回 session模拟 maxTouchPointsuser contexts[user context]。

  3. 对于活动 BiDi 会话中的每个 session

    1. emulated maxTouchPointssession模拟 maxTouchPointsdefault

    2. 如果 emulated maxTouchPoints 不为 null,则返回 emulated maxTouchPoints

  4. 返回 null。

带有 sessioncommand parameters远程端步骤如下:

注:存在一个旧式的暴露旧式触摸事件 API, 一些现有 Web 内容仍可能将其用作用户代理是启用触摸的“移动”设备的信号。尽管该 API 是旧式的,用户代理仍可能运行实现定义的步骤,以在暴露旧式触摸事件 API中遵循 模拟 maxTouchPoints 状态。

  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts",则返回带有错误 码 invalid argument错误

  2. maxTouchPointscommand parameters["maxTouchPoints"]。

  3. 如果 command parameterscontexts 字段存在:

    1. navigables尝试使用 command parameters["contexts"] 通过 ID 获取有效顶级 可遍历 的结果。

    2. 对于 navigables 中的每个 navigable

      1. 如果 maxTouchPoints 为 null,则从 session模拟 maxTouchPointsnavigables移除 navigable

      2. 否则,将 session模拟 maxTouchPointsnavigables[navigable] 设置maxTouchPoints

    3. 返回带有数据 null 的成功

  4. 如果 command parametersuserContexts 字段存在:

    1. user contexts尝试使用 command parameters["userContexts"] 获取有效用户上下文的结果。

    2. 对于 user contexts 中的每个 user context

      1. 如果 maxTouchPoints 为 null,则从 session模拟 maxTouchPointsuser contexts移除 user context

      2. 否则,将 session模拟 maxTouchPointsuser contexts[user context] 设置maxTouchPoints

    3. 返回带有数据 null 的成功

  5. session模拟 maxTouchPointsdefault 设为 maxTouchPoints

  6. 返回带有数据 null 的成功

7.5. network 模块

network 模块包含与网络请求相关的命令和事件。

7.5.1. 定义

远程端定义

NetworkCommand = (
  network.AddDataCollector //
  network.AddIntercept //
  network.ContinueRequest //
  network.ContinueResponse //
  network.ContinueWithAuth //
  network.DisownData //
  network.FailRequest //
  network.GetData //
  network.ProvideResponse //
  network.RemoveDataCollector //
  network.RemoveIntercept //
  network.SetCacheBehavior //
  network.SetExtraHeaders
)

本地端定义

NetworkResult = (
  network.AddDataCollectorResult /
  network.AddInterceptResult /
  network.ContinueRequestResult /
  network.ContinueResponseResult /
  network.ContinueWithAuthResult /
  network.DisownDataResult /
  network.FailRequestResult /
  network.GetDataResult /
  network.ProvideResponseResult /
  network.RemoveDataCollectorResult /
  network.RemoveInterceptResult /
  network.SetCacheBehaviorResult /
  network.SetExtraHeadersResult
)

NetworkEvent = (
    network.AuthRequired //
    network.BeforeRequestSent //
    network.FetchError //
    network.ResponseCompleted //
    network.ResponseStarted
)

一个远程端具有一个 请求发送前映射,其初始为空映射。它用于跟踪 已发送过 network.beforeRequestSent 事件的网络事件。

一个远程端具有一个 默认缓存行为,它是字符串。其初始为 "default"。

一个远程端具有一个 可导航缓存行为映射,它是顶级可遍历与表示缓存 行为的字符串之间的弱映射。其初始为空。

一个 BiDi 会话具有 额外标头,它是一个结构体,具有 一个名为 默认 标头,它是一个标头 列表(初始设为空 标头列表);一个名为 用户上下文标头,它是 用户上下文标头列表之间的弱映射;以及一个名为 可导航标头,它是 可导航标头 列表之间的弱映射。

7.5.2. 网络数据收集

网络数据是一个具有以下内容的结构体

collector 是一个具有以下内容的结构体

注:max encoded item size 定义每项(响应或请求)的限制, 并不限制特定 collector 所收集的大小。所有已收集资源的总大小 由 最大总收集大小限制。

一个 BiDi 会话具有 network collectors, 它是 network.Collectorcollector之间的映射。其初始为空。

一个远程端具有 已收集网络数据,它是 网络数据的列表。其初始为空。

一个远程端具有一个 最大总收集大小,它是表示 在已收集网络数据中分配给收集网络数据的大小的 js-uint。其 值是实现定义的。

注:这允许实现设置资源使用 限制。 预期这些限制足够大,使用户可以依赖 收集已由浏览器完全解码和处理的数据, 例如网页中使用的图片和字体。

要在给定 request 的情况下获取 request 的 navigable
  1. navigable 为 null。

  2. 如果 requestclient 是一个环境设置对象

    1. environment settingsrequestclient

    2. 如果存在一个navigable,其活动 windowenvironment settings全局对象,则将 navigable 设置为该 navigable。

  3. 返回 navigable

要在给定 collectornavigable 的情况下匹配 navigable 的 collector
  1. 如果 collectorcontexts 不是

    1. 如果 collectorcontexts 包含 navigablenavigable id,则返回 true。

    2. 否则,返回 false。

  2. 如果 collectoruser contexts 不是

    1. user contextnavigable关联 用户上下文

    2. 如果 collectoruser contexts 包含 user context用户上下文 id,则返回 true。

    3. 否则,返回 false。

  3. 返回 true。

给定 request request 时,WebDriver BiDi 克隆网络请求 body步骤为:
  1. 如果 requestbody 为 null,则返回。

  2. 对于 活动 BiDi 会话中的每个 session

    1. 如果 sessionnetwork collectors 不是

      1. collected data 为一个network data,其中 bytes 设置为 null, cloned body 设置为 requestbody克隆collectors 设置为空列表, pending 设置为 true, request 设置为 requestrequest idsize 设置为 null, type 设置为 "request"。

      2. collected data 追加collected network data

      3. 返回。

给定 requestresponse body 时,WebDriver BiDi 克隆网络响应 body步骤为:
  1. 如果 response body 为 null,则返回。

  2. 对于 活动 BiDi 会话中的每个 session

    1. 如果 sessionnetwork collectors 不是

      1. collected data 为一个network data,其中 bytes 设置为 null, cloned body 设置为 response body克隆collectors 设置为空列表, pending 设置为 true, request 设置为 requestrequest idsize 设置为 null, type 设置为 "response"。

      2. collected data 追加collected network data

      3. 返回。

要在给定 request iddata type 的情况下获取 collected data
  1. 对于 collected network data 中的每个 collected data

    1. 如果 collected datarequestrequest id,且 collected datatypedata type,则返回 collected data

  2. 返回 null。

要在给定 request 的情况下可能中止网络响应 body 收集
  1. collected data 为以 requestrequest id 和 "response" 调用获取 collected data所得的结果。

  2. 如果 collected data 为 null,则返回。

  3. collected datapending 设置为 false。

  4. 用 "network data collected" 和 (requestrequest id, "response") 恢复

要在给定 request 的情况下可能 收集网络请求 body
  1. collected data 为以 requestrequest id 和 "request" 调用获取 collected data所得的结果。

  2. 如果 collected data 为 null,则返回。

    注:如果在创建请求时没有设置 collectors, 且 WebDriver BiDi 克隆网络请求 body未克隆对应的 body, 或者 body 一开始就是 null,则可能发生这种情况。

  3. requestcollected data、null 和 "request" 调用可能收集 network data

要在给定 requestresponse 的情况下可能 收集网络响应 body
  1. 如果 responsestatusredirect status,则返回。

    注:对于重定向,仅存储最终响应 body。

  2. collected data 为以 requestrequest id 和 "response" 调用获取 collected data所得的结果。

  3. 如果 collected data 为 null,则返回。

    注:如果在创建响应时没有设置 collectors, 且 WebDriver BiDi 克隆网络 响应 body未克隆对应的 body, 或者 body 一开始就是 null,则可能发生这种情况。

  4. sizeresponseresponse body infoencoded size

    注:从 fetch stream 检索的 bytes 对应于已解码数据这一事实与为了计算大小限制而使用编码(网络)大小之间存在差异。 实现可以决定使用这样的存储模型:只要在 getData 中返回给客户端的数据与已解码数据相同, 其使用的大小就可以小于存储已解码数据所需的大小。存储与性能之间的潜在 取舍由实现决定。

  5. requestcollected datasize 和 "response" 调用可能收集 network data

要在给定 request requestnetwork data collected data、js-uint sizenetwork.DataType data type 的情况下可能收集 network data
  1. collected datapending 设置为 false。

  2. navigable 为以 request 调用获取 request 的 navigable所得的结果。

  3. 如果 navigable 为 null:

    1. collected network data移除 collected data

    2. 用 "network data collected" 和 (requestrequest id, data type) 恢复

    3. 返回。

    这会阻止 收集与 navigable 无关的数据。 我们仍然需要检索 navigable 以对照 collector 配置进行检查,但这里仍可接受 null。

  4. top-level navigablenavigable顶级 traversable

  5. collectors 为空列表。

  6. 对于 活动 BiDi 会话中的每个 session

    1. 对于 sessionnetwork collectors 中的每个 collector

      1. 如果 collectordata types 包含 data type,且以 collectortop-level navigable 调用匹配 navigable 的 collector所得的结果为 true:

        1. collector 追加collectors

  7. 如果 collectors

    1. collected network data移除 collected data

    2. 用 "network data collected" 和 (requestrequest id, data type) 恢复

    3. 返回。

  8. bytes 为 null。

  9. 令给定 nullOrBytesprocessBody 为此步骤:

    1. 如果 nullOrBytes 不是 null:

      1. bytes 设置为用 nullOrBytes 调用序列化协议 bytes所得的结果。

      2. 如果 size 为 null,则将 size 设置为 bytes长度

  10. processBodyError 为此步骤:不执行任何操作。

  11. 给定 processBodyprocessBodyError完全读取 collected datacloned body

  12. 如果 bytes 不是 null:

    1. 对于 collectors 中的每个 collector

      1. 如果 size 小于或等于 collectormax encoded item size, 则将 collectorcollector 追加collected datacollectors

    2. 如果 collected datacollectors 不是

      1. 给定 size 分配大小以记录数据

      2. collected databytes 设置为 bytes

      3. collected datasize 设置为 size

    3. 否则,从 collected network data移除 collected data

  13. 用 "network data collected" 和 (requestrequest id, data type) 恢复

要在给定 size 的情况下分配 大小以记录数据
  1. available sizemax total collected size

  2. already collected data 为空列表。

  3. 对于 collected network data 中的每个 collected data

    1. 如果 collected databytes 不是 null:

      1. available size 减少 collected datasize

      2. collected data 追加already collected data

  4. 如果 size 大于 available size

    1. 对于 already collected data 中的每个 collected data

      1. available size 增加 collected datasize

      2. collected databytes 字段 设置为 null。

      3. collected datasize 字段设置为 null。

      4. 如果 available size 大于或等于 size,则返回。

要在给定 collected datacollector id 的情况下从数据中移除 collector
  1. 如果 collected datacollectors 包含 collector id

    1. collected datacollectors移除 collector id

    2. 如果 collected datacollectors

      1. collected network data移除 collected data

7.5.3. 网络拦截

网络拦截 是一种允许远程端拦截 并修改网络请求和响应的机制。

一个 BiDi 会话具有一个 拦截映射,它是 拦截 ID 与具有 url patternsphasescontexts 字段的结构体之间的映射, 这些字段定义活动网络拦截的属性。其初始为空。

一个 BiDi 会话具有一个 已阻塞请求 映射,用于跟踪 正在被主动阻塞的请求。它是请求 ID 与具有 requestphaseresponse 字段的结构体 之间的映射。其初始为空。

要在给定 sessioneventrequestnavigable id 的情况下,获取 网络拦截

  1. session interceptssession拦截映射

  2. intercepts 为空列表。

  3. 运行第一个匹配条件下的步骤:

    event 为 "network.beforeRequestSent"
    phase 设为 "beforeRequestSent"。
    event 为 "network.responseStarted"
    phase 设为 "responseStarted"。
    event 为 "network.authRequired"
    phase 设为 "authRequired"。
    event 为 "network.responseCompleted"
    返回 intercepts
  4. url 为使用 requestURL 运行URL 序列化器的结果。

  5. 对于 session intercepts 中的每个 intercept idintercept

    1. 如果 interceptcontexts 不为 null:

      1. 如果 interceptcontexts包含 navigable id

        1. 继续。

    2. 如果 interceptphases 包含 phase

      1. url patternsintercepturl patterns

      2. 如果 url patterns

        1. intercept id 追加intercepts

        2. 继续。

      3. 对于 url patterns 中的每个 url pattern

        1. 如果使用 url patternurl 匹配 URL 模式

          1. intercept id 追加intercepts

          2. 中断。

  6. 返回 intercepts

要在给定 sessioncommandcommand parameters 的情况下,更新 响应
  1. blocked requestssession已阻塞请求映射

  2. request idcommand parameters["request"]。

  3. 如果 blocked requests包含 request id,则返回带有错误 码 无此请求错误

  4. 令 (request, phase, response) 为 blocked requests[request id]。

  5. 如果 phase 为 "beforeRequestSent" 且 command 为 "continueResponse",则返回带有错误码 "invalid argument" 的错误

    TODO:考虑使用不同的错误

  6. 如果 response 为 null:

    1. 断言:phase 为 "beforeRequestSent"。

    2. response 设为新的响应

  7. 如果 command parameters 包含 "statusCode":

    1. responses状态设为 command parameters["statusCode"]。

  8. 如果 command parameters 包含 "reasonPhrase":

    1. responses状态消息设为使用 command parameters["reasonPhrase"] UTF-8 编码的结果。

  9. 如果 command parameters 包含 "headers":

    1. headers尝试使用 command parameters["headers"] 创建标头列表的结果。

    2. response标头列表设为 headers

  10. 如果 command parameters 包含 "cookies":

    1. 如果 command parameters 包含 "headers",则令 headersresponse标头列表

      否则:

      1. headers 为空标头列表

      2. 对于 response标头列表中的每个 header

        1. nameheader 的 name。

        2. 如果 name字节小写不是 `set-cookie`:

          1. header 追加到 headers

    2. 对于 command parameters["cookies"] 中的每个 cookie

      1. header value 为使用 cookie 序列化 set-cookie 标头的结果。

      2. 将 (`Set-Cookie`, header value) 追加到 headers

      3. response标头列表设为 headers

  11. 如果 command parameters 包含 "credentials":

    这没有 取消身份验证的方式。

    1. credentialscommand parameters["credentials"]。

    2. 断言:credentials["type"] 为 "password"。

    3. response 的身份验证凭据设为 (credentials["username"], credentials["password"])

  12. 返回 response

7.5.4. 类型

7.5.4.1. network.AuthChallenge 类型
network.AuthChallenge = {
  scheme: text,
  realm: text,
}

要在给定 response 的情况下提取 challenges

是否应包含 realm 之外的参数?

  1. 如果 responsestatus 为 401,则令 header name 为 `WWW-Authenticate`。否则,如果 responsestatus 为 407,则令 header name 为 `Proxy-Authenticate`。否则返回 null。

  2. challenges 为一个新的列表

  3. 对于 responseheader list中的每个 (name, value):

    与 Fetch 中一样, 尚不清楚这是否是处理多个 headers、解析问题等的正确方式。

    1. 如果 nameheader name 按字节大小写不敏感匹配:

      1. header challenges 为将 value 解析为 challenges 列表的结果,每个 challenge 由一个 scheme 和一个参数列表组成, 每个参数均为元组 (name, value),按照 [RFC9110] 的规则解析。

      2. 对于 header challenges 中的每个 header challenge

        1. schemeheader challenge 的 scheme。

        2. realm 为空字符串。

        3. 对于 header challenge 的 parameters 中的每个 (param name, param value):

          1. 如果 param name 等于 `realm`,则令 realm 为 对 param value 进行UTF-8 decode所得的结果。

        4. challenge 为一个新的映射,匹配 network.AuthChallenge 产生式,其中 scheme 字段设置为 scheme,且 realm 字段设置为 realm

      3. challenge 追加challenges

  4. 返回 challenges

7.5.4.2. network.AuthCredentials 类型
network.AuthCredentials = {
  type: "password",
  username: text,
  password: text,
}

network.AuthCredentials 类型表示对授权凭据请求的响应。

7.5.4.3. network.BaseParameters 类型
network.BaseParameters = (
    context: browsingContext.BrowsingContext / null,
    isBlocked: bool,
    navigation: browsingContext.Navigation / null,
    redirectCount: js-uint,
    request: network.RequestData,
    timestamp: js-uint,
    ? userContext: browser.UserContext / null,
    ? intercepts: [+network.Intercept]
)

network.BaseParameters 类型是一个抽象类型,表示 所有网络事件共有的数据。

考虑除 context 之外, 还包含发起请求的 document 节点的 `sharedId`。

要在给定 sessioneventrequest 的情况下处理 network event
  1. request data 为以 request 调用获取 request data所得的结果。

  2. navigationrequestnavigation id

  3. navigable id 为 null。

  4. top-level navigable id 为 null。

  5. user context id 为 null。

  6. 如果 requestclient 是一个环境设置对象

    1. environment settingsrequestclient

    2. 如果存在一个navigable,其活动 windowenvironment settings全局对象,则将 navigable id 设置为该 navigable 的navigable id,将 top-level navigable id 设置为 该 navigable 的顶级 traversablenavigable id,并 将 user context id 设置为该 navigable 的 关联用户上下文用户上下文 id

  7. intercepts 为以 sessioneventrequesttop-level navigable id 调用获取网络 拦截所得的结果。

  8. redirect countrequestredirect count

  9. timestamp 为一个时间值,表示 UTC 中的当前日期 和时间。

  10. 如果 intercepts 不是,则令 is blocked 为 true,否则 令 is blocked 为 false。

  11. params映射, 匹配 network.BaseParameters 产生式,其中 request 字段设置为 request datanavigation 字段设置为 navigationcontext 字段设置为 navigable iduserContext 字段设置为 user context idtimestamp 字段设置为 timestampredirectCount 字段设置为 redirect countisBlocked 字段设置为 is blocked,且如果 is blocked 为 true, 则 intercepts 字段设置为 intercepts,否则省略。

  12. 返回 params

7.5.4.4. network.BytesValue 类型
network.BytesValue = network.StringValue / network.Base64Value;

network.StringValue = {
  type: "string",
  value: text,
}

network.Base64Value = {
  type: "base64",
  value: text,
}

network.BytesValue 类型表示通过网络发送的二进制数据。有效的 UTF-8 用 network.StringValue 类型表示,任何其他数据均以 Base64 编码形式表示为 network.Base64Value

要在给定 protocol bytes 的情况下反序列化 协议 bytes

注:这接收编码为 network.BytesValue 的 bytes,并返回 字节序列

  1. 如果 protocol bytes 匹配 network.StringValue 产生式, 则令 bytes 为对 protocol bytes["value"] 进行 UTF-8 encode所得的结果。

  2. 否则,如果 protocol bytes 匹配 network.Base64Value 产生式。令 bytes 为对 protocol bytes["value"] 进行forgiving-base64 decode所得的结果。

  3. 返回 bytes

要在给定 bytes 的情况下,序列化 协议字节

注:这会接受一个字节序列 并返回一个 network.BytesValue

  1. text 为对 bytes 执行无 BOM 的 UTF-8 解码或失败的结果。

  2. 如果 text 为 failure,则返回一个匹配 network.Base64Value 产生式的映射, 其中 value 设为对 bytes 执行宽容 base64 编码的结果。

  3. 返回一个匹配 network.StringValue 产生式的映射, 其中 value 设为 text

7.5.4.5. network.Collector 类型

远程端定义本地端定义

network.Collector = text

network.Collector 类型表示一个collector 的 ID。

7.5.4.6. network.CollectorType 类型

远程端定义本地端定义

network.CollectorType = "blob"

注:将来我们可能还会支持 "stream" collector 类型,供希望通过流读取给定 collector 所收集数据的客户端使用。

network.CollectorType 类型表示可添加的数据 collector 的不同类型。

远程端定义本地端定义

network.SameSite = "strict" / "lax" / "none" / "default"


network.Cookie = {
    name: text,
    value: network.BytesValue,
    domain: text,
    path: text,
    size: js-uint,
    httpOnly: bool,
    secure: bool,
    sameSite: network.SameSite,
    ? expiry: js-uint,
    Extensible,
}

network.Cookie 类型表示一个 cookie。

要在给定 stored cookie 的情况下序列化 cookie
  1. name 为使用 stored cookie 的 name 字段进行UTF-8 解码的结果。

  2. value 为使用 stored cookie 的 value 对序列化协议字节的结果。

  3. domainstored cookie 的 domain 字段。

  4. pathstored cookie 的 path 字段。

  5. 如果已设置,则令 expirystored cookie 的 expiry-time 字段表示为 unix 时间戳;否则为 null。

  6. size 为将 stored cookie 序列化为它在 Cookie 标头中表示时所得结果的字节长度。

  7. 如果 stored cookie 的 http-only-flag 为 true,则令 http only 为 true,否则为 false。

  8. 如果 stored cookie 的 secure-only-flag 为 true,则令 secure 为 true,否则为 false。

  9. 如果 stored cookie 的 same-site-flag 为 "None",则令 same site 为 "none";如果为 "Lax",则为 "lax"; 如果为 "Strict",则为 "strict";如果为 "Default",则为 "default"

  10. 返回一个匹配 network.Cookie 产生式的映射, 其中 name 字段设为 namevalue 字段 设为 valuedomain 字段设为 domainpath 字段设为 path,如果 expiry 字段不为 null 则设为 expiry,否则省略;size 字段 设为 sizehttpOnly 字段设为 http onlysecure 字段设为 secure,且 sameSite 字段设为 same site

7.5.4.8. network.CookieHeader 类型

远程端定义

network.CookieHeader = {
    name: text,
    value: network.BytesValue,
}

network.CookieHeader 类型表示 Cookie 请求标头中的 cookie 数据子集。

要在给定 protocol cookie 的情况下序列化 cookie 标头
  1. name 为对 protocol cookie["name"] 进行UTF-8 编码的结果。

  2. value 为使用 protocol cookie["value"] 反序列化协议字节的结果。

  3. header value 为通过连接 name、 `=` 和 value 形成的字节 序列

  4. 返回 header value

7.5.4.9. network.DataType 类型

远程端定义本地端定义

network.DataType = "request" / "response"

network.DataType 类型表示可以收集的网络数据的不同类型。

7.5.4.10. network.FetchTimingInfo 类型

远程端定义本地端定义

network.FetchTimingInfo = {
    timeOrigin: float,
    requestTime: float,
    redirectStart: float,
    redirectEnd: float,
    fetchStart: float,
    dnsStart: float,
    dnsEnd: float,
    connectStart: float,
    connectEnd: float,
    tlsStart: float,

    requestStart: float,
    responseStart: float,

    responseEnd: float,
}

network.FetchTimingInfo 类型表示请求各部分相对于该请求客户端时间原点的时间。

要在给定 request 的情况下,获取 fetch 计时
  1. globalrequest客户端

  2. 如果 global 为 null,则返回一个匹配 network.FetchTimingInfo 产生式的映射,其中所有字段都设为 0。

  3. time origin 为使用 global 获取时间原点时间戳的结果。

  4. timingsrequestfetch 计时信息

  5. 如果 timings最终连接计时信息不为 null,则令 connection timing 为它;否则为一个新的连接计时信息

  6. request time 为给定 timings开始时间global 转换 fetch 时间戳的结果。

  7. redirect start 为给定 timings重定向开始时间global 转换 fetch 时间戳的结果。

  8. redirect end 为给定 timings重定向结束时间global 转换 fetch 时间戳的结果。

  9. fetch start 为给定 timings重定向后开始时间global 转换 fetch 时间戳的结果。

  10. DNS start 为给定 connection timing域名查找开始时间global 转换 fetch 时间戳的结果。

  11. DNS end 为给定 connection timing域名查找结束时间global 转换 fetch 时间戳的结果。

  12. TLS start 为给定 connection timing安全连接开始 时间global 转换 fetch 时间戳的结果。

  13. connect start 为给定 connection timing连接开始时间global 转换 fetch 时间戳的结果。

  14. connect end 为给定 connection timing连接结束时间global 转换 fetch 时间戳的结果。

  15. request start 为给定 timings最终网络请求开始 时间global 转换 fetch 时间戳的结果。

  16. response start 为给定 timings最终网络响应 开始时间global 转换 fetch 时间戳的结果。

  17. response end 为给定 timings结束时间global 转换 fetch 时间戳的结果。

  18. 返回一个匹配 network.FetchTimingInfo 产生式的映射, 其中 timeOrigin 字段设为 time originrequestTime 字段设为 request timeredirectStart 字段设为 redirect startredirectEnd 字段设为 redirect endfetchStart 字段设为 fetch startdnsStart 字段设为 DNS startdnsEnd 字段设为 DNS endconnectStart 字段设为 connect startconnectEnd 字段设为 connect endtlsStart 字段设为 TLS startrequestStart 字段设为 request startresponseStart 字段设为 response start,且 responseEnd 字段设为 response end

TODO:添加 service worker 字段

7.5.4.11. network.Header 类型

远程端定义本地端定义

network.Header = {
  name: text,
  value: network.BytesValue,
}

network.Header 类型表示单个请求标头。

要在给定 name bytesvalue bytes 的情况下序列化标头
  1. name 为使用 name bytes 进行UTF-8 解码的结果。

    断言:由于标头名称被约束为仅 ASCII,因此这不会失败。

  2. value 为使用 value bytes 序列化协议字节的结果。

  3. 返回一个匹配 network.Header 产生式的映射,其中 name 字段设为 name,且 value 字段 设为 value

要在给定 protocol header 的情况下反序列化 标头
  1. name 为对 protocol header["name"] 进行UTF-8 编码的结果。

  2. value 为使用 protocol header["value"] 反序列化协议字节的结果。

  3. 返回一个标头 (name, value)。

要在给定 protocol headers 的情况下,创建标头 列表
  1. headers 为空标头列表

  2. 对于 protocol headers 中的每个 header

    1. deserialized header 为使用 header 反序列化标头的结果。

    2. 如果 deserialized header 的 name 不匹配field-name token 产生式,则返回带有 错误码 "invalid argument" 的错误

    3. 如果 deserialized header 的 value 不匹配标头 值 产生式,则返回带有 错误码 "invalid argument" 的错误

    4. deserialized header 追加到 headers

  3. 返回带有数据 headers成功

7.5.4.12. network.Initiator 类型

远程端定义本地端定义

network.Initiator = {
    ? columnNumber: js-uint,
    ? lineNumber: js-uint,
    ? request: network.Request,
    ? stackTrace: script.StackTrace,
    ? type: "parser" / "script" / "preflight" / "other"
}

network.Initiator 类型表示网络请求的来源。

注:type 字段被包含在 定义中是为了向后 兼容,但不再由获取 initiator步骤设置,并且将在本规范的未来修订中移除。预期其用途会被 network.RequestData 上的 initiatorTypedestination 替代。

注:request 字段被包含在 定义中是为了向后 兼容,但不再由获取 initiator步骤设置,并且将在本规范的未来修订中移除。 network.Initiator 被包含在 network.BeforeRequestSentParameters 中,而后者也包含相同的 请求 ID,使得此信息成为冗余。参见 § 7.5.4.3 network.BaseParameters 类型

要在给定 request 的情况下获取 initiator
  1. 如果 requestinitiator type 为 "fetch" 或 "xmlhttprequest":

    1. stack trace当前堆栈跟踪

    2. 如果 stack trace 的大小为 1 或更大,则令 line numberstack trace[0] 中 lineNumber 字段的值,并令 column numberstack trace[0] 中 columnNumber 字段的值。否则 令 line numbercolumn number 为 0。

    否则,令 stack tracecolumn numberline number 全部为 null。

    TODO:Chrome 会将当前解析器位置作为解析器插入资源的 column number / line number 包含进去。

  2. 返回一个匹配 network.Initiator 产生式的映射, 如果 columnNumber 字段不为 null,则设为 column number, 否则省略;如果 lineNumber 字段不为 null,则设为 line number, 否则省略;且如果 stackTrace 字段不为 null,则设为 stack trace,否则省略。

7.5.4.13. network.Intercept 类型

远程端定义本地端定义

network.Intercept = text

network.Intercept 类型表示一个网络拦截的 ID。

7.5.4.14. network.Request 类型

远程端定义本地端定义

network.Request = text;

每个网络请求都有一个关联的请求 ID,它是唯一标识该请求的字符串。由重定向产生的请求的标识符与发起它的请求相匹配。

7.5.4.15. network.RequestData 类型

远程端定义本地端定义

network.RequestData = {
    request: network.Request,
    url: text,
    method: text,
    headers: [*network.Header],
    cookies: [*network.Cookie],
    headersSize: js-uint,
    bodySize: js-uint / null,
    destination: text,
    initiatorType: text / null,
    timings: network.FetchTimingInfo,
}

network.RequestData 类型表示正在进行的网络请求。

要在给定 request 的情况下获取请求 数据

  1. request id 为 request 的请求 ID

  2. url 为使用 requestURL 运行URL 序列化器的结果。

  3. methodrequest方法

  4. body size 为 null。

  5. body 为 request 的主体

  6. 如果 body字节 序列,则将 body size 设为该序列的长度。 否则,如果 body主体,则将 body size 设为该主体的长度

  7. headers sizerequest标头列表按照 [HTTP11] 要求序列化时的字节大小。

    注:对于允许标头压缩的协议, 这是通过网络发送的标头的压缩 大小。

  8. headers 为空列表。

  9. cookies 为空列表。

  10. 对于 request标头列表中的每个 (name, value):

    1. 将使用 namevalue 序列化标头的结果追加到 headers

    2. 如果 name 与 "Cookie" 是字节大小写不敏感匹配,则:

      1. 对于用户代理的cookie 存储中包含在 request 中的每个 cookie

        注:[COOKIES] 定义了一些关于存储中的哪些 cookie 可被包含在请求中的基线要求,但用户代理可以自由地施加额外约束。

        1. 将给定 cookie 序列化 cookie的结果追加到 cookies

  11. destinationrequest目标

  12. initiator typerequestinitiator type

  13. timings 为使用 request 获取 fetch 计时的结果。

  14. 返回一个匹配 network.RequestData 产生式的映射,其中 request 字段设为 request idurl 字段 设为 urlmethod 字段设为 methodheaders 字段设为 headerscookies 字段设为 cookiesheadersSize 字段设为 headers sizebodySize 字段设为 body sizedestination 字段设为 destinationinitiatorType 字段设为 initiator type,且 timings 字段设为 timings

7.5.4.16. network.ResponseContent 类型

远程端定义本地端定义

network.ResponseContent = {
    size: js-uint
}

network.ResponseContent 类型表示对 网络请求的已解码响应。

要在给定 response 的情况下获取 响应内容信息
  1. 返回一个匹配 network.ResponseContent 产生式的新映射,其中 size 字段设为 response响应主体信息已解码大小

7.5.4.17. network.ResponseData 类型

远程端定义本地端定义

network.ResponseData = {
    url: text,
    protocol: text,
    status: js-uint,
    statusText: text,
    fromCache: bool,
    headers: [*network.Header],
    mimeType: text,
    bytesReceived: js-uint,
    headersSize: js-uint / null,
    bodySize: js-uint / null,
    content: network.ResponseContent,
    ?authChallenges: [*network.AuthChallenge],
}

network.ResponseData 类型表示对网络 请求的响应。

要在给定 response 的情况下获取 协议

  1. protocol 为空字符串。

  2. 如果 response最终连接计时 信息不为 null,则将 protocol 设为 response最终连接计时 信息ALPN 协商协议

  3. 如果 protocol 为空字符串,或等于 "unknown":

    1. protocol 设为 responseurl方案

    2. 如果 protocol 等于 "http" 或 "https",且 response 具有关联的 HTTP Response。

      注:[FETCH] 没有明确说明 HTTP 网络响应与 response 对象之间的关系。

      1. http version 为 HTTP Response 的 Status line 的 HTTP-version [HTTP11]

      2. 如果 http version 以 "HTTP/" 开头:

        1. versionhttp version 从 5 到 http version长度码元子串

        2. 如果 version 为 "0.9",则将 protocol 设为 "http/0.9";否则如果 version 为 "1.0", 则将 protocol 设为 "http/1.0";否则如果 version 为 "1.1",则将 protocol 设为 "http/1.1"。

  4. 返回 protocol

要在给定 response 的情况下,获取响应 数据
  1. url 为使用 responseURL 运行URL 序列化器的结果。

  2. protocol 设为给定 response 获取协议的结果。

  3. statusresponse状态

  4. status textresponse状态消息

  5. 如果 response缓存状态为 "local",则令 from cache 为 true,否则令其为 false。

  6. headers 为空列表。

  7. mime typeresponse计算出的 MIME 类型本质

    注:这是浏览器实际使用的任何 MIME 类型, 即使它没有遵循 [MIMESNIFF] 规范中的精确算法。

  8. 对于 response标头列表中的每个 (name, value):

    1. 将使用 namevalue 序列化标头的结果追加到 headers

  9. bytes received 为作为与 response 关联的 HTTP 响应的一部分传输的总字节数。

  10. headers size 为作为 HTTP 响应的标头 字段部分传输的字节数。

  11. body sizeresponse响应主体信息已编码大小

  12. content 为使用 response 获取 响应内容信息的结果。

  13. auth challenges 为使用 response 提取质询的结果。

  14. 返回一个匹配 network.ResponseData 产生式的映射, 其中 url 字段设为 urlprotocol 字段 设为 protocolstatus 字段设为 statusstatusText 字段设为 status textfromCache 字段设为 from cacheheaders 字段设为 headersmimeType 字段设为 mime typebytesReceived 字段设为 bytes receivedheadersSize 字段设为 headers sizebodySize 字段设为 body sizecontent 字段设为 content,且如果 authChallenges 字段不为 null,则设为 auth challenges,否则省略。

7.5.4.18. network.SetCookieHeader 类型

Remote end definition

network.SetCookieHeader = {
    name: text,
    value: network.BytesValue,
    ? domain: text,
    ? httpOnly: bool,
    ? expiry: text,
    ? maxAge: js-int,
    ? path: text,
    ? sameSite: network.SameSite,
    ? secure: bool,
}

network.SetCookieHeader 表示 Set-Cookie 响应 header 中的数据。

要在给定作为整数的 input 的情况下序列化 整数

注:这会生成 input 作为十进制数字字符串的最短表示。

  1. serialized 为空字符串。

  2. valueinput

  3. value 大于 0 时:

    1. xvalue 除以 10。

    2. most significant digitsx 的整数部分。

    3. ymost significant digits 乘以 10。

    4. least significant digitvalue - y

    5. 断言:least significant digit 是 0 到 9(含)范围内的整数。

    6. codepoint 为一个码 点,其为 U+0030 DIGIT ZERO 的 + least significant digit

    7. codepoint 前置到 serialized

    8. value 设置为 most significant digits

  4. 返回 serialized

给定 protocol cookie,要序列化 set-cookie 标头
  1. name 为对 protocol cookie["name"] 进行 UTF-8 编码的结果。

  2. value 为用 protocol cookie["value"] 反序列化协议字节的结果。

  3. header value 为通过连接 name、 `=` 和 value 形成的字节 序列

  4. 如果 protocol cookie 包含 "expiry":

    1. attribute 为 `;Expires=`

    2. protocol cookie["expiry"] 的 UTF-8 编码追加到 attribute

    3. attribute 追加到 header value

  5. 如果 protocol cookie 包含 "maxAge":

    1. attribute 为 `;Max-Age=`

    2. max age string 为对 protocol cookie["maxAge"] 序列化整数的结果。

    3. max age stringUTF-8 编码追加到 attribute

    4. attribute 追加到 header value

  6. 如果 protocol cookie 包含 "domain":

    1. attribute 为 `;Domain=`

    2. protocol cookie["domain"] 的 UTF-8 编码追加到 attribute

    3. attribute 追加到 header value

  7. 如果 protocol cookie 包含 "path":

    1. attribute 为 `;Path=`

    2. protocol cookie["path"] 的 UTF-8 编码追加到 attribute

    3. attribute 追加到 header value

  8. 如果 protocol cookie 包含 "secure" 且 protocol cookie["secure"] 为 true:

    1. 将 `;Secure` 追加到 header value

  9. 如果 protocol cookie 包含 "httpOnly" 且 protocol cookie["httpOnly"] 为 true:

    1. 将 `;HttpOnly` 追加到 header value

  10. 如果 protocol cookie 包含 "sameSite":

    1. attribute 为 `;SameSite=`

    2. protocol cookie["sameSite"] 的 UTF-8 编码追加到 attribute

    3. attribute 追加到 header value

  11. 返回 header value

7.5.4.19. network.UrlPattern 类型

Remote end definition

network.UrlPattern = (
  network.UrlPatternPattern /
  network.UrlPatternString
)

network.UrlPatternPattern = {
    type: "pattern",
    ?protocol: text,
    ?hostname: text,
    ?port: text,
    ?pathname: text,
    ?search: text,
}


network.UrlPatternString = {
    type: "string",
    pattern: text,
}

network.UrlPattern 表示用于为网络 拦截匹配请求 URL 的模式。

当 URL 与 network.UrlPattern 匹配时,会解析该 URL, 并在模式中存在对应字段时,将每个组成部分与该字段按相等性进行比较。 模式中缺失的字段始终匹配。

注:此语法在设计时考虑了未来的可扩展性。 特别是,该语法禁止在 [URLPattern] 规范中被特殊处理的字符。这些字符可以通过在其前面加上 U+005C (\) 字符进行转义。

要在给定 pattern 的情况下反转义 URL 模式
  1. forbidden characters 为码点 «U+0028 ((), U+0029 ()), U+002A (*), U+007B ({), U+007D (})» 的集合

  2. result 为空字符串。

  3. is escaped character 为 false。

  4. 对于 pattern 中的每个 codepoint

    1. 如果 is escaped character 为 false:

      1. 如果 forbidden characters 包含 codepoint,则返回带有错误码 无效参数错误

      2. 如果 codepoint 为 U+005C (\):

        1. is escaped character 设为 true。

        2. 继续。

    2. codepoint 追加到 result。

    3. is escaped character 设为 false。

  5. 返回带有数据 result成功

给定 pattern,要解析 URL 模式
  1. has protocol 为 true。

  2. has hostname 为 true。

  3. has port 为 true。

  4. has pathname 为 true。

  5. has search 为 true。

  6. 如果 pattern 匹配 network.UrlPatternPattern 产生式:

    1. pattern url 为空字符串。

    2. 如果 pattern 包含 "protocol":

      1. 如果 pattern["protocol"] 是空字符串,则返回带有错误码 invalid argument错误

      2. protocol 为用 pattern["protocol"] 尝试反转义 URL Pattern的结果。

      3. 对于 protocol 中的每个 codepoint

        1. 如果 codepoint 不是 ASCII 字母数字,并且 «U+002B (+), U+002D (-), U+002E (.)» 不包含 codepoint

          1. 返回带有错误码 invalid argument 的错误

      4. protocol 追加到 pattern url

    3. 否则:

      1. has protocol 设置为 false。

      2. 将 "http" 追加到 pattern url

    4. scheme 为对 pattern url 进行 ASCII 小写化的结果。

    5. 将 ":" 追加到 pattern url

    6. 如果 scheme 是 特殊的,则将 "//" 追加到 pattern url

    7. 如果 pattern 包含 "hostname":

      1. 如果 pattern["hostname"] 是空字符串,则返回带有错误码 invalid argument错误

      2. 如果 scheme 是 "file",则返回带有错误码 invalid argument错误

      3. hostname 为用 pattern["hostname"] 尝试反转义 URL Pattern的结果。

      4. inside brackets 为 false。

      5. 对于 hostname 中的每个 codepoint

        1. 如果 «U+002F (/), U+003F (?), U+0023 (#)» 包含 codepoint

          1. 返回带有错误码 invalid argument错误

        2. 如果 inside brackets 为 false 且 codepoint 是 U+003A (:):

          1. 返回带有错误码 invalid argument错误

        3. 如果 codepoint 是 U+005B ([),则将 inside brackets 设置为 true。

        4. 如果 codepoint 是 U+005D (]),则将 inside brackets 设置为 false。

      6. hostname 追加到 pattern url

    8. 否则:

      1. 如果 scheme 不是 "file",则将 "placeholder" 追加到 pattern url

      2. has hostname 设置为 false。

    9. 如果 pattern 包含 "port":

      1. 如果 pattern["port"] 是空字符串,则返回带有错误码 invalid argument错误

      2. port 为用 pattern["port"] 尝试反转义 URL Pattern的结果。

      3. 将 ":" 追加到 pattern url

      4. 对于 port 中的每个 codepoint

        1. 如果 codepoint 不是ASCII 数字

          1. 返回带有错误码 invalid argument错误

      5. port 追加到 pattern url

    10. 否则:

      1. has port 设置为 false。

    11. 如果 pattern 包含 "pathname":

      1. pathname 为用 pattern["pathname"] 尝试反转义 URL Pattern的结果。

      2. 如果 pathname 不以 U+002F (/) 开始,则 将 "/" 追加到 pattern url

      3. 对于 pathname 中的每个 codepoint

        1. 如果 «U+003F (?), U+0023 (#)» 包含 codepoint

          1. 返回带有错误码 invalid argument错误

      4. pathname 追加到 pattern url

    12. 否则:

      1. has pathname 设置为 false。

    13. 如果 pattern 包含 "search":

      1. search 为用 pattern["search"] 尝试反转义 URL pattern的结果。

      2. 如果 search 不以 U+003F (?) 开始,则 将 "?" 追加到 pattern url

      3. 对于 search 中的每个 codepoint

        1. 如果 codepoint 是 U+0023 (#):

          1. 返回带有错误码 invalid argument错误

      4. search 追加到 pattern url

    14. 否则:

      1. has search 设置为 false。

  7. 否则,如果 pattern 匹配 network.UrlPatternString 产生式:

    1. pattern url 为用 pattern["pattern"] 尝试反转义 URL pattern的结果。

  8. url 为对 pattern url 进行解析的结果。

  9. 如果 url 为 failure,则返回带有错误码 invalid argument错误

  10. parsed 为具有以下字段的结构:

    protocol
    如果 has protocol 为 true,则为 urlscheme;否则为 null。
    hostname
    如果 has hostname 为 true,则为 urlhost;否则为 null。
    port
    1. 如果 has port 为 false:

      1. null。

    2. 否则:

      1. 如果 urlscheme是特殊的,且 urlscheme默认端口不为 null,并且 urlport 为 null 或 等于 scheme默认端口

        1. 空字符串。

      2. 否则,如果 urlport 不为 null:

        1. urlport序列化整数

      3. 否则:

        1. null。

    pathname
    1. 如果 has pathname 为 false:

      1. null。

    2. 否则:

      1. 如果 urlpath不是空字符串且 不是, 则为用 url 运行 URL path serializer 的结果; 否则为 null。

    search
    1. 如果 has search 为 false:

      1. null。

    2. 否则:

      1. 如果 urlquery 为 null,则为空字符串;否则为 urlquery

  11. 返回带有数据 parsed成功

要在给定 url patternurl string 的情况下匹配 URL 模式
  1. url解析 url string的结果。

  2. 如果 url pattern 的 protocol 不为 null 且不等于 urlscheme,则返回 false。

  3. 如果 url pattern 的 hostname 不为 null 且不等于 urlhost,则返回 false。

  4. 如果 url pattern 的 port 不为 null:

    1. port 为 null。

    2. 如果 urlscheme为 特殊,且 urlscheme默认 端口不为 null,且 urlport 为 null 或等于scheme默认 端口

      1. port 设为空字符串。

    3. 否则,如果 urlport不为 null:

      1. port 设为使用 urlport 序列化整数的结果。

    4. 如果 url pattern 的 port 不等于 port,则返回 false。

  5. 如果 url pattern 的 pathname 不为 null,且不等于 使用 url 运行URL 路径序列化器的结果,则返回 false。

  6. 如果 url pattern 的 search 不为 null:

    1. url queryurlquery

    2. 如果 url query 为 null,则将 url query 设为空字符串。

    3. 如果 url pattern 的 search 不等于 url query,则返回 false。

  7. 返回 true。

7.5.5. 命令

7.5.5.1. network.addDataCollector 命令

network.addDataCollector 会添加一个 collector

命令类型
network.AddDataCollector = (
  method: "network.addDataCollector",
  params: network.AddDataCollectorParameters
)

network.AddDataCollectorParameters = {
  dataTypes: [+network.DataType],
  maxEncodedDataSize: js-uint,
  ? collectorType: network.CollectorType .default "blob",
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}
返回类型
network.AddDataCollectorResult = {
  collector: network.Collector
}
给定 sessioncommand parameters远程端步骤如下:
  1. collector id 为一个 UUID 的字符串表示。

  2. input context ids 为空集合

  3. 如果 command parameterscontexts 字段存在, 则将 input context ids 设为用 command parameters[contexts] 创建集合的结果。

  4. data types 为用 command parameters["dataTypes"] 创建集合的结果。

  5. max encoded item sizecommand parameters ["maxEncodedDataSize"]。

    注:maxEncodedDataSize 参数表示 最大编码项大小,并限制 给定 collector 收集的每个请求的大小, 而不是该 collector 收集的总大小。

    注:不同实现可能 支持不同的编码,这意味着 编码后的大小在不同浏览器之间可能不同。因此,对于相同的数据 collector 配置,某些网络数据可能只在部分实现中符合最大编码项大小

  6. collector typecommand parameters ["collectorType"]。

  7. input user context ids 为空集合

  8. 如果 command parametersuserContexts 字段存在, 则将 input user context ids 设为用 command parameters[userContexts] 创建集合的结果。

  9. 如果 input user context ids 不为空且 input context ids 不为 空,则返回带有错误 码 无效参数错误

  10. 如果 max encoded item size 为 0,或 max encoded item size 大于 最大总收集大小,则返回带有错误 码 无效参数错误

  11. 如果 input context ids为空

    1. navigables尝试使用 input context ids 通过 ID 获取有效可导航的结果。

    2. 对于 navigables 中的每个 navigable

      1. 如果 navigable 不是顶级可遍历,则返回带有错误码 无效参数错误

  12. 否则,如果 input user context ids为空

    1. 对于 input user context ids 中的每个 user context id 执行

      1. user context 为使用 user context id 获取用户上下文的结果。

      2. 如果 user context 为 null,则返回带有错误码 无此用户上下文错误

  13. collector 为一个collector,其 最大编码项大小字段设为 max encoded item sizedata types 字段设为 data typescollector 字段设为 collector idcollector type 字段设为 collector typecontexts 字段设为 input context idsuser contexts 字段设为 input user context ids

  14. sessionnetwork collectors[collector id] 设为 collector

  15. 返回一个匹配 network.AddDataCollectorResult 产生式的新映射,其中 collector 字段设为 collector id

7.5.5.2. network.addIntercept 命令

network.addIntercept 命令会添加一个 网络拦截

命令类型
network.AddIntercept = (
  method: "network.addIntercept",
  params: network.AddInterceptParameters
)

network.AddInterceptParameters = {
  phases: [+network.InterceptPhase],
  ? contexts: [+browsingContext.BrowsingContext],
  ? urlPatterns: [*network.UrlPattern],
}

network.InterceptPhase = "beforeRequestSent" / "responseStarted" /
                         "authRequired"
返回类型
network.AddInterceptResult = {
  intercept: network.Intercept
}
给定 sessioncommand parameters远程端步骤如下:
  1. intercept 为一个 UUID 的字符串表示。

  2. 如果存在,则令 url patternscommand parametersurlPatterns 字段,否则为空列表

  3. navigables 为 null。

  4. 如果 command parameterscontexts 字段存在:

    1. navigables 设为空集合

    2. 对于 command parameters["contexts"] 中的每个 navigable id

      1. navigable尝试使用 navigable id 获取可导航的结果。

      2. 如果 navigable 不是顶级可遍历,则返回带有错误码 无效参数错误

      3. navigable 追加到 navigables

    3. 如果 navigables 是空集合,则返回带有 错误码 无效参数错误

  5. intercept mapsession拦截映射

  6. parsed patterns 为空列表

  7. 对于 url patterns 中的每个 url pattern

    1. parsed尝试使用 url pattern 解析 url 模式的结果。

    2. parsed 追加parsed patterns

  8. intercept map[intercept] 设为一个结构体,其中 url patternsparsed patternsphasescommand parameters["phases"],且 browsingContextsnavigables

  9. 返回一个匹配 network.AddInterceptResult 产生式的新映射,其中 intercept 字段设为 intercept

7.5.5.3. network.continueRequest 命令

network.continueRequest 命令继续执行 被网络拦截阻塞的请求。

命令类型
network.ContinueRequest = (
  method: "network.continueRequest",
  params: network.ContinueRequestParameters
)

network.ContinueRequestParameters = {
  request: network.Request,
  ?body: network.BytesValue,
  ?cookies: [*network.CookieHeader],
  ?headers: [*network.Header],
  ?method: text,
  ?url: text,
}
返回类型
network.ContinueRequestResult = EmptyResult
给定 sessioncommand parameters远端步骤如下:
  1. blocked requestssession阻塞请求映射

  2. request idcommand parameters["request"]。

  3. 如果 blocked requests包含 request id,则返回带有错误 码 no such request错误

  4. 令 (request, phase, response) 为 blocked requests[request id]。

  5. 如果 phase 不是 "beforeRequestSent",则返回带有错误码 invalid argument错误

    考虑使用 "request already sent" 错误。

  6. 如果 command parameters 包含 "url":

    1. url record 为将 URL parser 应用于 command parameters["url"] 且基 URL 为 null 的结果。

    2. 如果 url record 为 failure,则返回带有 错误码 invalid argument错误

      TODO:这里也应当恢复吗?

    3. requesturlurl record

  7. 如果 command parameters 包含 "method":

    1. methodcommand parameters["method"]。

    2. 如果 method 不匹配方法令牌产生式,则返回带有 错误码 "invalid argument" 的错误

    3. requestmethodmethod

  8. 如果 command parameters 包含 "headers":

    1. headers 为空标头列表

    2. 对于 command parameters["headers"] 中的 header

      1. deserialized header 为用 header 反序列化 标头的结果。

      2. 如果 deserialized header 的 name 不匹配field-name 令牌 产生式,则返回带有错误码 "invalid argument" 的错误

      3. 如果 deserialized header 的 value 不匹配标头值 产生式,则返回带有错误码 "invalid argument" 的错误

      4. deserialized header 追加到 headers

    3. request标头列表设置为 headers

  9. 如果 command parameters 包含 "cookies":

    1. cookie header 为空字节 序列

    2. 对于 command parameters["cookies"] 中的每个 cookie

      1. 如果 cookie header 不为空,则将 `;` 追加到 cookie header

      2. 将用 cookie 序列化 cookie 标头的结果追加到 cookie header

    3. found cookie header 为 false。

    4. 对于 request标头列表中的每个 header

      1. nameheader 的 name。

      2. 如果对 name 进行字节小写化的结果为 `cookie`:

        1. header 的 value 设置为 cookie header

        2. found cookie header 设置为 true。

        3. 中断。

    5. 如果 found cookie header 为 false:

      1. 标头(`Cookie`,cookie header)追加到 request标头列表

  10. 如果 command parameters 包含 "body":

    1. body 为用 command parameters["body"] 反序列化协议字节的结果。

    2. requestbody设置为 body

  11. 用 "continue request"、request id 和 (null, "incomplete") 恢复

  12. 返回带有数据 null 的成功

7.5.5.4. network.continueResponse 命令

network.continueResponse 命令继续执行 被网络拦截阻塞的响应。它可以在 responseStarted 阶段调用,用于修改该 响应的状态和标头,但仍提供网络响应主体。

命令类型
network.ContinueResponse = (
  method: "network.continueResponse",
  params: network.ContinueResponseParameters
)

network.ContinueResponseParameters = {
  request: network.Request,
  ?cookies: [*network.SetCookieHeader]
  ?credentials: network.AuthCredentials,
  ?headers: [*network.Header],
  ?reasonPhrase: text,
  ?statusCode: js-uint,
}
返回类型
network.ContinueResponseResult = EmptyResult
给定 sessioncommand parameters远程端步骤如下:
  1. request idcommand parameters["request"]。

  2. response尝试使用 session、"continueResponse" 和 command parameters 更新 响应的结果。

  3. 使用 "continue request"、request id 和 (response, "incomplete") 恢复

  4. 返回带有数据 null 的成功

7.5.5.5. network.continueWithAuth 命令

network.continueWithAuth 命令会继续一个在 authRequired 阶段被网络拦截阻塞的响应。

命令类型
network.ContinueWithAuth = (
  method: "network.continueWithAuth",
  params: network.ContinueWithAuthParameters
)

network.ContinueWithAuthParameters = {
  request: network.Request,
  (network.ContinueWithAuthCredentials // network.ContinueWithAuthNoCredentials)
}

network.ContinueWithAuthCredentials = (
  action: "provideCredentials", 
  credentials: network.AuthCredentials
)

network.ContinueWithAuthNoCredentials = (
  action: "default" / "cancel"
)
返回类型
network.ContinueWithAuthResult = EmptyResult
给定 sessioncommand parameters远程端步骤如下:
  1. blocked requestssession已阻塞请求映射

  2. request idcommand parameters["request"]。

  3. 如果 blocked requests包含 request id,则返回 带有错误 码 无此请求错误

  4. 令 (request, phase, response) 为 blocked requests[request id]。

  5. 如果 phase 不是 "authRequired",则返回带有错误码 无效参数错误

  6. 如果 command parameters "action" 为 "cancel",则将 response 的身份验证凭据设为 "cancelled"。

  7. 如果 command parameters "action" 为 "provideCredentials":

    1. credentialscommand parameters["credentials"]。

    2. 断言:credentials["type"] 为 "password"。

    3. response 的身份验证凭据设为 (credentials["username"], credentials["password"])

  8. 使用 "continue request"、request id 和 (response, "incomplete") 恢复

  9. 返回带有数据 null 的成功

7.5.5.6. network.disownData 命令

network.disownData 命令会释放给定collector 的 已收集网络数据。

命令类型
network.DisownData = (
  method: "network.disownData",
  params: network.DisownDataParameters
)

network.DisownDataParameters = {
  dataType: network.DataType,
  collector: network.Collector,
  request: network.Request,
}
返回类型
network.DisownDataResult = EmptyResult
给定 sessioncommand parameters远程端步骤如下:
  1. data typecommand parameters 中 "dataType" 字段的值。

  2. collector idcommand parameters 中 "collector" 字段的值。

  3. request idcommand parameters 中 "request" 字段的值。

  4. collectorssessionnetwork collectors

  5. 如果 collectors包含 collector id,则返回 带有错误 码 无此网络 collector错误

  6. collected data 为使用 request iddata type 获取已收集数据的结果。

  7. 如果 collected data 为 null,则返回带有错误码 无此网络 数据错误

  8. 使用 collected datacollector id 从数据中移除 collector

  9. 返回带有数据 null成功

7.5.5.7. network.failRequest 命令

network.failRequest 命令使被网络拦截阻塞的 fetch 失败。

命令类型
network.FailRequest = (
  method: "network.failRequest",
  params: network.FailRequestParameters
)

network.FailRequestParameters = {
  request: network.Request,
}
返回类型
network.FailRequestResult = EmptyResult
给定 sessioncommand parameters远程端步骤如下:
  1. blocked requestssession已阻塞请求映射

  2. request idcommand parameters["request"]。

  3. 如果 blocked requests包含 request id,则返回 带有错误 码 无此请求错误

  4. 令 (request, phase, response) 为 blocked requests[request id]。

  5. 如果 phase 为 "authRequired",则返回带有错误码 无效参数错误

  6. response 为新的网络错误

    允许设置 精确的错误类型 [Issue #508]

  7. 使用 "continue request"、request id 和 (response, "complete") 恢复

  8. 返回带有数据 null 的成功

7.5.5.8. network.getData 命令

network.getData 命令在网络数据可用时获取该数据。

命令类型
network.GetData = (
  method: "network.getData",
  params: network.GetDataParameters
)

network.GetDataParameters = {
  dataType: network.DataType,
  ? collector: network.Collector,
  ? disown: bool .default false,
  request: network.Request,
}
返回类型
network.GetDataResult = {
  bytes: network.BytesValue,
}
给定 sessioncommand parameters远程端步骤如下:
  1. data typecommand parameters["dataType"]。

  2. request idcommand parameters["request"]。

  3. collector id 为 null。

  4. 如果 command parameters 包含 "collector":

    1. collectorssessionnetwork collectors

    2. 如果 collectors包含 collector id,则返回 带有错误码 无此网络 collector错误

    3. collector id 设为 command parameters["collector"]。

  5. disowncommand parameters["disown"]。

  6. 如果 disown 为 true 且 collector id 为 null,则返回带有错误码 无效参数错误

  7. collected data 为给定 request iddata type 获取已收集数据的结果。

  8. 如果 collected data 为 null:

    1. 返回带有错误码 无此 网络数据错误

  9. 如果 collected datapending 为 true:

    1. 使用 "network data collected" 和 (request id, data type) 等待

  10. 如果 collector id 不为 null,且如果 collected datacollectors包含 collector id

    1. 返回带有错误码 无此 网络数据错误

  11. bytescollected databytes

  12. 如果 bytes 为 null,

    1. 返回带有错误码 不可用网络数据错误

  13. body 为一个匹配 network.GetDataResult 产生式的映射, 其中 bytes 字段设为 bytes

  14. 如果 disown 为 true,则使用 collected datacollector id 从数据中移除 collector

  15. 返回带有数据 body成功

7.5.5.9. network.provideResponse 命令

network.provideResponse 命令通过提供完整 响应,继续一个被网络拦截阻塞的请求。

注:这不会阻止该请求经历正常的请求 生命周期,因此在其推进过程中仍会发出其他事件。

命令类型
network.ProvideResponse = (
  method: "network.provideResponse",
  params: network.ProvideResponseParameters
)

network.ProvideResponseParameters = {
  request: network.Request,
  ?body: network.BytesValue,
  ?cookies: [*network.SetCookieHeader],
  ?headers: [*network.Header],
  ?reasonPhrase: text,
  ?statusCode: js-uint,
}
返回类型
network.ProvideResponseResult = EmptyResult
给定 sessioncommand parameters远程端步骤如下:
  1. request idcommand parameters["request"]。

  2. response尝试使用 session、"provideResponse" 和 command parameters 更新 响应的结果。

  3. 如果 command parameters 包含 "body":

    1. body 为使用 command parameters["body"] 反序列化协议字节的结果。

    2. response主体设为以 body 作为主体

  4. 使用 "continue request"、request id 和 (response,"complete") 恢复

  5. 返回带有数据 null 的成功

7.5.5.10. network.removeDataCollector 命令

network.removeDataCollector 命令会移除一个 collector

命令类型
network.RemoveDataCollector = (
  method: "network.removeDataCollector",
  params: network.RemoveDataCollectorParameters
)

network.RemoveDataCollectorParameters = {
  collector: network.Collector
}
返回类型
network.RemoveDataCollectorResult = EmptyResult
给定 sessioncommand parameters远程端步骤如下:
  1. collector idcommand parameters 中 "collector" 字段的值。

  2. collectorssessionnetwork collectors

  3. 如果 collectors包含 collector id,则返回 带有错误 码 无此网络 collector错误

  4. sessionnetwork collectors移除 collector id

  5. 对于已收集网络数据中的 collected data,使用 collected datacollector id 从数据中移除 collector

  6. 返回带有数据 null成功

7.5.5.11. network.removeIntercept 命令

network.removeIntercept 命令移除一个 网络拦截

命令类型
network.RemoveIntercept = (
  method: "network.removeIntercept",
  params: network.RemoveInterceptParameters
)

network.RemoveInterceptParameters = {
  intercept: network.Intercept
}
返回类型
network.RemoveInterceptResult = EmptyResult
给定 sessioncommand parameters远程端步骤如下:
  1. interceptcommand parameters 中 "intercept" 字段的值。

  2. intercept mapsession拦截映射

  3. 如果 intercept map包含 intercept,则返回 带有错误 码 无此拦截错误

  4. intercept map移除 intercept

注:移除拦截不会影响 已经被此拦截阻塞的请求。只有未来请求或现有 请求的未来阶段会受到影响。

  1. 返回带有数据 null成功

7.5.5.12. network.setCacheBehavior 命令

network.setCacheBehavior 命令配置 某些请求的网络缓存行为。

命令类型
network.SetCacheBehavior = (
  method: "network.setCacheBehavior",
  params: network.SetCacheBehaviorParameters
)

network.SetCacheBehaviorParameters = {
  cacheBehavior: "default" / "bypass",
  ? contexts: [+browsingContext.BrowsingContext]
}
返回类型
network.SetCacheBehaviorResult = EmptyResult
给定请求 requestWebDriver BiDi 缓存行为步骤如下:
  1. navigable 为 null。

  2. 如果 request客户端环境设置对象

    1. environment settingsrequest客户端

    2. 如果存在一个可导航,其活动窗口environment settings全局对象,则将 navigable 设为该可导航的顶级可遍历

  3. 如果 navigable 不为 null 且可导航 缓存行为映射包含 navigable,则返回可导航缓存行为 映射[navigable]。

  4. 返回默认缓存行为

给定 navigable可导航缓存 行为步骤如下:
  1. top-level navigablenavigable顶级可遍历

  2. 如果可导航缓存行为映射包含 top-level navigable,则返回 可导航缓存行为映射[top-level navigable]。

  3. 返回默认缓存行为

给定 sessioncommand parameters远程端步骤如下:
  1. behaviorcommand parameters["cacheBehavior"]。

  2. 如果 command parameters包含 "contexts":

    1. 默认缓存行为设为 behavior

    2. 清空可导航缓存行为映射

    3. 切换 behavior 的值:

      "bypass"
      执行实现定义的步骤,以禁用任何 实现特定的资源缓存。
      "default"
      执行实现定义的步骤,以启用 当前远程端配置中通常启用的任何 实现特定的资源缓存。
    4. 返回带有数据 null 的成功

  3. navigables 为空集合

  4. 对于 command parameters["contexts"] 中的每个 navigable id

    1. context尝试使用 navigable id 获取 可导航的结果。

    2. 如果 context 不是顶级浏览上下文,则返回带有错误码 无效参数错误

    3. context 追加navigables

  5. 对于 navigables 中的每个 navigable

    1. 如果可导航缓存行为映射包含 navigable,且 可导航缓存行为 映射[navigable] 等于 behavior,则 继续。

    2. 切换 behavior 的值:

      "bypass"
      执行实现定义的步骤,以禁用源自任何浏览 上下文(其中 navigable顶级浏览上下文)的网络请求的任何实现特定 资源缓存。
      "default"
      执行实现定义的步骤,以启用 当前远程端配置中通常为源自任何浏览上下文 (其中 navigable顶级浏览上下文)的网络请求启用的任何 实现特定资源缓存。
    3. 如果 behavior 等于默认缓存行为

      1. 如果可导航缓存行为映射 包含 navigable, 则移除可导航缓存行为 映射[navigable]。

    4. 否则:

      1. 可导航缓存行为 映射[navigable] 设为 behavior

  6. 返回带有数据 null 的成功

7.5.5.13. network.setExtraHeaders 命令

network.setExtraHeaders 命令允许 指定用于扩展或覆盖现有请求标头的标头。

命令类型
network.SetExtraHeaders = (
  method: "network.setExtraHeaders",
  params: network.SetExtraHeadersParameters
)

network.SetExtraHeadersParameters = {
  headers: [*network.Header]
  ? contexts: [+browsingContext.BrowsingContext]
  ? userContexts: [+browser.UserContext]
}
返回类型
network.SetExtraHeadersResult = EmptyResult
要在给定 requestheaders 的情况下,更新标头
  1. request headersrequest标头列表

  2. 对于 headers 中的每个 header

    1. request headers设置 header

      注:这始终会覆盖 现有值(如果有)。特别是,它不会 将 cookie 追加到现有的 `Set-Cookie` 标头。

要在给定 sessionrequestrelated navigables 的情况下,更新请求 标头
  1. 断言:related navigables大小为 0 或 1。

    注:这意味着它不适用于 与多个可导航关联的 worker。在这种情况下,不清楚应以何种顺序覆盖标头。

  2. 使用 requestsession额外 标头默认标头更新标头

  3. user context headerssession额外标头用户上下文标头

  4. 对于 related navigables 中的 navigable

    1. user contextnavigable关联 用户上下文

    2. 如果 user context headers 包含 user context, 则使用 requestuser context headers[user context] 更新 标头

  5. navigable headerssession额外标头可导航标头

  6. 对于 related navigables 中的 navigable

    1. top-level traversablenavigable顶级可遍历

    2. 如果 navigable headers 包含 top-level traversable, 则使用 requestnavigable headers[top-level traversable] 更新 标头

给定 sessioncommand parameters远端步骤如下:
  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 码 invalid argument错误

  2. headers 为用 command parameters["headers"] 尝试创建标头列表的结果。

  3. 如果 command parameters 包含 "userContexts":

    1. user contexts 为空列表

    2. 对于 command parameters["userContexts"] 中的 user context id

      1. user context 为用 user context id 获取用户上下文的结果。

      2. 如果 user context 为 null,则返回带有错误码 no such user context错误

      3. user context 追加user contexts

    3. targetsession额外标头用户上下文标头

    4. 对于 user contexts 中的 user context

      1. target[user context] 设置为 headers

    5. 返回带有数据 null 的成功

  4. 如果 command parameters 包含 "contexts":

    1. navigables 为用 command parameters["contexts"] 尝试 通过 ID 获取有效顶级 可遍历对象的结果。

    2. targetsession额外标头navigable 标头

    3. 对于 navigables 中的 navigable

      1. target[navigable] 设置为 headers

    4. 返回带有数据 null 的成功

  5. session额外标头默认标头设置为 headers

  6. 返回带有数据 null 的成功

7.5.6. 事件

7.5.6.1. network.authRequired 事件
事件类型
network.AuthRequired = (
  method: "network.authRequired",
  params: network.AuthRequiredParameters
)

network.AuthRequiredParameters = {
  network.BaseParameters,
  response: network.ResponseData
}

此事件会在用户代理即将提示输入授权 凭据时发出。

远程端事件触发器是给定请求 request响应 responseWebDriver BiDi auth required 步骤:
  1. redirect countrequest重定向计数

  2. 断言:请求发送前映射[request] 等于 redirect count

    注:这意味着每个调用方都需要 确保在这些步骤之前,已使用 request 调用WebDriver BiDi before request sent 步骤。

  3. 如果 request客户端不为 null,则令 related navigables 为使用 request获取相关可导航客户端的结果。否则,令 related navigables 为空 集合。

  4. 对于给定 "network.authRequired" 和 related navigables已启用事件的会话集合 中的每个 session

    1. params 为使用 session、 "network.authRequired" 和 request 处理 网络事件的结果。

    2. response data 为使用 response 获取响应 数据的结果。

    3. 断言:response data 包含 "authChallenge"。

    4. paramsresponse 字段设为 response data

    5. 断言:params 匹配 network.AuthRequiredParameters 产生式。

    6. body 为匹配 network.AuthRequired 产生式的映射,其中 params 字段设为 params

    7. 使用 sessionbody 发出 事件

    8. 如果 params["isBlocked"] 为 true:

      1. blocked requestssession已阻塞 请求映射

      2. request idrequest请求 ID

      3. blocked requests[request id] 设为 (request, "authRequired", response)。

      4. 使用 «"continue request"» 和 request id 等待

      5. 移除 blocked requests[request id]。

7.5.6.2. network.beforeRequestSent 事件
事件类型
network.BeforeRequestSent = (
  method: "network.beforeRequestSent",
  params: network.BeforeRequestSentParameters
 )

network.BeforeRequestSentParameters = {
  network.BaseParameters,
  ? initiator: network.Initiator,
}

此事件会在请求被发送之前发出(无论是通过网络发送,还是 在由 serviceworker 或本地缓存处理之前)。

给定 requestuser context 时,用于检查请求是否源自用户上下文的步骤为:
  1. settingsrequestclient

  2. related navigables 为以 settings 调用获取相关 navigables所得的结果。

  3. 对于 related navigables 中的 navigable

    1. 如果 navigable关联用户上下文user context,则返回 true。

  4. 返回 false。

在给定 related navigables 的情况下,获取模拟网络条件的步骤如下:
  1. 对于 related navigables 中的每个 navigable

    1. top-level traversablenavigable顶级可遍历

    2. user contexttop-level traversable关联 用户上下文

    3. 对于活动 BiDi 会话中的每个 session

      1. 如果 session模拟网络 条件可导航 网络条件 包含 top-level traversable, 则返回 session模拟网络 条件可导航 网络条件[top-level traversable]。

    4. 对于活动 BiDi 会话中的每个 session

      1. 如果 session模拟网络 条件用户 上下文网络条件 包含 user context,则返回 session模拟网络 条件用户 上下文网络条件[user context]。

    5. 对于活动 BiDi 会话中的每个 session

      1. 如果 session模拟网络 条件默认 网络条件不为 null, 则返回 session模拟网络 条件默认 网络条件

  2. 返回 null。

给定 环境设置对象 settingsWebDriver BiDi 网络离线步骤如下:
  1. navigablesettings相关全局对象关联 Document节点可导航

  2. emulated network conditions 为使用 [navigable] 获取模拟网络条件的结果。

  3. 如果 emulated network conditions 不为 null,且 emulated network conditionsoffline 为 true,则返回 true。

  4. 返回 false。

远程端事件触发器是给定请求 requestWebDriver BiDi before request sent 步骤:
  1. 对于用户上下文集合中的每个 user context

    1. 如果使用 requestuser context 运行请求源自用户 上下文步骤返回 true:

      1. 对于活动 BiDi 会话中的每个 session

        注:user context 至多只能在一个 用户 上下文到接受不安全证书覆盖映射中。

        1. 如果 session用户 上下文到接受不安全证书覆盖映射 包含 user context

          1. accept insecure certificatessession用户 上下文到接受不安全证书覆盖 映射[user context]。

          2. 如果 accept insecure certificates 为 true:

            1. 断言端点节点 支持接受不安全的 TLS 连接。

            2. 当为 request 运行基本证书 处理步骤时,跳过步骤 a,以及任何其他 实现定义的证书验证步骤。

          3. 否则,当为 request 运行基本证书处理 步骤时,执行所有步骤以及任何 实现定义的 证书验证步骤。

        注:user context 至多只能在一个 用户上下文到代理 配置映射中。

        1. 如果 session用户上下文 到代理配置映射 包含 user context

          1. proxy configurationsession用户 上下文到代理配置映射[user context]。

          2. 执行实现定义的步骤,以确保 request 使用 proxy configuration 所定义的代理设置。

            注:这些 设置在创建用户上下文时已被验证,因此 在此阶段假定其有效;访问代理时的任何错误 都将在处理请求时报告为网络错误。

  2. 使用 request 可能收集网络请求主体

  3. 如果请求发送前映射不包含 request,则将请求发送前映射[request] 设为新的 集合。

  4. redirect countrequest重定向计数

  5. redirect count 添加到请求发送前映射[request]。

  6. 如果 request客户端不为 null,则令 related navigables 为使用 request获取相关可导航客户端的结果。否则,令 related navigables 为空 集合。

  7. response 为 null。

  8. response status 为 "incomplete"。

  9. 对于活动 BiDi 会话中的每个 session

    1. 使用 sessionrequestrelated navigables 更新请求标头

  10. 对于给定 "network.beforeRequestSent" 和 related navigables已启用事件的会话集合 中的每个 session

    1. params 为使用 session、 "network.beforeRequestSent" 和 request 处理 网络事件的结果。

    2. initiator 为使用 request 获取 initiator的结果。

    3. 如果 initiator 不是,则将 paramsinitiator 字段设为 initiator

    4. 断言:params 匹配 network.BeforeRequestSentParameters 产生式。

    5. body 为匹配 network.BeforeRequestSent 产生式的映射,其中 params 字段设为 params

    6. 使用 sessionbody 发出 事件

    7. 如果 params["isBlocked"] 为 true,则:

      1. blocked requestssession已阻塞 请求映射

      2. request idrequest请求 ID

      3. blocked requests[request id] 设为 (request, "beforeRequestSent", null)。

      4. 令 (response, status) 为使用 «"continue request"» 和 request请求 ID 等待的结果。

      5. 如果 status 为 "complete",则将 response status 设为 status

      6. 移除 blocked requests[request id]。

      注:等待期间,不会对请求进行进一步 处理。

  11. emulated network conditions 为使用 related navigables 获取模拟网络条件的结果。

  12. 如果 emulated network conditions 不为 null,且 emulated network conditionsoffline 为 true,则返回 (网络错误, "complete")。

  13. 返回 (response, response status)。

在 Fetch 的 "HTTP-network-or-cache fetch" 算法中遵循返回值。

7.5.6.3. network.fetchError 事件
事件类型
network.FetchError = (
  method: "network.fetchError",
  params: network.FetchErrorParameters
 )

network.FetchErrorParameters = {
  network.BaseParameters,
  errorText: text,
}

此事件会在网络请求以错误结束时发出。

远端事件触发器是给定 request request 时的 WebDriver BiDi fetch error 步骤:
  1. 如果 before request sent map[request] 不包含 requestredirect count,则以 request 运行 WebDriver BiDi before request sent 步骤。

    注:这确保了 network.beforeRequestSent 总是可以在 network.fetchError 之前发出,而无需调用者在每条错误路径上显式调用 WebDriver BiDi before request sent 步骤。

  2. 如果 requestclient 不是 null,则令 related navigables 为以 requestclient 调用获取相关 navigables所得的结果。否则令 related navigables 为空 集合。

  3. request 调用可能中止网络响应体 收集

  4. 对于给定 "network.fetchError" 和 related navigables 时的事件已启用的会话集合中的每个 session

    1. params 为以 session、 "network.fetchError" 和 request 调用处理 network event所得的结果。

    2. paramserrorText 字段设置为一个实现定义的 字符串, 用于描述导致请求中止的错误。

    3. 断言:params 匹配 network.FetchErrorParameters 产生式。

    4. body 为一个匹配 network.FetchError 产生式的映射,其 params 字段设置为 params

    5. sessionbody 发出 事件

7.5.6.4. network.responseCompleted 事件
事件类型
network.ResponseCompleted = (
  method: "network.responseCompleted",
  params: network.ResponseCompletedParameters
 )

network.ResponseCompletedParameters = {
  network.BaseParameters,
  response: network.ResponseData,
}

此事件会在接收到完整响应体之后发出。

远端事件触发器是给定 request requestresponse response 时的 WebDriver BiDi response completed 步骤:
  1. redirect countrequestredirect count

  2. 断言:before request sent map[request] 包含 redirect count

    注:这意味着每个调用者都需要确保在这些步骤之前, 先以 request 调用 WebDriver BiDi before request sent 步骤。

  3. 如果 requestclient 不是 null,则令 related navigables 为以 requestclient 调用获取相关 navigables所得的结果。否则令 related navigables 为空 集合。

  4. requestresponse 调用可能收集网络响应体

  5. sessions 为给定 "network.responseCompleted" 和 related navigables 时的事件已启用的会话集合

  6. 对于 sessions 中的每个 session

    1. params 为以 session、 "network.responseCompleted" 和 request 调用处理 network event所得的结果。

    2. 断言:params["isBlocked"] 为 false。

    3. response data 为以 response 调用获取 response data所得的结果。

    4. paramsresponse 字段设置为 response data

    5. 断言:params 匹配 network.ResponseCompletedParameters 产生式。

    6. body 为一个匹配 network.ResponseCompleted 产生式的映射,其 params 字段设置为 params

    7. sessionbody 发出 事件

7.5.6.5. network.responseStarted 事件
事件类型
network.ResponseStarted = (
  method: "network.responseStarted",
  params: network.ResponseStartedParameters
 )

network.ResponseStartedParameters = {
  network.BaseParameters,
  response: network.ResponseData,
}

此事件会在接收到响应头之后、响应体完成之前发出。

远端事件触发器是给定 request requestresponse response 时的 WebDriver BiDi response started 步骤:
  1. redirect countrequestredirect count

  2. 断言:before request sent map[request] 等于 redirect count

    注:这意味着每个调用者都需要确保在这些步骤之前, 先以 request 调用 WebDriver BiDi before request sent 步骤。

  3. 如果 requestclient 不是 null,则令 related navigables 为以 requestclient 调用获取相关 navigables所得的结果。否则令 related navigables 为空 集合。

  4. response status 为 "incomplete"。

  5. sessions 为给定 "network.responseStarted" 和 related navigables 时的事件已启用的会话集合

  6. 对于 sessions 中的每个 session

    1. params 为以 session、 "network.responseStarted" 和 request 调用处理 network event所得的结果。

    2. response data 为以 response 调用获取 response data所得的结果。

    3. paramsresponse 字段设置为 response data

    4. 断言:params 匹配 network.ResponseStartedParameters 产生式。

    5. body 为一个匹配 network.ResponseStarted 产生式的映射,其 params 字段设置为 params

    6. sessionbody 发出 事件

    7. 如果 params["isBlocked"] 为 true:

      1. blocked requestssessionblocked request map

      2. request idrequestrequest id

      3. blocked requests[request id] 设置为 (request, "beforeRequestSent", response)。

      4. 令 (response, status) 为以 «"continue request"» 和 request id 等待所得的结果。

      5. 如果 status 为 "complete",则将 response status 设置为 status

      6. 移除 blocked requests[request id]。

  7. 返回 (response, response status)。

7.6. script 模块

script 模块包含与 script realm 和执行相关的命令与事件。

7.6.1. 定义

Remote end definition

ScriptCommand = (
  script.AddPreloadScript //
  script.CallFunction //
  script.Disown //
  script.Evaluate //
  script.GetRealms //
  script.RemovePreloadScript
)

local end definition

ScriptResult = (
  script.AddPreloadScriptResult /
  script.CallFunctionResult /
  script.DisownResult /
  script.EvaluateResult /
  script.GetRealmsResult /
  script.RemovePreloadScriptResult
)

ScriptEvent = (
  script.Message //
  script.RealmCreated //
  script.RealmDestroyed
)

7.6.2. 预加载脚本

预加载脚本是一个 在新的 Window 创建时运行, 且在任何作者定义脚本运行之前运行的脚本。

TODO:将其扩展到其他种类 realm 中的脚本。

一个 BiDi 会话具有一个 预加载脚本映射, 它是一个映射, 其中键为 UUID,值为具有以下项的结构体: 名为 function declaration,它是字符串; 名为 arguments,它是列表; 名为 contexts,它是列表或 null; 名为 sandbox,它是字符串或 null; 以及名为 user contexts,它是一个集合

注:如果执行预加载脚本失败,无论是由于语法 错误,还是 运行时异常,都会在其被执行的 realm 中报告一个 [ECMAScript] 异常,而其他预加载脚本会照常运行。

要在给定 environment settings 的情况下,运行 WebDriver BiDi 预加载脚本
  1. documentenvironment settings相关全局对象关联 Document

  2. navigabledocument可导航

  3. user contextnavigable关联用户 上下文

  4. user context iduser context用户 上下文 ID

  5. 对于活动 BiDi 会话中的每个 session

    1. 对于 session预加载脚本映射中的每个 preload script

      1. 如果 preload scriptuser contexts大小不为零:

        1. 如果 preload scriptuser contexts包含 user context id, 则继续

      2. 如果 preload scriptcontexts 不为 null:

        1. navigable idnavigable顶级可遍历的 id。

        2. 如果 preload scriptcontexts包含 navigable id, 则继续

      3. 如果 preload scriptsandbox 不为 null,则令 realm 为使用 preload scriptsandboxnavigable 获取或创建沙盒 realm的结果。 否则,令 realmenvironment settingsrealm 执行上下文的 Realm 组件。

      4. exception reporting globalenvironment settingsrealm 执行上下文的 Realm 组件的全局对象

      5. argumentspreload scriptarguments

      6. deserialized arguments 为空列表。

      7. 对于 arguments 中的每个 argument

        1. channel 为使用 sessionrealmargument 创建 通道的结果。

        2. channel 追加到 deserialized arguments

      8. base URLenvironment settingsAPI 基础 URL

      9. options默认脚本 fetch 选项

      10. function declarationpreload scriptfunction declaration

      11. function body evaluation status 为使用 function declarationenvironment settingsbase URLoptions 求值函数体的结果。

      12. 如果 function body evaluation status突然完成,则为 exception reporting global 报告由异常 function body evaluation status.[[Value]] 给出的异常。

      13. function objectfunction body evaluation status.[[Value]]。

      14. 如果 IsCallable(function object) 为 false

        1. errorrealm 中新的 TypeError 对象。

        2. exception reporting global 报告异常 error

      15. 使用 environment settings 准备运行脚本

      16. evaluation status 设为 Call(function object, null, deserialized arguments)。

      17. 使用 environment settings 运行脚本后清理

      18. 如果 evaluation status突然 完成,则为 exception reporting global 报告由异常 evaluation status.[[Value]] 给出的异常。

7.6.3. 类型

7.6.3.1. script.Channel 类型

远程端定义本地端定义

script.Channel = text;

script.Channel 类型表示用于从远程端本地端发送自定义消息的特定通道的 ID。

7.6.3.2. script.ChannelValue 类型

远程端定义

script.ChannelValue = {
  type: "channel",
  value: script.ChannelProperties,
}

script.ChannelProperties = {
  channel: script.Channel,
  ? serializationOptions: script.SerializationOptions,
  ? ownership: script.ResultOwnership,
}

script.ChannelValue 类型表示一种 ArgumentValue,它可以被反序列化为一个函数,该函数用于从远程端本地端发送 消息。

要在给定 sessionrealmprotocol value 的情况下创建 channel

  1. channel propertiesprotocol value["value"]。

  2. steps 为给定参数 message 时的以下步骤:

    1. current realm当前 Realm Record

    2. sessioncurrent realmchannel propertiesmessage 发出 script message

  3. 返回 CreateBuiltinFunction(steps, 1, "", « », realm)。

7.6.3.3. script.EvaluateResult 类型

远程端定义本地端定义

script.EvaluateResult = (
  script.EvaluateResultSuccess /
  script.EvaluateResultException
)

script.EvaluateResultSuccess = {
  type: "success",
  result: script.RemoteValue,
  realm: script.Realm
}

script.EvaluateResultException = {
  type: "exception",
  exceptionDetails: script.ExceptionDetails
  realm: script.Realm
}

script.EvaluateResult 类型指示执行脚本的命令的返回值。 script.EvaluateResultSuccess 变体用于脚本正常完成的情况,而 script.EvaluateResultException 变体用于脚本以抛出异常完成的情况。

7.6.3.4. script.ExceptionDetails 类型

远程端定义本地端定义

script.ExceptionDetails = {
  columnNumber: js-uint,
  exception: script.RemoteValue,
  lineNumber: js-uint,
  stackTrace: script.StackTrace,
  text: text,
}

script.ExceptionDetails 类型表示一个 JavaScript 异常。

要在给定 realm、一个完成记录 record、一个 ownership type 和一个 session 的情况下,获取异常 详情

  1. 断言:record.[[Type]] 为 throw

  2. text 为由实现定义的、对 record 所表示错误的文本描述。

    TODO:收紧这里的要求;人们很可能会尝试用正则表达式之类同样糟糕的东西来解析 这些数据。

  3. serialization options 为一个匹配 script.SerializationOptions 产生式的映射, 其字段设为 它们的默认值。

  4. exception 为使用 record.[[Value]]、serialization optionsownership type、 一个新的映射作为序列化内部映射、realmsession 序列化为 远程值的结果。

  5. stack trace 为给定 record异常的堆栈跟踪

  6. 如果 stack trace 的大小为 1 或更大,则令 line numberstack trace[0] 中 lineNumber 字段的值,并令 column numberstack trace[0] 中 columnNumber 字段的值。否则 令 line numbercolumn number 为 0。

  7. exception details 为一个匹配 script.ExceptionDetails 产生式的映射, 其中 text 字段设为 textexception 字段设为 exceptionlineNumber 字段设为 line numbercolumnNumber 字段设为 column number,并且 stackTrace 字段设为 stack trace

  8. 返回 exception details

7.6.3.5. script.Handle 类型

远程端定义本地端定义

script.Handle = text;

script.Handle 类型表示由 ECMAScript 运行时拥有的对象的句柄。该句柄仅在特定Realm中有效。

每个 ECMAScript Realm 都有一个对应的 句柄对象映射。这是一个 从句柄 ID 到其对应对象的强映射

7.6.3.6. script.InternalId 类型

远程端定义本地端定义

script.InternalId = text;

script.InternalId 类型表示在 序列化期间, 先前序列化的 script.RemoteValue 的 ID。

7.6.3.7. script.LocalValue 类型

远程端定义

script.LocalValue = (
  script.RemoteReference /
  script.PrimitiveProtocolValue /
  script.ChannelValue /
  script.ArrayLocalValue /
  { script.DateLocalValue } /
  script.MapLocalValue /
  script.ObjectLocalValue /
  { script.RegExpLocalValue } /
  script.SetLocalValue
)

script.ListLocalValue = [*script.LocalValue];

script.ArrayLocalValue = {
  type: "array",
  value: script.ListLocalValue,
}

script.DateLocalValue = (
  type: "date",
  value: text
)

script.MappingLocalValue = [*[(script.LocalValue / text), script.LocalValue]];

script.MapLocalValue = {
  type: "map",
  value: script.MappingLocalValue,
}

script.ObjectLocalValue = {
  type: "object",
  value: script.MappingLocalValue,
}

script.RegExpValue = {
  pattern: text,
  ? flags: text,
}

script.RegExpLocalValue = (
  type: "regexp",
  value: script.RegExpValue,
)

script.SetLocalValue = {
  type: "set",
  value: script.ListLocalValue,
}

script.LocalValue 类型表示可以被反序列化到 ECMAScript 中的值。 这包括原始值和非原始值,以及远程引用通道

要在给定 serialized key-value listrealmsession 的情况下,反序列化 键值列表

  1. deserialized key-value list 为一个新列表。

  2. 对于 serialized key-value list 中的每个 serialized key-value

    1. 如果 serialized key-value大小不是 2, 则返回带有错误码 无效参数错误

    2. serialized keyserialized key-value[0]。

    3. 如果 serialized keystring, 则令 deserialized keyserialized key

    4. 否则,令 deserialized key尝试在给定 serialized keyrealmsession 的情况下 反序列化本地值的结果。

    5. serialized valueserialized key-value[1]。

    6. deserialized value尝试 在给定 serialized valuerealmsession 的情况下 反序列化本地值的结果。

    7. CreateArrayFromListdeserialized key, deserialized value») 追加到 deserialized key-value list

  3. 返回带有数据 deserialized key-value list成功

要在给定 serialized value listrealmsession 的情况下,反序列化 值列表

  1. deserialized values 为一个新列表。

  2. 对于 serialized value list 中的每个 serialized value

    1. deserialized value尝试 在给定 serialized valuerealmsession 的情况下 反序列化本地值的结果。

    2. deserialized value 追加到 deserialized values

  3. 返回带有数据 deserialized values成功

要在给定 local protocol valuerealmsession 的情况下,反序列化 本地值

  1. 如果 local protocol value 匹配script.RemoteReference 产生式,则返回 给定 local protocol valuerealmsession反序列化远程引用

  2. 如果 local protocol value 匹配script.PrimitiveProtocolValue 产生式, 则返回使用 local protocol value 反序列化原始协议值的结果。

  3. 如果 local protocol value 匹配 script.ChannelValue 产生式, 则返回使用 sessionrealmlocal protocol value 创建 通道的结果。

  4. typelocal protocol valuetype 字段的值;如果没有这样的字段,则为 undefined。

  5. valuelocal protocol valuevalue 字段的值;如果没有这样的字段, 则为 undefined。

  6. 在以下条件及关联步骤列表中,运行首个关联条件为 true 的步骤集:

    type 为字符串 "array"
    1. deserialized value list尝试在给定 valuerealmsession 的情况下反序列化值列表的结果。

    2. 返回带有数据 CreateArrayFromList(deserialized value list) 的成功

    type 为字符串 "date"
    1. 如果 value 不匹配 日期时间字符串格式,则返回 带有 错误码 无效参数错误

    2. date resultConstruct(Date, value)。

    3. 断言:date result 不是突然 完成

    4. 返回带有数据 date result成功

    type 为字符串 "map"
    1. deserialized key-value list尝试使用 valuerealmsession 反序列化键值列表的结果。

    2. iterableCreateArrayFromList(deserialized key-value list)

    3. 返回带有数据 Map(iterable) 的成功

    type 为字符串 "object"
    1. deserialized key-value list尝试使用 valuerealmsession 反序列化键值列表的结果。

    2. iterableCreateArrayFromList(deserialized key-value list)

    3. 返回带有数据 Object.fromEntries(iterable) 的成功

    type 为字符串 "regexp"
    1. patternlocal protocol valuepattern 字段的值。

    2. flagslocal protocol valueflags 字段的值; 如果没有这样的字段,则为 undefined。

    3. regex_resultRegexp(pattern, flags)。如果这抛出异常,则返回 带有错误码 无效参数错误

    4. 返回带有数据 regex_result成功

    type 为字符串 "set"
    1. deserialized value list尝试在给定 valuerealmsession 的情况下反序列化值列表的结果。

    2. iterableCreateArrayFromList(deserialized key-value list)

    3. 返回带有数据 Set object(iterable) 的成功

    否则
    返回带有错误码 无效参数错误
7.6.3.8. script.PreloadScript 类型

远程端定义本地端定义

script.PreloadScript = text;

script.PreloadScript 类型表示将在 realm 创建时运行的脚本的句柄。

7.6.3.9. script.Realm 类型

远程端定义本地端定义

script.Realm = text;

每个 realm 都有关联的 realm ID,它是一个 唯一标识该 realm 的字符串。这会在 realm 创建时隐式设置。

realm 的 realm ID 是不透明的, 不得能从句柄对象映射中对应全局对象的句柄 ID 推导出来,或在相关时,从任何可导航 ID可导航推导出来。

注:这是为了确保用户不会依赖 不同 ID 之间实现特定的 关系。

要在给定 realm id 的情况下获取 realm
  1. 如果 realm id 为 null,则返回带有数据 null 的成功

  2. 如果不存在具有 ID realm idrealm,则返回 带有错误 码 无此 frame错误

  3. realm 为具有 ID realm idrealm

  4. 返回带有数据 realm成功

这使用了错误的 错误码

7.6.3.10. script.PrimitiveProtocolValue 类型

远程端定义本地端定义

script.PrimitiveProtocolValue = (
  script.UndefinedValue /
  script.NullValue /
  script.StringValue /
  script.NumberValue /
  script.BooleanValue /
  script.BigIntValue
)

script.UndefinedValue = {
  type: "undefined",
}

script.NullValue = {
  type: "null",
}

script.StringValue = {
  type: "string",
  value: text,
}

script.SpecialNumber = "NaN" / "-0" / "Infinity" / "-Infinity";

script.NumberValue = {
  type: "number",
  value: number / script.SpecialNumber,
}

script.BooleanValue = {
  type: "boolean",
  value: bool,
}

script.BigIntValue = {
  type: "bigint",
  value: text,
}

script.PrimitiveProtocolValue 表示只能 由值表示而绝不由引用表示的值。

要在给定 value 的情况下序列化原始协议值

  1. remote value 为 undefined。

  2. 在以下条件及关联步骤列表中,如果有的话,运行首个 关联条件为 true 的步骤集:

    Type(value) 为 undefined
    remote value 为一个匹配 本地端定义script.UndefinedValue 产生式的映射
    Type(value) 为 Null
    remote value 为一个匹配 本地端定义script.NullValue 产生式的映射
    Type(value) 为 String
    remote value 为一个匹配 本地端定义script.StringValue 产生式的映射, 其 value 属性设为 value

    这 不处理孤立代理项

    Type(value) 为 Number
    1. 切换 value 的值:

      NaN
      serialized"NaN"
      -0
      serialized"-0"
      Infinity
      serialized"Infinity"
      -Infinity
      serialized"-Infinity"
      否则:
      serializedvalue
    2. remote value 为一个匹配 本地端定义script.NumberValue 产生式的映射, 其 value 属性设为 serialized

    Type(value) 为 Boolean
    remote value 为一个匹配 本地端定义script.BooleanValue 产生式的映射, 其 value 属性设为 value
    Type(value) 为 BigInt
    remote value 为一个匹配 本地端定义script.BigIntValue 产生式的映射, 其 value 属性设为在 value 上运行 ToString 操作的结果。
  3. 返回 remote value

要在给定 primitive protocol value 的情况下反序列化原始协议值

  1. typeprimitive protocol valuetype 字段的值。

  2. value 为 undefined。

  3. 如果 primitive protocol value 具有字段 value

    1. valueprimitive protocol valuevalue 字段的值。

  4. 在以下条件及关联步骤列表中,运行首个关联条件为 true 的步骤集:

    type 为字符串 "undefined"
    返回带有数据 undefined成功
    type 为字符串 "null"
    返回带有数据 null成功
    type 为字符串 "string"
    返回带有数据 value成功
    type 为字符串 "number"
    1. 如果 Type(value) 为 Number,则返回带有数据 value成功

    2. 断言:Type(value) 为 String。

    3. 如果 value 是字符串 "NaN",则返回带有 数据 NaN 的成功

    4. number_resultStringToNumber(value)。

    5. 如果 number_result 为 NaN,则返回带有错误码 无效参数错误

    6. 返回带有数据 number_result成功

    type 为字符串 "boolean"
    返回带有数据 value成功
    type 为字符串 "bigint"
    1. bigint_resultStringToBigInt(value)。

    2. 如果 bigint_result 为 undefined,则返回带有错误码 无效参数错误

    3. 返回带有数据 bigint_result成功

  5. 返回带有错误 码 无效参数错误

7.6.3.11. script.RealmInfo 类型

本地端定义

script.RealmInfo = (
  script.WindowRealmInfo /
  script.DedicatedWorkerRealmInfo /
  script.SharedWorkerRealmInfo /
  script.ServiceWorkerRealmInfo /
  script.WorkerRealmInfo /
  script.PaintWorkletRealmInfo /
  script.AudioWorkletRealmInfo /
  script.WorkletRealmInfo
)

script.BaseRealmInfo = (
  realm: script.Realm,
  origin: text
)

script.WindowRealmInfo = {
  script.BaseRealmInfo,
  type: "window",
  context: browsingContext.BrowsingContext,
  ? userContext: browser.UserContext,
  ? sandbox: text
}

script.DedicatedWorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "dedicated-worker",
  owners: [script.Realm]
}

script.SharedWorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "shared-worker"
}

script.ServiceWorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "service-worker"
}

script.WorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "worker"
}

script.PaintWorkletRealmInfo = {
  script.BaseRealmInfo,
  type: "paint-worklet"
}

script.AudioWorkletRealmInfo = {
  script.BaseRealmInfo,
  type: "audio-worklet"
}

script.WorkletRealmInfo = {
  script.BaseRealmInfo,
  type: "worklet"
}

注: script.RealmInfo 的变体与 script.RealmType 的值之间存在 1:1 关系。

script.RealmInfo 类型表示 realm 的属性。

要在给定 realm 的情况下,获取该可导航
  1. global objectrealm全局对象

  2. global object解包后global object

  3. 如果 global object 不是 Window 对象,则返回 null

  4. documentglobal object 的已包装 Window关联 Document

  5. 返回 document节点可导航

要在给定 global object 的情况下,获取该 worker 的 拥有者
  1. 断言:global objectWorkerGlobalScope 对象。

  2. owners 为空列表

  3. 对于 global object 的关联拥有者集合中的每个 owner

    1. owner environment settingsowner相关设置对象

    2. owner realm info 为给定 owner environment settings 获取 realm info的结果。

    3. 如果 owner realm info 为 null,则继续。

    4. owner realm info["id"] 追加到 owners

  4. 返回 owners

要在给定 environment settings 的情况下,获取 realm info
  1. realmenvironment settingsrealm 执行上下文的 Realm 组件。

  2. realm idrealmrealm ID

  3. origin 为给定 environment settingsorigin源序列化

  4. global objectenvironment settings 指定的全局对象

  5. 运行首个匹配条件下的步骤:

    global objectWindow 对象
    1. documentenvironment settings相关全局对象关联 Document

    2. navigabledocument节点可导航

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

    4. navigable idnavigable可导航 ID

    5. user context idnavigable关联用户上下文用户上下文 ID

    6. realm info 为一个匹配 script.WindowRealmInfo 产生式的映射, 其中 realm 字段设为 realm idorigin 字段设为 origincontext 字段设为 navigable id,且 userContext 字段设为 user context id

    global objectSandboxWindowProxy 对象
    TODO:尚不清楚这是否是处理 sandbox 的正确表述。
    1. documentglobal object 的已包装 Window关联 Document

    2. navigabledocument节点可导航

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

    4. navigable idnavigable可导航 ID

    5. user context idnavigable关联用户上下文用户上下文 ID

    6. sandbox name 为给定 realm 获取 sandbox 名称的结果。

    7. 断言:sandbox name 不为 null。

    8. realm info 为一个匹配 script.WindowRealmInfo 产生式的映射, 其中 realm 字段设为 realm idorigin 字段设为 origincontext 字段设为 navigable iduserContext 字段设为 user context id,且 sandbox 字段设为 sandbox name

    global objectDedicatedWorkerGlobalScope 对象
    1. owners 为给定 global object 获取该 worker 的拥有者的结果。

    2. 断言:owners 正好有一项。

    3. realm info 为一个匹配 script.DedicatedWorkerRealmInfo 产生式的映射, 其中 realm 字段设为 realm idorigin 字段 设为 origin,且 owners 字段设为 owners

    global objectSharedWorkerGlobalScope 对象
    1. realm info 为一个匹配 script.SharedWorkerRealmInfo 产生式的映射, 其中 realm 字段设为 realm id,且 origin 字段 设为 origin

    global objectServiceWorkerGlobalScope 对象
    1. realm info 为一个匹配 script.ServiceWorkerRealmInfo 产生式的映射, 其中 realm 字段设为 realm id,且 origin 字段 设为 origin

    global objectWorkerGlobalScope 对象
    1. realm info 为一个匹配 script.WorkerRealmInfo 产生式的映射, 其中 realm 字段设为 realm id,且 origin 字段设为 origin

    global objectPaintWorkletGlobalScope 对象
    1. realm info 为一个匹配 script.PaintWorkletRealmInfo 产生式的映射, 其中 realm 字段设为 realm id,且 origin 字段设为 origin

    global objectAudioWorkletGlobalScope 对象
    1. realm info 为一个匹配 script.AudioWorkletRealmInfo 产生式的映射, 其中 realm 字段设为 realm id,且 origin 字段设为 origin

    global objectWorkletGlobalScope 对象
    1. realm info 为一个匹配 script.WorkletRealmInfo 产生式的映射, 其中 realm 字段设为 realm id,且 origin 字段设为 origin

    否则:
    1. realm info 为 null。

  6. 返回 realm info

注:本规范未来的变体将 保持如下不变量: 在按 "-" 拆分后,类型名称的最后一个组成部分 对于实现 WorkerGlobalScope 的全局对象始终为 "worker", 而对于实现 WorkletGlobalScope 的全局对象始终为 "worklet"。

7.6.3.12. script.RealmType 类型

远程端定义本地端定义

script.RealmType = "window" / "dedicated-worker" / "shared-worker" / "service-worker" /
                   "worker" / "paint-worklet" / "audio-worklet" / "worklet"

script.RealmType 类型表示 Realm 的不同类型。

7.6.3.13. script.RemoteReference 类型

远程端定义

script.RemoteReference = (
  script.SharedReference /
  script.RemoteObjectReference
)

script.SharedReference = {
   sharedId: script.SharedId

   ? handle: script.Handle,
   Extensible
}

script.RemoteObjectReference = {
   handle: script.Handle,

   ? sharedId: script.SharedId
   Extensible
}

script.RemoteReference 类型要么是 script.RemoteObjectReference,表示对给定Realm句柄对象映射里 现有 ECMAScript 对象的远程引用,要么 是 script.SharedReference,表示对节点的引用。

处理“陈旧对象 引用”情形。

注:如果提供的引用同时具有 handlesharedId,则该算法将忽略 handle,并且仅遵循 sharedId

要在给定 remote referencerealmsession 的情况下,反序列化 远程引用
  1. 断言 remote reference 匹配 script.RemoteReference 产生式。

  2. 如果 remote reference 匹配 script.SharedReference 产生式,则返回 使用 remote referencerealmsession 反序列化共享引用的结果。

  3. 返回使用 remote referencerealm 反序列化远程对象引用的结果。

要在给定 remote object referencerealm 的情况下,反序列化远程对象引用
  1. handle idremote object referencehandle 字段的值。

  2. handle maprealm句柄对象映射

  3. 如果 handle map 不包含 handle id,则返回 带有 错误码 无此句柄错误

  4. 返回带有数据 handle map[handle id] 的成功

要在给定 shared referencerealmsession 的情况下,反序列化 共享引用
  1. 断言 shared reference 匹配 script.SharedReference 产生式。

  2. navigable 为使用 realm 获取该可导航的结果。

  3. 如果 navigablenull,则返回带有错误码 无此 节点错误

    注:当 realm 不是 Window 全局对象时会发生这种情况。

  4. shared idshared referencesharedId 字段的值。

  5. node尝试使用 sessionnavigableshared id 获取节点的结果。

  6. 如果 nodenull,则返回带有错误码 无此 节点错误

  7. environment settings环境设置对象,其 realm 执行上下文的 Realm 组件为 realm

  8. 如果 node节点文档environment settings不是同源域, 则返回带有错误 码 无此节点错误

    注:这确保 WebDriver-BiDi 不能被用来在本来不允许脚本访问的 realm 之间传递对象。

  9. realm global objectrealm全局对象

  10. 如果 realm global objectSandboxWindowProxy 对象,则将 node 设为在 realm 中包装 nodeSandboxProxy

  11. 返回带有数据 node成功

7.6.3.14. script.RemoteValue 类型

远程端定义本地端定义

script.RemoteValue = (
  script.PrimitiveProtocolValue /
  script.SymbolRemoteValue /
  script.ArrayRemoteValue /
  script.ObjectRemoteValue /
  script.FunctionRemoteValue /
  script.RegExpRemoteValue /
  script.DateRemoteValue /
  script.MapRemoteValue /
  script.SetRemoteValue /
  script.WeakMapRemoteValue /
  script.WeakSetRemoteValue /
  script.GeneratorRemoteValue /
  script.ErrorRemoteValue /
  script.ProxyRemoteValue /
  script.PromiseRemoteValue /
  script.TypedArrayRemoteValue /
  script.ArrayBufferRemoteValue /
  script.NodeListRemoteValue /
  script.HTMLCollectionRemoteValue /
  script.NodeRemoteValue /
  script.WindowProxyRemoteValue
)

script.ListRemoteValue = [*script.RemoteValue];

script.MappingRemoteValue = [*[(script.RemoteValue / text), script.RemoteValue]];

script.SymbolRemoteValue = {
  type: "symbol",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ArrayRemoteValue = {
  type: "array",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.ObjectRemoteValue = {
  type: "object",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.MappingRemoteValue,
}

script.FunctionRemoteValue = {
  type: "function",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.RegExpRemoteValue = {
  script.RegExpLocalValue,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.DateRemoteValue = {
  script.DateLocalValue,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.MapRemoteValue = {
  type: "map",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.MappingRemoteValue,
}

script.SetRemoteValue = {
  type: "set",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue
}

script.WeakMapRemoteValue = {
  type: "weakmap",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.WeakSetRemoteValue = {
  type: "weakset",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.GeneratorRemoteValue = {
  type: "generator",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ErrorRemoteValue = {
  type: "error",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ProxyRemoteValue = {
  type: "proxy",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.PromiseRemoteValue = {
  type: "promise",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.TypedArrayRemoteValue = {
  type: "typedarray",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ArrayBufferRemoteValue = {
  type: "arraybuffer",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.NodeListRemoteValue = {
  type: "nodelist",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.HTMLCollectionRemoteValue = {
  type: "htmlcollection",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.NodeRemoteValue = {
  type: "node",
  ? sharedId: script.SharedId,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.NodeProperties,
}

script.NodeProperties = {
  nodeType: js-uint,
  childNodeCount: js-uint,
  ? attributes: {*text => text},
  ? children: [*script.NodeRemoteValue],
  ? localName: text,
  ? mode: "open" / "closed",
  ? namespaceURI: text,
  ? nodeValue: text,
  ? shadowRoot: script.NodeRemoteValue / null,
}

script.WindowProxyRemoteValue = {
  type: "window",
  value: script.WindowProxyProperties,
  ? handle: script.Handle,
  ? internalId: script.InternalId
}

script.WindowProxyProperties = {
  context: browsingContext.BrowsingContext
}

添加 WASM 类型?

WindowProxy 是否应该以类似 Node 的样式 获取属性?

是否要特殊处理 String / Number / 等包装器对象?

可从 ECMAScript 运行时访问的值由一个镜像对象表示, 其指定为 script.RemoteValue。值的类型由 type 属性指定。对于可用 JSON 表示的 原始值,它会在 value 属性中包含该值;对于 不可用 JSON 表示的原始值,value 属性 包含该值的字符串表示。

对于非原始对象,handle 属性在存在时 包含指向该对象的唯一字符串 handle。该 handle 对于每次 序列化都是唯一的。远端会让具有对应 handle 的对象 保持存活,直到以该 handle 调用 script.disown, 或 realm 本身将被丢弃(例如由于导航)。

对于某些非原始类型,value 属性包含 ECMAScript 对象中数据的表示;对于容器类型,这 可以包含更多 script.RemoteValue 实例。 如果存在重复对象,即该对象已经在当前 script.RemoteValue 中被序列化过(也许作为循环的一部分), 或者在达到最大序列化深度时,value 属性可以为 null 或被省略。

在同一 script.RemoteValue 中存在重复对象的情况下, 只为其中一个 remote value 提供 value,而 对于给定序列化中的所有重复对象,都会提供按 ECMAScript 对象唯一的 internalId

Nodes 也由 script.RemoteValue 实例表示。它们在 value 属性中具有 node 的部分序列化。

重新考虑镜像对象的 生命周期。

注:镜像对象不会让运行时中的原始对象 保持存活。如果某个对象在运行时中被丢弃,随后尝试通过 协议访问它将导致错误。

要在给定 realmownership typeobject 时,获取对象的 handle
  1. 如果 ownership type 等于 "none",返回 null

  2. handle idobject 的新的、唯一的字符串 handle。

  3. handle maprealmhandle object map

  4. handle map[handle id] 设置为 object

  5. 返回 handle id 作为结果。

要在给定 nodesession获取 node 的 shared id
  1. node解包装的 node

  2. 如果 node 未实现 Node, 返回 null。

  3. navigablenodenode navigable

  4. 如果 navigable 为 null,返回 null。

  5. 返回以 sessionnavigablenode 调用获取或创建 node 引用的结果。

要在给定 serialization internal mapremote valueobject必要时设置 internal ids
  1. 如果 serialization internal map 不包含 object,则将 serialization internal map[object] 设置为 remote value

  2. 否则,运行以下步骤:

    1. previously serialized remote valueserialization internal map[object]。

    2. 如果 previously serialized remote value 没有 internalId 字段,则运行以下步骤:

      1. internal id 为基于真正随机或伪随机数字的 UUID 的字符串表示。

      2. previously serialized remote valueinternalId 字段设置为 internal id

    3. remote valueinternalId 字段设置为 previously serialized remote value 中的 internalId 字段。

要在给定 valueserialization options、 一个 ownership type、一个 serialization internal map、一个 realm 和一个 session 的情况下,序列化 为远程值

  1. remote value 为在给定 value 的情况下序列化原始协议值的结果。

  2. 如果 remote value 不是 undefined,则返回 remote value

  3. handle id 为使用 realmownership typevalue 对象的句柄

  4. ownership type 设为 "none"。

  5. 如果 valueserialization internal map 中,则令 known objecttrue,否则为 false

  6. 在以下条件及关联步骤列表中,运行首个 关联条件为 true 的步骤集:

    Type(value) 为 Symbol
    remote value 为一个匹配 本地端定义script.SymbolRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则省略该属性。
    IsArray(value)
    remote value 为使用 sessionscript.ArrayRemoteValuehandle idknown objectvalueserialization optionsownership typeserialization internal maprealmsession 序列化类数组对象的结果。
    IsRegExp(value)
    1. patternToString(Get(value, "source"))。

    2. flagsToString(Get(value, "flags"))。

    3. serialized 为一个匹配 本地端定义script.RegExpValue 产生式的映射, 其 pattern 属性设为 pattern,且 flags 属性设为 flags

    4. remote value 为一个匹配 本地端定义script.RegExpRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则省略该属性,并且 value 属性设为 serialized

    value 具有 [[DateValue]] 内部槽
    1. serialized 设为 Call(Date.prototype.toISOString, value)。

    2. 断言:serialized 不是抛出完成

    3. remote value 为一个匹配 本地端定义script.DateRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则省略该属性,并且 值设为 serialized

    value 具有 [[MapData]] 内部槽
    1. remote value 为一个匹配 本地端定义script.MapRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则 省略该属性。

    2. 使用 serialization internal mapremote valuevalue 按需设置内部 ID

    3. serialized 为 null。

    4. 如果 known objectfalse,且 serialization options["maxObjectDepth"] 不为 0,则运行以下 步骤:

      1. serialized 为使用 CreateMapIterator(value, key+value)、serialization optionsownership typeserialization internal maprealmsession 序列化为映射的结果。

    5. 如果 serialized 不为 null,则将 remote value 的字段 value 设为 serialized

    value 具有 [[SetData]] 内部槽
    1. remote value 为一个匹配 本地端定义script.SetRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则 省略该属性。

    2. 使用 serialization internal mapremote valuevalue 按需设置内部 ID

    3. serialized 为 null。

    4. 如果 known objectfalse,且 serialization options["maxObjectDepth"] 不为 0,则运行以下 步骤:

      1. serialized 为使用 CreateSetIterator(value, value)、serialization optionsownership typeserialization internal maprealmsession 序列化为列表的结果。

    5. 如果 serialized 不为 null,则将 remote value 的字段 value 设为 serialized

    value 具有 [[WeakMapData]] 内部槽
    remote value 为一个匹配 本地端定义script.WeakMapRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则省略该属性。
    value 具有 [[WeakSetData]] 内部槽
    remote value 为一个匹配 本地端定义script.WeakSetRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则省略该属性。
    value 具有 [[GeneratorState]] 内部槽或 [[AsyncGeneratorState]] 内部槽
    remote value 为一个匹配 本地端定义script.GeneratorRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则省略该属性。
    value 具有 [[ErrorData]] 内部槽
    remote value 为一个匹配 本地端定义script.ErrorRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则省略该属性。
    value 具有 [[ProxyHandler]] 内部槽和 [[ProxyTarget]] 内部槽
    remote value 为一个匹配 本地端定义script.ProxyRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则省略该属性。
    IsPromise(value)
    remote value 为一个匹配 本地端定义script.PromiseRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则省略该属性。
    value 具有 [[TypedArrayName]] 内部槽
    remote value 为一个匹配 本地端定义script.TypedArrayRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则省略该属性。
    value 具有 [[ArrayBufferData]] 内部槽
    remote value 为一个匹配 本地端定义script.ArrayBufferRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则省略该属性。
    value 是实现 NodeList平台对象
    remote value 为使用 script.NodeListRemoteValuehandle idknown objectvalueserialization optionsownership typeserialization internal maprealmsession 序列化类数组对象的结果。
    value 是实现 HTMLCollection平台对象
    remote value 为使用 script.HTMLCollectionRemoteValuehandle idknown objectvalueserialization optionsownership typeknown objectserialization internal maprealmsession 序列化类数组对象的结果。
    value 是实现 Node平台对象
    1. shared id 为使用 valuesession 获取 节点的共享 ID

    2. remote value 为一个匹配 本地端定义script.NodeRemoteValue 产生式的映射, 如果 shared id 不为 null,则将 sharedId 属性设为 shared id;否则省略该属性,并且 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则 省略该属性。

    3. 使用 serialization internal mapremote valuevalue 按需设置内部 ID

    4. serialized 为 null。

    5. 如果 known objectfalse,则运行以下步骤:

      1. serialized 为一个映射

      2. serialized["nodeType"] 设为 Get(value, "nodeType")。

      3. node value 设为 Get(value, "nodeValue")。

      4. 如果 node value 不为 null,则将 serialized["nodeValue"] 设为 node value

      5. 如果 value 实现 ElementAttr

        1. serialized["localName"] 设为 Get(value, "localName")。

        2. serialized["namespaceURI"] 设为 Get(value, "namespaceURI")

      6. child node countvalue子节点大小

      7. serialized["childNodeCount"] 设为 child node count

      8. 如果 serialization options["maxDomDepth"] 等于 0,或者如果 value 实现 ShadowRootserialization options["includeShadowTree"] 为 "none", 或者如果 serialization options["includeShadowTree"] 为 "open" 且 value模式为 "closed",则令 children 为 null。

        否则,令 children 为空列表,并且对于 value子节点中的每个节点 child

        1. child serialization optionsserialization options克隆

        2. 如果 child serialization options["maxDomDepth"] 不为 null,则将 child serialization options["maxDomDepth"] 设为 child serialization options["maxDomDepth"] - 1。

        3. serialized 为使用 childchild serialization optionsownership typeserialization internal maprealmsession 序列化为 远程值的结果。

        4. serialized 追加到 children

      9. 如果 children 不为 null,则将 serialized["children"] 设为 children

      10. 如果 value 实现 Element

        1. attributes 为新的映射

        2. 对于 value属性列表中的每个 attribute

          1. nameattribute限定 名称

          2. valueattribute

          3. attributes[name] 设为 value

        3. serialized["attributes"] 设为 attributes

        4. shadow rootvalue影子根

        5. 如果 shadow root 为 null,则令 serialized shadow 为 null。 否则运行以下子步骤:

          1. serialized shadow 为使用 shadow rootserialization optionsownership typeserialization internal maprealmsession 序列化 为远程值的结果。

        6. serialized["shadowRoot"] 设为 serialized shadow

      11. 如果 value 实现 ShadowRoot, 则将 serialized["mode"] 设为 value模式

    6. 如果 serialized 不为 null,则将 remote value 的字段 value 设为 serialized

    value 是实现 WindowProxy平台对象
    1. windowvalue 的 [[WindowProxy]] 内部 槽的值。

    2. navigablewindow可导航

    3. navigable idnavigable可导航 ID

    4. serialized 为一个匹配 本地端定义script.WindowProxyProperties 产生式的映射, 其 context 属性设为 navigable id

    5. remote value 为一个匹配 本地端定义script.WindowProxyRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则省略该属性,并且 value 属性设为 serialized

    value平台对象
    1. 令 remote value 为一个匹配 本地端定义script.ObjectRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则省略该属性。
    IsCallable(value)
    remote value 为一个匹配 本地端定义script.FunctionRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性设为 handle id;否则省略该属性。
    否则:
    1. 断言Type(value) 为 Object

    2. remote value 为一个匹配 本地端定义script.ObjectRemoteValue 产生式的映射, 如果 handle id 不为 null,则将 handle 属性 设为 handle id;否则省略该属性。

    3. 使用 serialization internal mapremote valuevalue 按需设置内部 ID

    4. serialized 为 null。

    5. 如果 known objectfalse,且 serialization options["maxObjectDepth"] 不为 0,则运行以下 步骤:

      1. serialized 为使用 EnumerableOwnPropertyNames(value, key+value)、serialization optionsownership typeserialization internal maprealmsession 序列化为映射的结果。

    6. 如果 serialized 不为 null,则将 remote value 的字段 value 设为 serialized

  7. 返回 remote value

children 和子节点是不同的东西。childNodeCount 要么应当 引用 childNodes,要么应当重命名为 childrenCount

要在给定 productionhandle idknown objectvalueserialization optionsownership typeserialization internal maprealmsession序列化 Array-like
  1. remote value 为一个映射, 其匹配 production,并将 handle 属性设置为 handle id(如果它不为 null),否则省略。

  2. serialization internal mapremote valuevalue 调用必要时设置 internal ids

  3. 如果 known objectfalse,且 serialization options["maxObjectDepth"] 不为 0:

    1. serialized 为以 CreateArrayIterator(value, value)、serialization optionsownership typeserialization internal maprealmsession 调用序列化为 list的结果。

    2. 如果 serialized 不为 null,则将 remote value 的字段 value 设置为 serialized

  4. 返回 remote value

要在给定 iterableserialization optionsownership typeserialization internal maprealmsession序列化为 list
  1. 如果 serialization options["maxObjectDepth"] 不为 null, 断言:serialization options["maxObjectDepth"] 大于 0。

  2. serialized 为一个新列表。

  3. 对于 IteratorToList(GetIterator(iterable, sync)) 中的每个 child value

    1. child serialization optionsserialization options克隆

    2. 如果 child serialization options["maxObjectDepth"] 不为 null,则将 child serialization options["maxObjectDepth"] 设置为 child serialization options["maxObjectDepth"] - 1。

    3. serialized child 为以 child valuechild serialization optionsownership typeserialization internal maprealmsession 调用序列化为 remote value的结果。

    4. serialized child 追加到 serialized

  4. 返回 serialized

要在给定 iterableserialization optionsownership typeserialization internal maprealmsession序列化为 mapping

  1. 如果 serialization options["maxObjectDepth"] 不为 null, 断言:serialization options["maxObjectDepth"] 大于 0。

  2. serialized 为一个新列表。

  3. 对于 IteratorToList(GetIterator(iterable, sync)) 中的 item

    1. 断言:IsArray(item)

    2. propertyCreateListFromArrayLike(item)

    3. 断言:property 是一个大小为 2 的列表

    4. keyproperty[0],令 valueproperty[1]

    5. child serialization optionsserialization options克隆

    6. 如果 child serialization options["maxObjectDepth"] 不为 null,则将 child serialization options["maxObjectDepth"] 设置为 child serialization options["maxObjectDepth"] - 1。

    7. 如果 Type(key) is String,则令 serialized keychild key, 否则令 serialized key 为以 child keychild serialization optionsownership typeserialization internal maprealmsession 调用序列化为 remote value的结果。

    8. serialized value 为以 valuechild serialization optionsownership typeserialization internal maprealmsession 调用序列化为 remote value的结果。

    9. serialized child 为(«serialized key, serialized value»)。

    10. serialized child 追加到 serialized

  4. 返回 serialized

7.6.3.15. script.ResultOwnership 类型
script.ResultOwnership = "root" / "none"

script.ResultOwnership 指定如何处理已序列化值的 所有权。

7.6.3.16. script.SerializationOptions 类型

远程端定义

script.SerializationOptions = {
  ? maxDomDepth: (js-uint / null) .default 0,
  ? maxObjectDepth: (js-uint / null) .default null,
  ? includeShadowTree: ("none" / "open" / "all") .default "none",
}

script.SerializationOptions 允许指定 ECMAScript 对象将如何被序列化。

7.6.3.17. script.SharedId 类型

远程端定义本地端定义

script.SharedId = text;

script.SharedId 类型表示对 DOM Node 的引用,该引用 可在任何 realm 中使用(包括 Sandbox Realms)。

7.6.3.18. script.StackFrame 类型

远程端定义本地端定义

script.StackFrame = {
  columnNumber: js-uint,
  functionName: text,
  lineNumber: js-uint,
  url: text,
}

堆栈跟踪中的帧由一个 StackFrame 对象表示。它具有 url 属性,表示 脚本的 URL;具有 functionName 属性,表示正在 执行的函数的名称;并具有 lineNumbercolumnNumber 属性,表示被执行代码的行号和列号。

7.6.3.19. script.StackTrace 类型

远程端定义本地端定义

script.StackTrace = {
  callFrames: [*script.StackFrame],
}

script.StackTrace 类型表示脚本执行中某一点处的 JavaScript 堆栈。

注:关于如何获取堆栈帧列表的细节, 以及该列表的属性 规定不足,因此这里的细节由实现定义。

假定实现能够生成堆栈 帧列表,它是一个列表,其中每一项对应 JavaScript 调用堆栈中的每个条目,从最近的开始。每个条目都是一个单个堆栈 帧,对应于脚本 script 中语句或表达式的执行,并包含以下字段:

脚本 URL
包含 script 的资源的 URL
函数
正在执行的函数的名称
行号
被执行代码的从零开始的行号,相对于包含 script 的资源顶部。
列号
被执行代码的从零开始的列号,相对于 包含 script 的资源中该行的起始位置。

要使用堆栈帧列表 stack 构造 堆栈跟踪

  1. call frames 为一个新列表。

  2. 对于 stack 中从最近执行的帧开始的每个堆栈帧 frame, 运行以下步骤:

    1. url 为在给定 frame脚本 URLURL 时,运行 URL 序列化器的结果。

    2. frame info 为一个新的映射,其匹配 script.StackFrame 产生式,其中 url 字段设为 urlfunctionName 字段设为 frame函数lineNumber 字段设为 frame行号, 且 columnNumber 字段设为 frame列号

  3. frame info 追加到 call frames

  4. stack trace 为一个新的映射, 其匹配 script.StackTrace 产生式,其中 callFrames 属性设为 call frames

  5. 返回 stack trace

当前堆栈 跟踪 是在给定表示正在运行的 执行上下文的调用堆栈的堆栈 帧列表时,构造堆栈跟踪的结果。

带有异常或类型为 throwCompletion Record exception异常的堆栈 跟踪,由以下给出:

  1. 如果 exception 是作为异常被抛出的值,则令 record 为为抛出 exception 而创建的 Completion Record。否则令 recordexception

  2. stack 为与 创建 record 时所在点的执行相对应的堆栈帧列表

  3. 返回在给定 stack 的情况下构造堆栈跟踪的结果。

7.6.3.20. script.Source 类型

本地端定义

script.Source = {
  realm: script.Realm,
  ? context: browsingContext.BrowsingContext,
  ? userContext: browser.UserContext
}

script.Source 类型表示一个 script.Realm, 以及可选的 browsingContext.BrowsingContext 和相关的 browser.UserContext,脚本相关事件在其中发生。

要在给定 source realm 的情况下获取源
  1. realmsource realmrealm ID

  2. environment settings环境设置对象,其 realm 执行上下文的 Realm 组件为 source realm

  3. 如果 environment settings 具有关联 Document

    1. document 为 environment settings 的关联 Document

    2. navigabledocument节点可导航

    3. 如果 navigable 不为 null,则令 navigable idnavigable可导航 ID

    4. user context idnavigable关联用户上下文用户上下文 ID

    否则,令 navigable 为 null。

  4. source 为一个匹配 script.Source 产生式的映射, 其中 realm 字段设为 realm,如果 navigable 不为 null,则 context 字段设为 navigable id,否则不设置, 并且如果 |navigable 不为 null,则 userContext 字段设为 user context id, 否则不设置。

  5. 返回 source

7.6.3.21. script.Target 类型

远程端定义

script.RealmTarget = {
  realm: script.Realm
}

script.ContextTarget = {
  context: browsingContext.BrowsingContext,
  ? sandbox: text
}

script.Target = (
  script.ContextTarget /
  script.RealmTarget
)

script.Target 类型表示一个要么是 script.Realm,要么是 browsingContext.BrowsingContext 的值。 这在可导航标识符可以代表与该可导航的活动文档 关联的 realm 的情况下很有用。

要在给定 navigable idsandbox 的情况下,从可导航获取 realm
  1. navigable尝试使用 navigable id 获取 可导航的结果。

  2. 如果 sandbox 为 null 或为空字符串:

    1. documentnavigable活动文档

    2. environment settings环境设置对象,其 相关全局对象关联 Documentdocument

    3. realmenvironment settingsrealm 执行上下文的 Realm 组件。

  3. 否则:令 realm尝试在给定 sandboxnavigable 的情况下获取或创建 sandbox realm的结果。

  4. 返回带有数据 realm成功

这使用了错误的 错误码

要在给定 target 的情况下,从 target 获取 realm
  1. 如果 target 匹配 script.ContextTarget 产生式:

    1. sandbox 为 null。

    2. 如果 target 包含 "sandbox",则将 sandbox 设为 target["sandbox"]。

    3. realm 为使用 target["context"] 和 sandbox 从可导航获取 realm的结果。

  2. 否则:

    1. 断言:target 匹配 script.RealmTarget 产生式。

    2. realm idtargetrealm 字段的值。

    3. realm 为给定 realm id获取 realm的结果。

  3. 返回带有数据 realm成功

这使用了错误的 错误码

7.6.4. 命令

7.6.4.1. script.addPreloadScript 命令

script.addPreloadScript 命令添加一个预加载脚本

命令类型
script.AddPreloadScript = (
  method: "script.addPreloadScript",
  params: script.AddPreloadScriptParameters
)

script.AddPreloadScriptParameters = {
  functionDeclaration: text,
  ? arguments: [*script.ChannelValue],
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
  ? sandbox: text
}
返回类型
script.AddPreloadScriptResult = {
  script: script.PreloadScript
}
给定 sessioncommand parameters远端步骤如下:
  1. 如果 command parameters 包含 "userContexts" 且 command parameters 包含 "contexts", 则返回带有错误 码 invalid argument错误

  2. function declarationcommand parametersfunctionDeclaration 字段。

  3. 如果存在,则令 argumentscommand parametersarguments 字段;否则为空列表

  4. user contexts 为一个集合

  5. navigables 为 null。

  6. 如果 command parameterscontexts 字段存在:

    1. navigables 设置为空集合

    2. 对于 command parameters["contexts"] 的每个 navigable id

      1. navigable 为用 navigable id 尝试获取 navigable 的结果。

      2. 如果 navigable 不是顶级可遍历对象,则返回带有错误码 invalid argument错误

      3. navigable 追加到 navigables

  7. 否则,如果 command parameters 包含 userContexts

    1. user contexts 设置为用 command parameters["userContexts"] 创建 集合的结果。

    2. 对于 user contexts 的每个 user context id

      1. user context 设置为用 user context id 获取用户上下文的结果。

      2. 如果 user context 为 null,则返回带有错误码 no such user context错误

  8. 如果存在,则令 sandboxcommand parameters 中 "sandbox" 字段的值;否则为 null。

  9. scriptUUID 的字符串表示。

  10. preload script mapsession预加载脚本映射

  11. preload script map[script] 设置为一个结构,其 function declarationfunction declarationargumentsargumentscontextsnavigablessandboxsandbox,且 user contextsuser contexts

  12. 返回一个新的映射,其匹配 script.AddPreloadScriptResult, 并且 script 字段设置为 script

7.6.4.2. script.disown 命令

script.disown 命令解除对给定句柄的拥有。 这并不保证被句柄引用的对象会被垃圾收集,因为可能存在 其他句柄或强 ECMAScript 引用。

命令类型
script.Disown = (
  method: "script.disown",
  params: script.DisownParameters
)

script.DisownParameters = {
  handles: [*script.Handle]
  target: script.Target;
}
返回类型
script.DisownResult = EmptyResult
带有 command parameters远程端步骤如下:
  1. realm尝试给定 command parameterstarget 字段的值从 target 获取 realm的结果。

  2. handlescommand parametershandles 字段的值。

  3. 对于 handles 的每个 handle id

    1. handle maprealm句柄对象映射

    2. 如果 handle map 包含 handle id,则从 handle map 中移除 handle id

  4. 返回带有数据 null 的成功

7.6.4.3. script.callFunction 命令

script.callFunction 命令在给定 realm 中使用给定实参调用提供的 函数。

RealmInfo 可以是 realm 或可导航。

注:functionDeclaration 中是箭头函数的情况下, this 实参不会影响函数的 this 绑定。

命令类型
script.CallFunction = (
  method: "script.callFunction",
  params: script.CallFunctionParameters
)

script.CallFunctionParameters = {
  functionDeclaration: text,
  awaitPromise: bool,
  target: script.Target,
  ? arguments: [*script.LocalValue],
  ? resultOwnership: script.ResultOwnership,
  ? serializationOptions: script.SerializationOptions,
  ? this: script.LocalValue,
  ? userActivation: bool .default false,
}
返回类型
script.CallFunctionResult = script.EvaluateResult

TODO:添加 timeout 实参, 如 script.evaluate 中所述。

要在给定 realmserialized arguments listsession 的情况下反序列化 实参

  1. deserialized arguments list 为空列表

  2. 对于 serialized arguments list 的每个 serialized argument

    1. deserialized argument尝试 在给定 serialized argumentrealmsession 的情况下 反序列化本地值的结果。

    2. deserialized argument 追加到 deserialized arguments list

  3. 返回带有数据 deserialized arguments list成功

要在给定 function declarationenvironment settingsbase URLoptions 的情况下,求值函数 体

注:function declaration 会被 加上括号并求值。

  1. bypassDisabledScripting 为 true。

  2. parenthesized function declaration 为 «"(", function declaration, ")"» 的拼接结果

  3. function script 为使用 parenthesized function declarationenvironment settingsbase URLoptionsbypassDisabledScripting 创建经典脚本的结果。

  4. 使用 environment settings 准备运行脚本

  5. function body evaluation statusScriptEvaluation(function script 的 record)。

  6. 使用 environment settings 运行脚本后清理

  7. 返回 function body evaluation status

带有 sessioncommand parameters远程端步骤如下:

  1. realm尝试给定 command parameterstarget 字段的值从 target 获取 realm的结果。

  2. realm idrealmrealm ID

  3. environment settings环境设置对象,其 realm 执行上下文的 Realm 组件为 realm

  4. command argumentscommand parametersarguments 字段的值。

  5. deserialized arguments 为空列表

  6. 如果 command arguments 不为 null,则将 deserialized arguments 设为 尝试在给定 realmcommand argumentssession 的情况下 反序列化实参的结果。

  7. this parametercommand parametersthis 字段的值。

  8. this object 为 null。

  9. 如果 this parameter 不为 null,则将 this object 设为 尝试在给定 this parameterrealmsession 的情况下 反序列化本地值的结果。

  10. function declarationcommand parametersfunctionDeclaration 字段的值。

  11. await promisecommand parametersawaitPromise 字段的值。

  12. 如果存在,则令 serialization optionscommand parametersserializationOptions 字段的值, 否则为一个匹配 script.SerializationOptions 产生式、且字段设为其默认值的映射

  13. 如果存在,则令 result ownershipcommand parametersresultOwnership 字段的值;否则为 none

  14. base URLenvironment settingsAPI 基础 URL

  15. options默认脚本 fetch 选项

  16. function body evaluation status 为使用 function declarationenvironment settingsbase URLoptions 求值函数体的 结果。

  17. 如果 function body evaluation status.[[Type]] 为 throw

    1. exception details 为给定 realmfunction body evaluation statusresult ownershipsession 时,获取异常 详情的结果。

    2. 返回一个新的映射,其匹配 script.EvaluateResultException 产生式,且 exceptionDetails 字段设为 exception details

  18. function objectfunction body evaluation status.[[Value]]。

  19. 如果 IsCallable(function object) 为 false

    1. 返回带有错误码 无效参数错误

  20. 如果 command parameters["userActivation"] 为 true,则运行激活通知步骤。

  21. 使用 environment settings 准备运行脚本

  22. evaluation status 设为 Call(function object, this object, deserialized arguments)。

  23. 如果 evaluation status.[[Type]] 为 normal,且 await promisetrue,且 IsPromise(evaluation status.[[Value]]):

    1. evaluation status 设为 Await(evaluation status.[[Value]])。

  24. 使用 environment settings 运行脚本后清理

  25. 如果 evaluation status.[[Type]] 为 throw

    1. exception details 为给定 realmevaluation statusresult ownershipsession 时,获取异常 详情的结果。

    2. 返回一个新的映射,其匹配 script.EvaluateResultException 产生式,且 exceptionDetails 字段设为 exception details

  26. 断言:evaluation status.[[Type]] 为 normal

  27. result 为使用 evaluation status.[[Value]]、serialization optionsresult ownership、 一个新的映射作为序列化内部映射、realmsession 序列化为 远程值的结果。

  28. 返回一个新的映射,其匹配 script.EvaluateResultSuccess 产生式,且 realm 字段设为 realm idresult 字段设为 result

7.6.4.4. script.evaluate 命令

script.evaluate 命令会在给定 realm 中求值所提供的 script。为方便起见,可以提供一个 navigable 来代替 realm;在这种情况下, 所使用的 realm 是该 browsing context 的 active document 的 realm。

该方法返回执行所提供 script 的值,除非它返回一个 promise 且 awaitPromise 为 true,在这种情况下会返回该 promise 的已解决值。

命令类型
script.Evaluate = (
  method: "script.evaluate",
  params: script.EvaluateParameters
)

script.EvaluateParameters = {
  expression: text,
  target: script.Target,
  awaitPromise: bool,
  ? resultOwnership: script.ResultOwnership,
  ? serializationOptions: script.SerializationOptions,
  ? userActivation: bool .default false,
}
返回类型
script.EvaluateResult

TODO:添加 timeout 参数。尚不完全清楚这应该如何工作;在 Chrome 中,timeout 似乎并不适用于 promise resolve 步骤,但 这可能并不是客户端想要的行为。

在给定 sessioncommand parameters 的情况下,远程端步骤如下:

  1. realm尝试给定 command parameterstarget 字段的值从 target 获取 realm的结果。

  2. realm idrealmrealm ID

  3. environment settings环境设置对象,其 realm 执行上下文的 Realm 组件为 realm

  4. sourcecommand parametersexpression 字段的值。

  5. await promisecommand parametersawaitPromise 字段的值。

  6. 如果存在,则令 serialization optionscommand parametersserializationOptions 字段的值, 否则为一个匹配 script.SerializationOptions 产生式、且字段设为其默认值的映射

  7. 如果存在,则令 result ownershipcommand parametersresultOwnership 字段的值;否则为 none

  8. options默认脚本 fetch 选项

  9. base URLenvironment settingsAPI 基础 URL

  10. bypassDisabledScripting 为 true。

  11. script 为使用 sourceenvironment settingsbase URLoptionsbypassDisabledScripting 创建经典脚本的结果。

  12. 如果 command parameters["userActivation"] 为 true,则运行激活通知步骤。

  13. 使用 environment settings 准备运行脚本

  14. evaluation status 设为 ScriptEvaluation(script 的 record)。

  15. 如果 evaluation status.[[Type]] 为 normalawait promise 为 true,且 IsPromise(evaluation status.[[Value]]):

    1. evaluation status 设为 Await(evaluation status.[[Value]])。

  16. 使用 environment settings 运行脚本后清理

  17. 如果 evaluation status.[[Type]] 为 throw

    1. exception details 为使用 realmevaluation statusresult ownershipsession 获取异常 详情的结果。

    2. 返回一个新的映射,其匹配 script.EvaluateResultException 产生式,且 realm 字段设为 realm idexceptionDetails 字段设为 exception details

  18. 断言:evaluation status.[[Type]] 为 normal

  19. result 为使用 evaluation status.[[Value]]、serialization optionsresult ownership、 一个新的映射作为序列化内部映射、realmsession 序列化为 远程值的结果。

  20. 返回一个新的映射,其匹配 script.EvaluateResultSuccess 产生式,且 realm 字段设为 realm idresult 字段设为 result

7.6.4.5. script.getRealms 命令

script.getRealms 命令返回所有 realm 的列表,可选地过滤为特定类型的 realm,或者过滤为与可导航活动文档关联的 realm。

命令类型
script.GetRealms = (
  method: "script.getRealms",
  params: script.GetRealmsParameters
)

script.GetRealmsParameters = {
  ? context: browsingContext.BrowsingContext,
  ? type: script.RealmType,
}
返回类型
script.GetRealmsResult = {
  realms: [*script.RealmInfo]
}
带有 sessioncommand parameters远程端步骤如下:
  1. environment settings 为所有已设置其执行就绪标志环境设置对象组成的列表

  2. 如果 command parameters 包含 context

    1. navigable尝试使用 command parameters["context"] 获取 可导航的结果。

    2. documentnavigable活动文档

    3. navigable environment settings 为一个列表

    4. 对于 environment settings 的每个 settings

      1. 如果满足以下任一条件:

        settings 追加到 navigable environment settings

    5. environment settings 设为 navigable environment settings

  3. realms 为一个列表。

  4. 对于 environment settings 的每个 settings

    1. realm info 为给定 settings获取 realm info的结果。

    2. 如果 command parameters 包含 type,并且 realm info["type"] 不等于 command parameters["type"],则继续

    3. 如果 realm info 不为 null,则将 realm info 追加到 realms

  5. body 为一个匹配 script.GetRealmsResult 产生式的映射, 其中 realms 字段设为 realms

  6. 返回带有数据 body成功

扩展此处以便也 允许 realm 父级,例如用于嵌套 worker?或者获取所有祖先 worker。

我们可能希望拥有 一个比字面匹配更复杂的过滤系统。

7.6.4.6. script.removePreloadScript 命令

script.removePreloadScript 命令移除一个 预加载脚本

命令类型
script.RemovePreloadScript = (
  method: "script.removePreloadScript",
  params: script.RemovePreloadScriptParameters
)

script.RemovePreloadScriptParameters = {
  script: script.PreloadScript
}
返回类型
script.RemovePreloadScriptResult = EmptyResult
在给定 sessioncommand parameters 的情况下,远程端步骤如下:
  1. scriptcommand parameters 中 "script" 字段的值。

  2. preload script mapsession预加载脚本映射

  3. 如果 preload script map包含 script,则返回 带有错误 码 无此脚本错误

  4. preload script map移除 script

  5. 返回 null

7.6.5. 事件

7.6.5.1. script.message 事件
事件类型
script.Message = (
  method: "script.message",
  params: script.MessageParameters
 )

script.MessageParameters = {
  channel: script.Channel,
  data: script.RemoteValue,
  source: script.Source,
}
远程端事件触发器发出脚本 消息步骤, 给定 sessionrealmchannel propertiesmessage
  1. environment settings环境设置对象,其 realm 执行上下文的 Realm 组件为 realm

  2. related navigables 为给定 environment settings获取相关 可导航的结果。

  3. 如果在给定 session、"script.message" 和 related navigables 的情况下事件已 启用

    1. 如果 channel properties 包含 "serializationOptions",则令 serialization optionschannel propertiesserializationOptions 字段的值。否则令 serialization options 为一个映射, 其匹配 script.SerializationOptions 产生式,且 字段设为其默认值。

    2. 如果 channel properties 包含 "ownership",则 令 ownership typechannel properties["ownership"]。 否则令 ownership type 为 "none"。

    3. data 为在给定 messageserialization optionsownership type、 一个新的映射作为序列化 内部映射以及 realm 的情况下序列化为远程值的结果。

    4. source 为使用 realm 获取源的结果。

    5. params 为一个匹配 script.MessageParameters 产生式的映射,其中 channel 字段设为 channel properties["channel"], data 字段设为 data,且 source 字段设为 source

    6. body 为一个匹配 script.Message 产生式的映射,其中 params 字段设为 params

    7. 使用 sessionbody 发出 事件

7.6.5.2. script.realmCreated 事件
事件类型
script.RealmCreated = (
 method: "script.realmCreated",
 params: script.RealmInfo
)
远程端事件触发器如下:

当任何设置 window 环境设置 对象设置 worker 环境设置 对象设置 worklet 环境设置 对象算法被调用时,在返回该设置 对象之前立即:

  1. environment settings 为新创建的环境设置对象

  2. realm info 为给定 environment settings获取 realm info的结果。

  3. 如果 realm info 为 null,则返回。

  4. related navigables 为给定 environment settings获取相关 可导航的结果。

  5. body 为一个匹配 script.RealmCreated 产生式的映射, 其中 params 字段设为 realm info

  6. 对于在给定 "script.realmCreated" 和 related navigables 的情况下,事件已启用的会话集合 中的每个 session

    1. 使用 sessionbody 发出 事件

带有订阅优先级 2,在给定 sessionnavigablesinclude global 的情况下,远程端订阅步骤如下:

  1. environment settings 为所有已设置其执行就绪标志环境设置对象的列表。

  2. 对于 environment settings 的每个 settings

    1. related navigables 为一个新集合

    2. 如果 settings相关全局对象关联 Document是一个Document

      1. navigablesettings相关全局对象关联 Document节点可导航

      2. 如果 navigable 为 null,则继续。

      3. top-level traversiblenavigable顶级可遍历

      4. 如果 top-level traversible 不在 navigables 中,则继续。

      5. top-level traversible 追加到 related navigables

      否则,如果 include global 为 false,则继续。

    3. realm info 为给定 settings获取 realm info的结果。

    4. 如果 realm info 为 null,则继续。

    5. body 为一个匹配 script.RealmCreated 产生式的映射,其中 params 字段设为 realm info

    6. 如果在给定 session、 "script.realmCreated" 和 related navigables 的情况下事件 已启用

      1. 使用 sessionbody 发出 事件

这里的顺序 是否应更好地定义?

7.6.5.3. script.realmDestroyed 事件
事件类型
script.RealmDestroyed = (
  method: "script.realmDestroyed",
  params: script.RealmDestroyedParameters
)

script.RealmDestroyedParameters = {
  realm: script.Realm
}

远程端事件触发器如下:
定义以下带有 document卸载文档清理步骤
  1. related navigables 为空集合

  2. document可导航追加到 related navigables

  3. 对于 documentworklet 全局作用域中的每个 worklet global scope

    1. realmworklet global scope相关 Realm

    2. realm idrealmrealm ID

    3. params 为一个匹配 script.RealmDestroyedParameters 产生式的映射,其中 realm 字段设为 realm id

    4. body 为一个匹配 script.RealmDestroyed 产生式的映射,其中 params 字段设为 params

    5. 对于在给定 "script.realmDestroyed" 和 related navigables 的情况下,事件已启用的会话集合 中的每个 session

      1. 使用 sessionbody 发出 事件

  4. environment settings环境设置对象,其 相关全局对象关联 Documentdocument

  5. realmenvironment settingsrealm 执行上下文的 Realm 组件。

  6. realm idrealmrealm ID

  7. params 为一个匹配 script.RealmDestroyedParameters 产生式的映射, 其中 realm 字段设为 realm id

  8. body 为一个匹配 script.RealmDestroyed 产生式的映射, 其中 params 字段设为 params

  9. 对于在给定 "script.realmDestroyed" 和 related navigables 的情况下,事件已启用的会话集合 中的每个 session

    1. 使用 sessionbody 发出 事件

每当一个 worker 事件循环 event loop 被销毁时,无论是因为 worker 到达其生命周期末尾,还是通过终止 worker算法提前终止:

  1. environment settings环境设置对象,对于该对象, event loop负责事件循环

  2. related navigables 为给定 environment settings获取相关 可导航的结果。

  3. realmenvironment settings环境设置对象的 Realm

  4. realm idrealmrealm ID

  5. params 为一个匹配 script.RealmDestroyedParameters 产生式的映射, 其中 realm 字段设为 realm id

  6. body 为一个匹配 script.RealmDestroyed 产生式的映射, 其中 params 字段设为 params

7.7. storage 模块

storage 模块包含与存储相关的功能和 事件。

存储分区 是一个命名空间,用户代理可以在其中 组织持久数据,例如 cookies 和本地存储。

存储分区 键是一个映射,它唯一标识一个存储分区

7.7.1. 定义

远程端定义

StorageCommand = (
  storage.DeleteCookies //
  storage.GetCookies //
  storage.SetCookie
)

本地端定义

StorageResult = (
  storage.DeleteCookiesResult /
  storage.GetCookiesResult /
  storage.SetCookieResult
)

7.7.2. 类型

7.7.2.1. storage.PartitionKey 类型

本地端定义

storage.PartitionKey = {
  ? userContext: text,
  ? sourceOrigin: text,
  Extensible,
}

storage.PartitionKey 类型表示一个存储分区键

以下标准存储分区键 属性表 枚举了具有众所周知含义的属性,远程端 可以 选择支持这些属性。实现可以定义额外的扩展存储分区键属性

属性 定义
"userContext" 一个用户上下文 ID
"sourceOrigin" 可以访问该存储分区的资源的源序列化

远程端可以支持任意数量的扩展存储分区键 属性。为了避免与其他实现冲突,这些 属性必须以厂商和用户代理的唯一标识符开头, 后跟 U+003A (:)。

远程端具有一个存储分区 键属性的默认值映射,其中包含零个或多个条目。每个键都必须是 标准存储分区键 属性表的成员,其中 存储分区 键对应于标准存储分区,或者在其不对应时,是一个 扩展存储分区键属性, 并且值 表示在用户未提供显式值时将使用的该分区键的默认值。 精确的条目由实现定义,并由实现采用的存储分区方式决定。

远程端具有一个必需分区键 属性列表,其中包含零个或多个条目。每个键都必须是 标准存储分区键 属性表的成员,其中 存储分区 键对应于标准存储分区,或者在其不对应时,是一个 扩展存储分区键属性。 精确的 条目由实现定义,并由实现采用的存储 分区方式决定。此列表仅包含没有可用默认值的分区 键。因此,该列表不得与存储分区 键属性的默认值的键共享任何 条目。

要在给定 filter 的情况下反序列化 过滤器
  1. deserialized filter 为空映射

  2. 对于 filter 中的每个 namevalue

    1. deserialized name 为在 cookie 转换表中与 JSON 键 name 对应的字段名称。

    2. 如果 name 是 "value",则将 deserialized value 设为 使用 value 反序列化协议字节的结果, 否则令 deserialized valuevalue

    3. deserialized filter[deserialized name] 设置deserialized value

  3. 返回 deserialized filter

给定 partition spec,要展开 存储分区规范
  1. 如果 partition spec 为 null:

    1. partition spec 设置为空映射

  2. 否则,如果 partition spec["type"] 为 "context":

    1. navigable 为给定 partition spec["context"] 尝试 获取 navigable的结果。

    2. partition keynavigable关联存储分区

    3. 返回带有数据 partition key成功

  3. partition key 为空映射

  4. 对于存储分区键属性的默认值中的每个 namedefault value

    1. valuepartition spec[name](如果它存在),否则为 default value

    2. partition key[name] 设置value

  5. 对于远端的必需分区键属性中的每个 name

    1. 如果 partition spec[name] 存在

      1. partition key][name] 设置partition spec[name]。

    2. 否则:

      1. 返回带有错误码 underspecified storage partition错误

  6. 返回带有数据 partition key成功

要在给定 storage partition key 的情况下获取 cookie 存储
  1. 如果 storage partition key 唯一标识一个现有的存储分区

    1. store 为该存储分区cookie 存储

    2. 返回带有数据 store成功

  2. 返回带有错误 码 无此存储分区错误

要在给定 stored cookiefilter 的情况下匹配 cookie
  1. 对于 filter 中的每个 namevalue

    1. 如果 stored cookie[name] 不等于 value

      1. 返回 false。

  2. 返回 true。

要在给定 cookie storefilter 的情况下获取匹配的 cookies
  1. cookies 为一个新列表。

  2. deserialized filter 设为使用 filter 反序列化过滤器的结果。

  3. 对于 cookie store 中的每个 stored cookie

    1. 如果使用 stored cookiedeserialized filter 匹配 cookie的结果为 true:

      1. stored cookie 追加到 cookies

  4. 返回 cookies

7.7.3. 命令

7.7.3.1. storage.getCookies 命令

storage.getCookies 命令检索零个或多个与一组提供的 参数匹配cookies

命令类型
storage.GetCookies = (
  method: "storage.getCookies",
  params: storage.GetCookiesParameters
)


storage.CookieFilter = {
  ? name: text,
  ? value: network.BytesValue,
  ? domain: text,
  ? path: text,
  ? size: js-uint,
  ? httpOnly: bool,
  ? secure: bool,
  ? sameSite: network.SameSite,
  ? expiry: js-uint,
  Extensible,
}

storage.BrowsingContextPartitionDescriptor = {
  type: "context",
  context: browsingContext.BrowsingContext
}

storage.StorageKeyPartitionDescriptor = {
  type: "storageKey",
  ? userContext: text,
  ? sourceOrigin: text,
  Extensible,
}

storage.PartitionDescriptor = (
  storage.BrowsingContextPartitionDescriptor /
  storage.StorageKeyPartitionDescriptor
)

storage.GetCookiesParameters = {
  ? filter: storage.CookieFilter,
  ? partition: storage.PartitionDescriptor,
}
返回类型
storage.GetCookiesResult = {
  cookies: [*network.Cookie],
  partitionKey: storage.PartitionKey,
}
带有 sessioncommand parameters远程端步骤如下:
  1. 如果存在,则令 filtercommand parametersfilter 字段的值; 否则为空映射

  2. 如果存在,则令 partition speccommand parameterspartition 字段的值;否则为 null。

  3. partition key尝试使用 partition spec 展开存储分区规范的结果。

  4. store尝试使用 partition key 获取 cookie 存储的结果。

  5. cookies 为使用 storefilter 获取匹配的 cookies的结果。

  6. serialized cookies 为一个新列表。

  7. 对于 cookies 中的每个 cookie

    1. serialized cookie 为给定 cookie序列化 cookie的结果。

    2. serialized cookie 追加到 serialized cookies

  8. body 为一个匹配 storage.GetCookiesResult 产生式的映射, 其中 cookies 字段设为 serialized cookies,且 partitionKey 字段设为 partition key

  9. 返回带有数据 body成功

7.7.3.2. storage.setCookie 命令

storage.setCookie 命令在 cookie 存储中创建一个新的 cookie, 替换该存储中根据 [COOKIES] 匹配的任何 cookie。

命令类型
storage.SetCookie = (
  method: "storage.setCookie",
  params: storage.SetCookieParameters,
)


storage.PartialCookie = {
  name: text,
  value: network.BytesValue,
  domain: text,
  ? path: text,
  ? httpOnly: bool,
  ? secure: bool,
  ? sameSite: network.SameSite,
  ? expiry: js-uint,
  Extensible,
}

storage.SetCookieParameters = {
  cookie: storage.PartialCookie,
  ? partition: storage.PartitionDescriptor,
}
返回类型
storage.SetCookieResult = {
  partitionKey: storage.PartitionKey
}
带有 sessioncommand parameters远程端步骤如下:
  1. cookie speccommand parameterscookie 字段的值。

  2. 如果存在,则令 partition speccommand parameterspartition 字段的值;否则为 null。

  3. partition key尝试使用 partition spec 展开存储分区规范的结果。

  4. store尝试使用 partition key 获取 cookie 存储的结果。

  5. deserialized value 为使用 cookie spec["value"] 反序列化协议字节的结果。

  6. 使用cookie 名称 cookie spec["name"]、 cookie 值 deserialized valuecookie 域 cookie spec["domain"],以及cookie 转换表中列出的 以下 cookie 概念的属性-值列表,在 store创建 cookie

    Cookie 路径

    如果 cookie spec["path"] 存在,则为它;否则为 "/"。

    Cookie 仅安全

    如果 cookie spec["secure"] 存在,则为它;否则为 false。

    Cookie 仅 HTTP

    如果 cookie spec["httpOnly"] 存在,则为它;否则为 false。

    Cookie 到期时间

    如果 cookie spec["expiry"] 存在,则为它;否则保持未设置, 以表示这是一个会话 cookie。

    注:cookie 的到期值 可能会由远程端根据 Cookie 生命周期限制来限制。

    Cookie same site

    如果 cookie spec["sameSite"] 存在,则为它;否则保持未设置, 以表示未定义 same site 策略。

    如果此步骤在未向 cookie 存储插入 cookie 的情况下中止,则返回 带有错误 码 无法设置 cookie错误

  7. body 为一个匹配 storage.SetCookieResult 产生式的映射, 其中 partitionKey 字段设为 partition key

  8. 返回带有数据 body成功

7.7.3.3. storage.deleteCookies 命令

storage.deleteCookies 命令移除零个或多个与一组提供的 参数匹配cookies

命令类型
storage.DeleteCookies = (
  method: "storage.deleteCookies",
  params: storage.DeleteCookiesParameters,
)

storage.DeleteCookiesParameters = {
  ? filter: storage.CookieFilter,
  ? partition: storage.PartitionDescriptor,
}
返回类型
storage.DeleteCookiesResult = {
  partitionKey: storage.PartitionKey
}
带有 sessioncommand parameters远程端步骤如下:
  1. 如果存在,则令 filtercommand parametersfilter 字段的值; 否则为空映射

  2. 如果存在,则令 partition speccommand parameterspartition 字段的值;否则为 null。

  3. partition key尝试使用 partition spec 展开存储分区规范的结果。

  4. store尝试使用 partition key 获取 cookie 存储的结果。

  5. cookies 为使用 storefilter 获取匹配的 cookies的结果。

  6. 对于 cookies 中的每个 cookie

    1. store 中移除 cookie

  7. body 为一个匹配 storage.DeleteCookiesResult 产生式的映射, 其中 partitionKey 字段设为 partition key

  8. 返回带有数据 body成功

7.8. log 模块

log 模块包含与日志记录相关的功能和事件。

BiDi 会话具有一个日志事件缓冲区,它 是一个从 可导航 ID到该上下文中尚未 发出的日志事件列表的映射。用户代理可以对此缓冲区施加最大大小,但须满足以下条件: 如果事件 A 和 B 发生在同一上下文中,且 A 发生在 B 之前,并且二者都被添加到缓冲区, 则 B 的条目不得在 A 的条目之前被移除。

要在给定 sessionnavigablesevent 的情况下缓冲日志 事件

  1. buffersession日志事件缓冲区

  2. navigable ids 为一个新列表。

  3. 对于 navigables 的每个 navigable

    1. navigable可导航 ID追加到 navigable ids

  4. 对于 navigable ids 中的每个 navigable id

    1. other navigables 为空列表

    2. 对于 navigable ids 中的每个 other id

    3. 如果 other id 不等于 navigable id,则将 other id 追加到 other navigables

    4. 如果 buffer 不包含 navigable id,则令 buffer[navigable id] 为一个 新列表。

    5. 将 (event, other navigables) 追加到 buffer[navigable id]。

注:我们在此存储其他可导航,以便 每个事件只发出 一次。实践中,这只与可以关联到 多个可导航的 worker 有关。

我们是否希望以 浏览上下文还是顶级可遍历作为键? 区别在于,如果事件发生在一个 frame 中,而该 frame 在本地端订阅顶级可导航的日志事件之前发生导航,会出现什么情况。

7.8.1. 定义

本地端定义

LogEvent = (
  log.EntryAdded
)

7.8.2. 类型

7.8.2.1. log.LogEntry

本地端定义

log.Level = "debug" / "info" / "warn" / "error"

log.Entry = (
  log.GenericLogEntry /
  log.ConsoleLogEntry /
  log.JavascriptLogEntry
)

log.BaseLogEntry = (
  level: log.Level,
  source: script.Source,
  text: text / null,
  timestamp: js-uint,
  ? stackTrace: script.StackTrace,
)

log.GenericLogEntry = {
  log.BaseLogEntry,
  type: text,
}

log.ConsoleLogEntry = {
  log.BaseLogEntry,
  type: "console",
  method: text,
  args: [*script.RemoteValue],
}

log.JavascriptLogEntry = {
  log.BaseLogEntry,
  type: "javascript",
}

每个日志事件都由一个 log.Entry 对象表示。它具有一个 type 属性,表示所添加日志条目的类型;一个 level 属性,表示严重性;一个 source 属性,表示日志条目的来源;一个 text 属性, 带有日志消息字符串本身;以及一个 timestamp 属性, 对应于日志条目生成的时间。log.Entry 的特定变体 用于表示来自不同来源的日志,并 提供特定于条目类型的附加字段。

7.8.3. 事件

7.8.3.1. log.entryAdded 事件
事件类型
log.EntryAdded = (
 method: "log.entryAdded",
 params: log.Entry,
)

远程端事件触发器如下:

定义以下带有 methodargsoptionsconsole 步骤

  1. 对于活动 BiDi 会话中的每个 session

    1. 如果 method 是 "error" 或 "assert",则令 level 为 "error"。如果 method 是 "debug" 或 "trace", 则令 level 为 "debug"。如果 method 是 "warn",则令 level 为 "warn"。否则令 level 为 "info"。

    2. timestamp 为一个表示当前 UTC 日期和时间的时间值

    3. text 为空字符串。

    4. 如果 Type(args[0]) 为 String,并且 args[0] 包含一个 格式化说明符,则令 formatted argsFormatter(args)。否则 令 formatted argsargs

      注:console 规范中 formatter 操作的规定不足, 不同实现之间格式化可能不一致。

    5. 对于 formatted args 中的每个 arg

      1. 如果 arg 不是 args 中的第一项,则向 text 追加一个 U+0020 SPACE。

      2. 如果 arg 是一个原始 ECMAScript 值,则将 ToString(arg) 追加到 text。否则向 text 追加一个由实现定义的字符串。

    6. realm当前 Realm Recordrealm ID

    7. serialized args 为一个新列表。

    8. serialization options 为一个匹配 script.SerializationOptions 产生式、且字段设为 其默认值的映射

    9. 对于 args 的每个 arg

      1. serialized arg 为使用 arg 作为 value、serialization optionsnone 作为 ownership type、一个新的映射作为 serialization internal map、 realmsession 序列化为远程值的结果。

      2. serialized arg 添加到 serialized args

    10. source 为给定当前 Realm Record获取源的结果。

    11. stack当前堆栈跟踪

    12. entry 为一个匹配 log.ConsoleLogEntry 产生式的映射, 其中 level 字段设为 leveltext 字段设为 texttimestamp 字段设为 timestampstackTrace 字段设为 stackmethod 字段设为 methodsource 字段设为 source, 且 args 字段设为 serialized args

    13. body 为一个匹配 log.EntryAdded 产生式的映射,其中 params 字段设为 entry

    14. settings当前设置对象

    15. related navigables 为给定 settings获取相关 可导航的结果。

    16. 如果在给定 session、"log.entryAdded" 和 related navigables 的情况下事件 已启用,则使用 sessionbody 发出事件

      否则,使用 sessionrelated browsing contextsbody 缓冲日志事件

定义以下带有实参 scriptline numbercolumn numbermessagehandled错误报告步骤

  1. 如果 handled 为 true,则返回。

  2. settingsscript设置对象

  3. timestamp 为一个表示当前 UTC 日期和时间的时间值

  4. stack 为带有对应于正在报告的错误的 异常时的异常的堆栈跟踪

  5. source 为给定当前 Realm Record获取源的结果。

  6. entry 为一个匹配 log.JavascriptLogEntry 产生式的映射, 其中 level 设为 "error",text 设为 messagesource 设为 sourcetimestamp 设为 timestamp,且 stackTrace 字段设为 stack

  7. body 为一个匹配 log.EntryAdded 产生式的映射, 其中 params 字段设为 entry

  8. related navigables 为给定 settings获取相关 可导航的结果。

  9. 对于活动 BiDi 会话中的每个 session

    1. 如果在给定 session、"log.entryAdded" 和 related navigables 的情况下事件 已启用,则使用 sessionbody 发出事件

      否则,使用 sessionrelated browsing contextsbody 缓冲日志事件

还有更多内容 需要日志记录。CDP 有 LogEntryAdded 类型 xml、 javascript、network、storage、appcache、rendering、security、deprecation、 worker、violation、intervention、recommendation、other。这些是对由不同方法表示的 js 异常和 console API 类型的补充。

允许 由实现定义的日志类型

带有订阅优先级 10,在给定 sessionnavigablesinclude global 的情况下,远程端订阅步骤如下:

  1. 对于 session日志事件 缓冲区中的每个 navigable idevents

    1. maybe context 为给定 navigable id获取可导航的结果。

    2. 如果 maybe context 是一个错误, 则从日志事件缓冲区中移除 navigable id, 并继续。

    3. navigablemaybe context 的数据

    4. top level navigablenavigable顶级可遍历

    5. 如果 include global 为 true 且 top level navigable 不在 navigables 中, 或者如果 include global 为 false 且 top level navigablenavigables 中:

      1. 对于 events 中的每个 (event, other navigables):

        1. 使用 sessionevent 发出事件

        2. 对于 other navigables 中的每个 other context id

          1. 如果日志事件缓冲区包含 other context id,则从日志事件 缓冲区[other context id] 中移除 event

7.9. input 模块

input 模块包含用于 模拟用户输入的功能。

7.9.1. 定义

远程端定义

InputCommand = (
  input.PerformActions //
  input.ReleaseActions //
  input.SetFiles
)
InputResult = (
  input.PerformActionsResult /
  input.ReleaseActionsResult /
  input.SetFilesResult
)

本地端定义

InputEvent = (
  input.FileDialogOpened
)

7.9.2. 类型

7.9.2.1. input.ElementOrigin

input.ElementOrigin 类型表示一个将被用作坐标原点的 Element

input.ElementOrigin = {
  type: "element",
  element: script.SharedReference
}
给定 objectis input.ElementOrigin 步骤如下:
  1. 如果 object 是一个匹配 input.ElementOrigin 产生式的映射, 则返回 true。

  2. 返回 false。

要在给定 session 的情况下,获取来自 input.ElementOrigin 的 Element 步骤
  1. 返回以下步骤,给定 originnavigable

    1. 断言:origin 匹配 input.ElementOrigin

    2. documentnavigable活动文档

    3. referenceorigin["element"]

    4. environment settings环境设置对象,其 相关全局对象关联 Documentdocument

    5. realmenvironment settingsrealm 执行上下文的 Realm 组件。

    6. element尝试使用 referencerealmsession 反序列化远程引用的结果。

    7. 如果 element 未实现 Element, 则返回带有错误码 无此元素错误

    8. 返回带有数据 element成功

7.9.3. 命令

7.9.3.1. input.performActions 命令

input.performActions 命令会执行指定的用户输入 actions 序列。

注:有关此命令行为的详细描述,请参见 actions section of [WEBDRIVER]

命令类型
input.PerformActions = (
  method: "input.performActions",
  params: input.PerformActionsParameters
)

input.PerformActionsParameters = {
  context: browsingContext.BrowsingContext,
  actions: [*input.SourceActions]
}

input.SourceActions = (
  input.NoneSourceActions /
  input.KeySourceActions /
  input.PointerSourceActions /
  input.WheelSourceActions
)

input.NoneSourceActions = {
  type: "none",
  id: text,
  actions: [*input.NoneSourceAction]
}

input.NoneSourceAction = input.PauseAction

input.KeySourceActions = {
  type: "key",
  id: text,
  actions: [*input.KeySourceAction]
}

input.KeySourceAction = (
  input.PauseAction /
  input.KeyDownAction /
  input.KeyUpAction
)

input.PointerSourceActions = {
  type: "pointer",
  id: text,
  ? parameters: input.PointerParameters,
  actions: [*input.PointerSourceAction]
}

input.PointerType = "mouse" / "pen" / "touch"

input.PointerParameters = {
  ? pointerType: input.PointerType .default "mouse"
}

input.PointerSourceAction = (
  input.PauseAction /
  input.PointerDownAction /
  input.PointerUpAction /
  input.PointerMoveAction
)

input.WheelSourceActions = {
  type: "wheel",
  id: text,
  actions: [*input.WheelSourceAction]
}

input.WheelSourceAction = (
  input.PauseAction /
  input.WheelScrollAction
)

input.PauseAction = {
  type: "pause",
  ? duration: js-uint
}

input.KeyDownAction = {
  type: "keyDown",
  value: text
}

input.KeyUpAction = {
  type: "keyUp",
  value: text
}

input.PointerUpAction = {
  type: "pointerUp",
  button: js-uint,
}

input.PointerDownAction = {
  type: "pointerDown",
  button: js-uint,
  input.PointerCommonProperties
}

input.PointerMoveAction = {
  type: "pointerMove",
  x: float,
  y: float,
  ? duration: js-uint,
  ? origin: input.Origin,
  input.PointerCommonProperties
}

input.WheelScrollAction = {
  type: "scroll",
  x: js-int,
  y: js-int,
  deltaX: js-int,
  deltaY: js-int,
  ? duration: js-uint,
  ? origin: input.Origin .default "viewport",
}

input.PointerCommonProperties = (
  ? width: js-uint,
  ? height: js-uint,
  ? pressure: (0.0..1.0),
  ? tangentialPressure: (-1.0..1.0),
  ? twist: (0..359),
  ; 0 .. Math.PI / 2
  ? altitudeAngle: (0.0..1.5707963267948966),
  ; 0 .. 2 * Math.PI
  ? azimuthAngle: (0.0..6.283185307179586),
)

input.Origin = "viewport" / "pointer" / input.ElementOrigin

带有 sessioncommand parameters远程端步骤如下:

  1. navigable idcommand parameterscontext 字段的值。

  2. navigable尝试使用 navigable id 获取 可导航的结果。

  3. input state 为使用 sessionnavigable顶级可遍历获取输入状态的结果。

  4. actions options 为一个新的actions options,其中 is element origin 步骤设为 is input.ElementOrigin,且 get element origin 步骤设为给定 session获取来自 input.ElementOrigin 的 Element 步骤的结果。

  5. actions by tick 为使用 input statecommand parametersactions options 提取动作序列的尝试结果。

  6. 尝试使用 input stateactions by ticknavigableactions options 分派动作

  7. 返回带有数据 null 的成功

7.9.3.2. input.releaseActions 命令

input.releaseActions 命令重置与当前会话关联的输入 状态。

命令类型
input.ReleaseActions = (
  method: "input.releaseActions",
  params: input.ReleaseActionsParameters
)

input.ReleaseActionsParameters = {
  context: browsingContext.BrowsingContext,
}
返回类型
input.ReleaseActionsResult = EmptyResult

给定 sessioncommand parameters远程端步骤如下:

  1. navigable idcommand parameterscontext 字段的值。

  2. navigable尝试使用 navigable id 获取 可导航的结果。

  3. top-level traversablenavigable顶级可遍历

  4. input state 为使用 sessiontop-level traversable 获取输入状态的结果。

  5. actions options 为一个新的actions options,其中 is element origin 步骤设为 is input.ElementOrigin,且 get element origin 步骤设为给定 session获取来自 input.ElementOrigin 的 Element 步骤

  6. undo actionsinput state输入取消列表的逆序。

  7. 尝试使用 undo actions、0、navigableactions options 分派 tick 动作

  8. 使用 sessiontop-level traversable 重置输入状态

  9. 返回带有数据 null 的成功

7.9.3.3. input.setFiles 命令

input.setFiles 命令将给定 input 元素(其 type 为 file)的 files 属性 设为一组文件路径。

命令类型
input.SetFiles = (
  method: "input.setFiles",
  params: input.SetFilesParameters
)

input.SetFilesParameters = {
  context: browsingContext.BrowsingContext,
  element: script.SharedReference,
  files: [*text]
}
返回类型
input.SetFilesResult = EmptyResult

给定 sessioncommand parameters远程端步骤如下:

  1. navigable idcommand parameters["context"] 字段的值。

  2. navigable尝试使用 navigable id 获取 可导航的结果。

  3. documentnavigable活动文档

  4. environment settings环境设置对象,其 相关全局对象关联 Documentdocument

  5. realmenvironment settingsrealm 执行上下文的 Realm 组件。

  6. element尝试使用 command parameters["element"]、realmsession 反序列化远程引用的结果。

  7. 如果 element 未实现 Element, 则返回带有错误 码 无此元素错误

  8. 如果 element 未实现 HTMLInputElementelementtype 不处于文件上传状态,或者 element禁用, 则返回带有错误 码 无法设置文件输入错误

  9. 如果 files大小大于 1,且 elementmultiple 属性未设置,则返回带有错误码 无法设置文件输入错误

  10. filescommand parameters["files"] 字段的值。

  11. selected fileselement已选文件

  12. 如果 filesselected files交集大小等于 selected files大小,并且等于 files大小,则在用户交互任务源上,给定 element排入一个元素任务,以在 element 上触发一个名为 cancel 的事件, 其 bubbles 属性初始化为 true。

    注:浏览器中的取消通常 由文件选择的变化来确定。换言之,如果没有变化,则会发送一个 "cancel" 事件。

  13. 否则,使用 files 作为用户的选择,更新文件选择

  14. 如果由于任何原因,远程端无法将 element已选文件设置为 files 中给出路径的文件, 则返回带有错误码 不支持的操作的错误。

    注:例如,远程端可能无法将已选文件设置为文件系统中 当前不存在的文件。

  15. 返回带有数据 null 的成功

7.9.4. 事件

7.9.4.1. input.fileDialogOpened 事件
事件类型
input.FileDialogOpened = (
   method: "input.fileDialogOpened",
   params: input.FileDialogInfo
)

input.FileDialogInfo = {
   context: browsingContext.BrowsingContext,
   ? userContext: browser.UserContext,
   ? element: script.SharedReference,
   multiple: bool,
}

WebDriver BiDi 文件选择器选项是一个结构体,具有一个名为 multiple,其为 boolean。

远程端事件触发器是 给定元素 element 和 可选的 WebDriver BiDi 文件选择器选项 file picker options(默认值:null)的 WebDriver BiDi 文件对话框已打开步骤:

注:不同于其他用户提示处理器,默认 行为是允许打开文件对话框。

  1. navigableelement节点文档可导航

  2. navigable idnavigable可导航 ID

  3. user context idnavigable关联用户 上下文用户 上下文 ID

  4. multiplefalse

  5. 如果 element 不为 null,且 elementmultiple 属性已设置, 则将 multiple 设为 true

  6. 如果 file picker options 不为 null,且 file picker optionsmultiple 为 true,则将 multiple 设为 true

  7. related navigables 为一个包含 navigable集合

  8. 对于在给定 "input.fileDialogOpened" 和 related navigables 的情况下事件已启用的会话集合中的每个 session

    1. params 为一个匹配 input.FileDialogInfo 产生式的映射,其中 context 字段设为 navigable iduserContext 字段设为 user context id,且 multiple 字段设为 multiple

    2. 如果 element 不为 null:

      1. shared id 为使用 elementsession 获取 节点的共享 ID

      2. params["element"] 设为 shared id

    3. body 为一个匹配 input.fileDialogOpened 产生式的映射,其中 params 字段设为 params

    4. 使用 sessionbody 发出 事件

  9. dismissed 为 false。

  10. 对于活动 BiDi 会话中的每个 session

    1. user prompt handlersession用户提示处理器

    2. 如果 user prompt handler 不为 null:

    3. 断言:user prompt handler 是一个映射

    4. 如果 user prompt handler 包含 "file":

      1. 如果 user prompt handler["file"] 不等于 "ignore",则将 dismissed 设为 true。

    5. 否则,如果 user prompt handler 包含 "default",且 user prompt handler["default"] 不等于 "ignore",则将 dismissed 设为 true。

  11. 返回 dismissed

7.10. webExtension 模块

webExtension 模块包含用于 管理 Web 扩展以及与其交互的功能。

7.10.1. 定义

远程端定义

WebExtensionCommand = (
  webExtension.Install //
  webExtension.Uninstall
)

本地端定义

WebExtensionResult = (
  webExtension.InstallResult /
  webExtension.UninstallResult
)

7.10.2. 类型

7.10.2.1. webExtension.Extension 类型
webExtension.Extension = text

webExtension.Extension 类型表示远程端中的 Web 扩展 ID。

7.10.3. 命令

7.10.3.1. webExtension.install 命令

webExtension.install 命令在远程端中安装一个 Web 扩展。

命令类型
webExtension.Install = (
   method: "webExtension.install",
   params: webExtension.InstallParameters
)

webExtension.InstallParameters = {
   extensionData: webExtension.ExtensionData,
}

webExtension.ExtensionData = (
   webExtension.ExtensionArchivePath /
   webExtension.ExtensionBase64Encoded /
   webExtension.ExtensionPath
)

webExtension.ExtensionPath = {
   type: "path",
   path: text,
}

webExtension.ExtensionArchivePath = {
   type: "archivePath",
   path: text,
}

webExtension.ExtensionBase64Encoded = {
   type: "base64",
   value: text,
}
返回类型
webExtension.InstallResult = {
  extension: webExtension.Extension
}
要在给定 bytes 的情况下提取 zip 归档
  1. 执行由实现定义的步骤,使用 zip 压缩算法解码 bytes。TODO:为 zip 解码寻找更好的引用。

  2. 如果上一步失败(例如因为 bytes 未表示有效的 zip 压缩 数据),则返回带有错误码 无效 Web 扩展错误。否则令 entry 为一个包含已提取文件系统条目的目录条目

  3. 返回 entry

要在给定 extension data spec 的情况下展开 Web 扩展 数据规范
  1. typeextension data spec["type"]。

  2. 如果不支持使用 type 安装 Web 扩展,则返回带有错误 码 不支持的操作错误

  3. 在以下条件及关联步骤列表中,运行首个关联条件为 true 的步骤集:

    type 是字符串 "path"
    1. pathextension data spec["path"]。

    2. locator 为一个目录定位器,其路径path,且对应于文件 系统的根。

    3. entry 为给定 locator定位条目的结果。

    type 是字符串 "archivePath"
    1. archive pathextension data spec["path"]。

    2. locator 为一个文件定位器,其路径archive path,且对应于文件 系统的根。

    3. archive entry 为给定 locator定位条目的结果。

    4. 如果 archive entry 为 null,则返回 null。

    5. bytesarchive entry二进制数据

    6. entry尝试给定 bytes 提取 zip 归档的结果。

    type 是字符串 "base64"
    1. bytes 为对 extension data spec["value"] 进行 forgiving-base64 解码的结果。

    2. 如果 bytes 为 failure,则返回 null。

    3. entry尝试给定 bytes 提取 zip 归档的结果。

  4. 返回 entry

带有 command parameters远程端步骤如下:
  1. 如果不支持安装 Web 扩展,则返回带有错误 码 不支持的操作错误

  2. extension data speccommand parameters["extensionData"]。

  3. extension directory entry尝试使用 extension data spec 展开 Web 扩展数据规范的结果。

  4. 如果 extension directory entry 为 null,则返回带有错误码 无效 Web 扩展错误

  5. 执行由实现定义的步骤,从 extension directory entry 安装 Web 扩展。如果这失败,则返回带有错误码 无效 Web 扩展错误。否则令 extension id 为新 安装的 Web 扩展的唯一标识符。

  6. result 为一个匹配 webExtension.InstallResult 产生式的映射, 其 extension 字段设为 extension id

  7. 返回带有数据 result成功

注:浏览器默认可能仅临时安装 Web 扩展, 以便 它们将在下次关闭期间自动卸载。

7.10.3.2. webExtension.uninstall 命令

webExtension.uninstall 命令为 远程端卸载一个 Web 扩展。

命令类型
webExtension.Uninstall = (
   method: "webExtension.uninstall",
   params: webExtension.UninstallParameters
)

webExtension.UninstallParameters = {
   extension: webExtension.Extension,
}
返回类型
webExtension.UninstallResult = EmptyResult
带有 command parameters远程端步骤如下:
  1. extensioncommand parameters["extension"]。

  2. 如果远程端没有 ID 等于 extension 的 Web 扩展,则返回带有错误码 无此 Web 扩展错误

  3. 执行任何由实现定义的步骤,从远程端移除该 Web 扩展。如果这失败,则返回带有错误码 未知错误错误

  4. 返回带有数据 null 的成功

8. 对其他规范的补丁

本规范要求对外部规范进行一些更改,以提供必要的 集成点。假定这些补丁将作为标准化流程的一部分提交到其他规范中。

8.1. HTML

report an error 算法被修改,在末尾增加一个步骤:

  1. 调用外部规范中定义的任何 error reporting steps,传入 scriptlinecolmessage,以及如果错误已 处理则为 true,否则为 false。

8.2. Console

其他规范可以定义 console steps

  1. 在以 参数 nameprinterArgsoptions(如果未提供该参数则为 undefined)调用 Printer 操作时,调用 外部规范中定义的任何 console steps,并传入参数 nameprinterArgsoptions

8.3. CSS

8.3.1. 确定设备像素比

determine the device pixel ratio 算法的开头插入以下步骤:

  1. 如果 device pixel ratio overrides 包含 windownavigable,则返回 device pixel ratio overrides[windownavigable]。

9. 附录

本节为非规范性内容。

9.1. 外部规范

注:该列表并不详尽,且可能不是最新的。

以下外部规范定义了额外的 WebDriver BiDi 模块:

  1. Digital Credentials API

  2. Permissions

  3. nav-speculation

  4. User-Agent Client Hints

  5. Web Bluetooth

索引

由本规范定义的术语

由引用定义的术语

参考文献

规范性参考文献

[ACCNAME-1.1]
Joanmarie Diggs; Bryan Garaventa; Michael Cooper. 可访问 名称和描述计算 1.1. URL: https://w3c.github.io/accname/
[CONSOLE]
Dominic Farolino; Robert Kowalski; Terin Stock. 控制台 标准. 现行标准. URL: https://console.spec.whatwg.org/
[COOKIES]
A. Barth. HTTP 状态管理机制. 2011 年 4 月. 拟议标准. URL: https://httpwg.org/specs/rfc6265.html
[CORE-AAM-1.1]
Joanmarie Diggs; et al. 核心可访问性 API 映射 1.1. URL: https://w3c.github.io/core-aam/
[CSS-COLOR-ADJUST-1]
Elika Etemad; et al. CSS 颜色调整 模块第 1 级. URL: https://drafts.csswg.org/css-color-adjust-1/
[CSS-OVERFLOW-3]
Elika Etemad; Florian Rivoal. CSS 溢出模块 第 3 级. URL: https://drafts.csswg.org/css-overflow-3/
[CSS-PAINT-API-1]
Ian Kilpatrick; Dean Jackson. CSS 绘制 API 第 1 级. URL: https://drafts.css-houdini.org/css-paint-api-1/
[CSS2]
Bert Bos; et al. 层叠样式表第 2 级修订版 1 (CSS 2.1)规范. URL: https://drafts.csswg.org/css2/
[CSSOM-VIEW-1]
Simon Fraser; Emilio Cobos Álvarez. CSSOM 视图 模块. URL: https://drafts.csswg.org/cssom-view/
[DOM]
Anne van Kesteren. DOM 标准. 现行标准. URL: https://dom.spec.whatwg.org/
[ECMA-402]
ECMAScript 国际化 API 规范. URL: https://tc39.es/ecma402/
[ECMAScript]
ECMAScript 语言规范. URL: https://tc39.es/ecma262/multipage/
[ENCODING]
Anne van Kesteren. 编码标准. 现行 标准. URL: https://encoding.spec.whatwg.org/
[FETCH]
Anne van Kesteren. Fetch 标准. 现行 标准. URL: https://fetch.spec.whatwg.org/
[FS]
Austin Sullivan. 文件系统标准. 现行 标准. URL: https://fs.spec.whatwg.org/
[FULLSCREEN]
Philip Jägenstedt. 全屏 API 标准. 现行标准. URL: https://fullscreen.spec.whatwg.org/
[GEOLOCATION]
Marcos Caceres; Reilly Grant. 地理定位. URL: https://w3c.github.io/geolocation/
[GEOMETRY-1]
Sebastian Zartner; Yehonatan Daniv. 几何接口 模块第 1 级. URL: https://drafts.csswg.org/geometry/
[HR-TIME-3]
Yoav Weiss. 高精度时间. URL: https://w3c.github.io/hr-time/
[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/
[MIMESNIFF]
Gordon P. Hemsley. MIME 嗅探标准. 现行标准. URL: https://mimesniff.spec.whatwg.org/
[RESOURCE-TIMING]
Yoav Weiss; Noam Rosenthal. 资源 计时. URL: https://w3c.github.io/resource-timing/
[RFC4648]
S. Josefsson. Base16、Base32 和 Base64 数据 编码. 2006 年 10 月. 拟议标准. URL: https://www.rfc-editor.org/info/rfc4648/
[RFC5280]
D. Cooper; et al. 互联网 X.509 公钥 基础设施证书和证书吊销列表(CRL)配置文件. 2008 年 5 月. 拟议标准. URL: https://www.rfc-editor.org/info/rfc5280/
[RFC6455]
I. Fette; A. Melnikov. WebSocket 协议. 2011 年 12 月. 拟议标准. URL: https://www.rfc-editor.org/info/rfc6455/
[RFC8610]
H. Birkholz; C. Vigano; C. Bormann. 简洁数据 定义语言(CDDL):用于表达简洁二进制对象表示 (CBOR)和 JSON 数据结构的记法约定. 2019 年 6 月. 拟议标准. URL: https://www.rfc-editor.org/info/rfc8610/
[RFC9110]
R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed.. HTTP 语义. 2022 年 6 月. 互联网 标准. URL: https://httpwg.org/specs/rfc9110.html
[RFC9562]
K. Davis; B. Peabody; P. Leach. 通用唯一 标识符(UUID). 2024 年 5 月. 拟议标准. URL: https://www.rfc-editor.org/info/rfc9562/
[SCREEN-CAPTURE]
Jan-Ivar Bruaroey; Elad Alon. 屏幕 捕获. URL: https://w3c.github.io/mediacapture-screen-share/
[SCREEN-ORIENTATION]
Marcos Caceres. 屏幕方向. URL: https://w3c.github.io/screen-orientation/
[SELECTORS-4]
Elika Etemad; Tab Atkins Jr.. 选择器第 4 级. URL: https://drafts.csswg.org/selectors/
[SERVICE-WORKERS]
Monica CHINTALA; Yoshisato Yanagisawa. Service Workers Nightly. URL: https://w3c.github.io/ServiceWorker/
[SVG2]
Amelia Bellamy-Royds; et al. 可缩放矢量 图形(SVG)2. URL: https://w3c.github.io/svgwg/svg2-draft/
[UNICODE]
Unicode 标准. URL: https://www.unicode.org/versions/latest/
[URL]
Anne van Kesteren. URL 标准. 现行标准. URL: https://url.spec.whatwg.org/
[WEBAUDIO-1.0]
Paul Adenot; Hongchan Choi. Web Audio API. URL: https://webaudio.github.io/web-audio-api/
[WEBDRIVER]
Simon Stewart; David Burns. WebDriver. URL: https://w3c.github.io/webdriver/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 标准. 现行 标准. URL: https://webidl.spec.whatwg.org/
[WEBSOCKETS]
Adam Rice. WebSockets 标准. 现行 标准. URL: https://websockets.spec.whatwg.org/
[WEBTRANSPORT]
Nidhi Jaju; Victor Vasiliev; Jan-Ivar Bruaroey. WebTransport. URL: https://w3c.github.io/webtransport/

资料性参考文献

[CSS-VALUES-3]
Tab Atkins Jr.; Elika Etemad. CSS Values and Units Module Level 3. URL: https://drafts.csswg.org/css-values-3/
[HTTP11]
R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed.. HTTP/1.1. 2022 年 6 月. Internet 标准. URL: https://httpwg.org/specs/rfc9112.html
[JSON-RPC]
JSON-RPC Working Group. JSON-RPC 2.0 规范. 2013 年 1 月 4 日. URL: https://www.jsonrpc.org/specification
[RFC6265BIS]
Cookies:HTTP 状态 管理机制. 编辑草案. URL: https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis
[TOUCH-EVENTS]
Doug Schepers; et al. Touch Events. URL: https://w3c.github.io/touch-events/
[URLPattern]
Ben Kelly; Jeremy Roman; 宍戸俊哉 (Shunya Shishido). URL Pattern 标准. 现行标准. URL: https://urlpattern.spec.whatwg.org/

CDDL 索引

远端定义

Command = {
  id: js-uint,
  CommandData,
  Extensible,
}

CommandData = (
  BrowserCommand //
  BrowsingContextCommand //
  EmulationCommand //
  InputCommand //
  NetworkCommand //
  ScriptCommand //
  SessionCommand //
  StorageCommand //
  WebExtensionCommand
)

EmptyParams = {
   Extensible
}

Extensible = (*text => any)

js-int = -9007199254740991..9007199254740991
js-uint = 0..9007199254740991

SessionCommand = (
  session.End //
  session.New //
  session.Status //
  session.Subscribe //
  session.Unsubscribe
)

session.CapabilitiesRequest = {
  ? alwaysMatch: session.CapabilityRequest,
  ? firstMatch: [*session.CapabilityRequest]
}

session.CapabilityRequest = {
  ? acceptInsecureCerts: bool,
  ? browserName: text,
  ? browserVersion: text,
  ? platformName: text,
  ? proxy: session.ProxyConfiguration,
  ? unhandledPromptBehavior: session.UserPromptHandler,
  Extensible
}

session.ProxyConfiguration = {
   session.AutodetectProxyConfiguration //
   session.DirectProxyConfiguration //
   session.ManualProxyConfiguration //
   session.PacProxyConfiguration //
   session.SystemProxyConfiguration
}

session.AutodetectProxyConfiguration = (
   proxyType: "autodetect",
   Extensible
)

session.DirectProxyConfiguration = (
   proxyType: "direct",
   Extensible
)

session.ManualProxyConfiguration = (
   proxyType: "manual",
   ? httpProxy: text,
   ? sslProxy: text,
   ? session.SocksProxyConfiguration,
   ? noProxy: [*text],
   Extensible
)

session.SocksProxyConfiguration = (
   socksProxy: text,
   socksVersion: 0..255,
)

session.PacProxyConfiguration = (
   proxyType: "pac",
   proxyAutoconfigUrl: text,
   Extensible
)

session.SystemProxyConfiguration = (
   proxyType: "system",
   Extensible
)


session.UserPromptHandler = {
  ? alert: session.UserPromptHandlerType,
  ? beforeUnload: session.UserPromptHandlerType,
  ? confirm: session.UserPromptHandlerType,
  ? default: session.UserPromptHandlerType,
  ? file: session.UserPromptHandlerType,
  ? prompt: session.UserPromptHandlerType,
}

session.UserPromptHandlerType = "accept" / "dismiss" / "ignore";

session.Subscription = text

session.SubscribeParameters = {
  events: [+text],
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

session.UnsubscribeByIDRequest = {
  subscriptions: [+session.Subscription],
}

session.UnsubscribeByAttributesRequest = {
  events: [+text],
}

session.Status = (
  method: "session.status",
  params: EmptyParams,
)

session.New = (
  method: "session.new",
  params: session.NewParameters
)

session.NewParameters = {
  capabilities: session.CapabilitiesRequest
}

session.End = (
  method: "session.end",
  params: EmptyParams
)


session.Subscribe = (
  method: "session.subscribe",
  params: session.SubscribeParameters
)

session.Unsubscribe = (
  method: "session.unsubscribe",
  params: session.UnsubscribeParameters,
)

session.UnsubscribeParameters = session.UnsubscribeByAttributesRequest / session.UnsubscribeByIDRequest

BrowserCommand = (
  browser.Close //
  browser.CreateUserContext //
  browser.GetClientWindows //
  browser.GetUserContexts //
  browser.RemoveUserContext //
  browser.SetClientWindowState //
  browser.SetDownloadBehavior
)

browser.ClientWindow = text;

browser.ClientWindowInfo = {
  active: bool,
  clientWindow: browser.ClientWindow,
  height: js-uint,
  state: "fullscreen" / "maximized" / "minimized" / "normal",
  width: js-uint,
  x: js-int,
  y: js-int,
}

browser.UserContext = text;

browser.UserContextInfo = {
  userContext: browser.UserContext
}

browser.Close = (
  method: "browser.close",
  params: EmptyParams,
)

browser.CreateUserContext = (
  method: "browser.createUserContext",
  params: browser.CreateUserContextParameters,
)

browser.CreateUserContextParameters = {
  ? acceptInsecureCerts: bool,
  ? proxy: session.ProxyConfiguration,
  ? unhandledPromptBehavior: session.UserPromptHandler
}

browser.GetClientWindows = (
  method: "browser.getClientWindows",
  params: EmptyParams,
)

browser.GetUserContexts = (
  method: "browser.getUserContexts",
  params: EmptyParams,
)

browser.RemoveUserContext = (
  method: "browser.removeUserContext",
  params: browser.RemoveUserContextParameters
)

browser.RemoveUserContextParameters = {
  userContext: browser.UserContext
}

browser.SetClientWindowState = (
  method: "browser.setClientWindowState",
  params: browser.SetClientWindowStateParameters
)

browser.SetClientWindowStateParameters = {
  clientWindow: browser.ClientWindow,
  (browser.ClientWindowNamedState // browser.ClientWindowRectState)
}

browser.ClientWindowNamedState = (
  state: "fullscreen" / "maximized" / "minimized"
)

browser.ClientWindowRectState = (
  state: "normal",
  ? width: js-uint,
  ? height: js-uint,
  ? x: js-int,
  ? y: js-int,
)

browser.SetDownloadBehavior = (
  method: "browser.setDownloadBehavior",
  params: browser.SetDownloadBehaviorParameters
)

browser.SetDownloadBehaviorParameters = {
  downloadBehavior: browser.DownloadBehavior / null,
  ? userContexts: [+browser.UserContext]
}

browser.DownloadBehavior = {
  (
    browser.DownloadBehaviorAllowed //
    browser.DownloadBehaviorDenied
  )
}

browser.DownloadBehaviorAllowed = (
  type: "allowed",
  destinationFolder: text
)

browser.DownloadBehaviorDenied = (
  type: "denied"
)

BrowsingContextCommand = (
  browsingContext.Activate //
  browsingContext.CaptureScreenshot //
  browsingContext.Close //
  browsingContext.Create //
  browsingContext.GetTree //
  browsingContext.HandleUserPrompt //
  browsingContext.LocateNodes //
  browsingContext.Navigate //
  browsingContext.Print //
  browsingContext.Reload //
  browsingContext.SetBypassCSP //
  browsingContext.SetViewport //
  browsingContext.StartScreencast //
  browsingContext.StopScreencast //
  browsingContext.TraverseHistory
)

browsingContext.BrowsingContext = text;

browsingContext.Locator = (
   browsingContext.AccessibilityLocator /
   browsingContext.CssLocator /
   browsingContext.ContextLocator /
   browsingContext.InnerTextLocator /
   browsingContext.XPathLocator
)

browsingContext.AccessibilityLocator = {
   type: "accessibility",
   value: {
    ? name: text,
    ? role: text,
   }
}

browsingContext.CssLocator = {
   type: "css",
   value: text
}

browsingContext.ContextLocator = {
  type: "context",
  value: {
    context: browsingContext.BrowsingContext,
  }
}

browsingContext.InnerTextLocator = {
   type: "innerText",
   value: text,
   ? ignoreCase: bool
   ? matchType: "full" / "partial",
   ? maxDepth: js-uint,
}

browsingContext.XPathLocator = {
   type: "xpath",
   value: text
}

browsingContext.Navigation = text;

browsingContext.Download = text;

browsingContext.ReadinessState = "none" / "interactive" / "complete"

browsingContext.UserPromptType = "alert" / "beforeunload" / "confirm" / "prompt";

browsingContext.Activate = (
  method: "browsingContext.activate",
  params: browsingContext.ActivateParameters
)

browsingContext.ActivateParameters = {
  context: browsingContext.BrowsingContext
}

browsingContext.CaptureScreenshot = (
  method: "browsingContext.captureScreenshot",
  params: browsingContext.CaptureScreenshotParameters
)

browsingContext.CaptureScreenshotParameters = {
  context: browsingContext.BrowsingContext,
  ? origin: ("viewport" / "document") .default "viewport",
  ? format: browsingContext.ImageFormat,
  ? clip: browsingContext.ClipRectangle,
}

browsingContext.ImageFormat = {
   type: text,
   ? quality: 0.0..1.0,
}

browsingContext.ClipRectangle = (
  browsingContext.BoxClipRectangle /
  browsingContext.ElementClipRectangle
)

browsingContext.ElementClipRectangle = {
  type: "element",
  element: script.SharedReference
}

browsingContext.BoxClipRectangle = {
   type: "box",
   x: float,
   y: float,
   width: float,
   height: float
}

browsingContext.Close = (
  method: "browsingContext.close",
  params: browsingContext.CloseParameters
)

browsingContext.CloseParameters = {
  context: browsingContext.BrowsingContext,
  ? promptUnload: bool .default false
}

browsingContext.Create = (
  method: "browsingContext.create",
  params: browsingContext.CreateParameters
)

browsingContext.CreateType = "tab" / "window"

browsingContext.CreateParameters = {
  type: browsingContext.CreateType,
  ? referenceContext: browsingContext.BrowsingContext,
  ? background: bool .default false,
  ? userContext: browser.UserContext
}

browsingContext.GetTree = (
  method: "browsingContext.getTree",
  params: browsingContext.GetTreeParameters
)

browsingContext.GetTreeParameters = {
  ? maxDepth: js-uint,
  ? root: browsingContext.BrowsingContext,
}

browsingContext.HandleUserPrompt = (
  method: "browsingContext.handleUserPrompt",
  params: browsingContext.HandleUserPromptParameters
)

browsingContext.HandleUserPromptParameters = {
  context: browsingContext.BrowsingContext,
  ? accept: bool,
  ? userText: text,
}

browsingContext.LocateNodes = (
  method: "browsingContext.locateNodes",
  params: browsingContext.LocateNodesParameters
)

browsingContext.LocateNodesParameters = {
   context: browsingContext.BrowsingContext,
   locator: browsingContext.Locator,
   ? maxNodeCount: (js-uint .ge 1),
   ? serializationOptions: script.SerializationOptions,
   ? startNodes: [ + script.SharedReference ]
}

browsingContext.Navigate = (
  method: "browsingContext.navigate",
  params: browsingContext.NavigateParameters
)

browsingContext.NavigateParameters = {
  context: browsingContext.BrowsingContext,
  url: text,
  ? wait: browsingContext.ReadinessState,
}

browsingContext.Print = (
  method: "browsingContext.print",
  params: browsingContext.PrintParameters
)

browsingContext.PrintParameters = {
  context: browsingContext.BrowsingContext,
  ? background: bool .default false,
  ? margin: browsingContext.PrintMarginParameters,
  ? orientation: ("portrait" / "landscape") .default "portrait",
  ? page: browsingContext.PrintPageParameters,
  ? pageRanges: [*(js-uint / text)],
  ? scale: (0.1..2.0) .default 1.0,
  ? shrinkToFit: bool .default true,
}

browsingContext.PrintMarginParameters = {
  ? bottom: (float .ge 0.0) .default 1.0,
  ? left: (float .ge 0.0) .default 1.0,
  ? right: (float .ge 0.0) .default 1.0,
  ? top: (float .ge 0.0) .default 1.0,
}

; Minimum size is 1pt x 1pt. Conversion follows from
; https://www.w3.org/TR/css3-values/#absolute-lengths
browsingContext.PrintPageParameters = {
  ? height: (float .ge 0.0352) .default 27.94,
  ? width: (float .ge 0.0352) .default 21.59,
}

browsingContext.Reload = (
  method: "browsingContext.reload",
  params: browsingContext.ReloadParameters
)

browsingContext.ReloadParameters = {
  context: browsingContext.BrowsingContext,
  ? ignoreCache: bool,
  ? wait: browsingContext.ReadinessState,
}

browsingContext.SetBypassCSP = (
  method: "browsingContext.setBypassCSP",
  params: browsingContext.SetBypassCSPParameters
)

browsingContext.SetBypassCSPParameters = {
  bypass: true / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

browsingContext.SetViewport = (
  method: "browsingContext.setViewport",
  params: browsingContext.SetViewportParameters
)

browsingContext.SetViewportParameters = {
  ? context: browsingContext.BrowsingContext,
  ? viewport: browsingContext.Viewport / null,
  ? devicePixelRatio: (float .gt 0.0) / null,
  ? userContexts: [+browser.UserContext],
}

browsingContext.Viewport = {
  width: js-uint,
  height: js-uint,
}

browsingContext.StartScreencast = (
  method: "browsingContext.startScreencast",
  params: browsingContext.StartScreencastParameters
)

browsingContext.StartScreencastParameters = {
  context: browsingContext.BrowsingContext,
  ? mimeType: text,
  ? video: browsingContext.MediaTrackConstraints,
  ? audio: bool .default false,
}

browsingContext.MediaTrackConstraints = {
   ? width: js-uint,
   ? height: js-uint,
   ? frameRate: js-uint,
}


browsingContext.Screencast = text

browsingContext.StopScreencast = (
  method: "browsingContext.stopScreencast",
  params: browsingContext.StopScreencastParameters
)

browsingContext.StopScreencastParameters = {
  screencast: browsingContext.Screencast
}

browsingContext.TraverseHistory = (
  method: "browsingContext.traverseHistory",
  params: browsingContext.TraverseHistoryParameters
)

browsingContext.TraverseHistoryParameters = {
  context: browsingContext.BrowsingContext,
  delta: js-int,
}

EmulationCommand = (
  emulation.SetForcedColorsModeThemeOverride //
  emulation.SetGeolocationOverride //
  emulation.SetLocaleOverride //
  emulation.SetNetworkConditions //
  emulation.SetScreenOrientationOverride //
  emulation.SetScreenSettingsOverride //
  emulation.SetScriptingEnabled //
  emulation.SetScrollbarTypeOverride //
  emulation.SetTimezoneOverride //
  emulation.SetTouchOverride //
  emulation.SetUserAgentOverride
)


emulation.SetForcedColorsModeThemeOverride = (
  method: "emulation.setForcedColorsModeThemeOverride",
  params: emulation.SetForcedColorsModeThemeOverrideParameters
)

emulation.SetForcedColorsModeThemeOverrideParameters = {
  theme: emulation.ForcedColorsModeTheme / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.ForcedColorsModeTheme = "light" / "dark"

emulation.SetGeolocationOverride = (
  method: "emulation.setGeolocationOverride",
  params: emulation.SetGeolocationOverrideParameters
)

emulation.SetGeolocationOverrideParameters = {
  (
    (coordinates: emulation.GeolocationCoordinates / null) //
    (error: emulation.GeolocationPositionError)
  ),
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.GeolocationCoordinates = {
   latitude: -90.0..90.0,
   longitude: -180.0..180.0,
   ? accuracy: (float .ge 0.0) .default 1.0,
   ? altitude: float / null .default null,
   ? altitudeAccuracy: (float .ge 0.0) / null .default null,
   ? heading: (0.0...360.0) / null .default null,
   ? speed: (float .ge 0.0) / null .default null,
}

emulation.GeolocationPositionError = {
   type: "positionUnavailable"
}

emulation.SetLocaleOverride = (
  method: "emulation.setLocaleOverride",
  params: emulation.SetLocaleOverrideParameters
)

emulation.SetLocaleOverrideParameters = {
  locale: text / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.SetNetworkConditions = (
  method: "emulation.setNetworkConditions",
  params: emulation.SetNetworkConditionsParameters
)

emulation.SetNetworkConditionsParameters = {
  networkConditions: emulation.NetworkConditions / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.NetworkConditions = emulation.NetworkConditionsOffline

emulation.NetworkConditionsOffline = {
  type: "offline"
}

emulation.SetScreenSettingsOverride = (
  method: "emulation.setScreenSettingsOverride",
  params: emulation.SetScreenSettingsOverrideParameters
)

emulation.ScreenArea = {
  width: js-uint,
  height: js-uint
}

emulation.SetScreenSettingsOverrideParameters = {
  screenArea: emulation.ScreenArea / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.SetScreenOrientationOverride = (
  method: "emulation.setScreenOrientationOverride",
  params: emulation.SetScreenOrientationOverrideParameters
)

emulation.ScreenOrientationNatural = "portrait" / "landscape"
emulation.ScreenOrientationType = "portrait-primary" / "portrait-secondary" / "landscape-primary" / "landscape-secondary"

emulation.ScreenOrientation = {
  natural: emulation.ScreenOrientationNatural,
  type: emulation.ScreenOrientationType
}

emulation.SetScreenOrientationOverrideParameters = {
  screenOrientation: emulation.ScreenOrientation / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.SetUserAgentOverride = (
  method: "emulation.setUserAgentOverride",
  params: emulation.SetUserAgentOverrideParameters
)

emulation.SetUserAgentOverrideParameters = {
  userAgent: text / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.SetScriptingEnabled = (
  method: "emulation.setScriptingEnabled",
  params: emulation.SetScriptingEnabledParameters
)

emulation.SetScriptingEnabledParameters = {
  enabled: false / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.SetScrollbarTypeOverride = (
  method: "emulation.setScrollbarTypeOverride",
  params: emulation.SetScrollbarTypeOverrideParameters
)

emulation.SetScrollbarTypeOverrideParameters = {
  scrollbarType: "classic" / "overlay" / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.SetTimezoneOverride = (
  method: "emulation.setTimezoneOverride",
  params: emulation.SetTimezoneOverrideParameters
)

emulation.SetTimezoneOverrideParameters = {
  timezone: text / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

emulation.SetTouchOverride = (
  method: "emulation.setTouchOverride",
  params: emulation.SetTouchOverrideParameters
)

emulation.SetTouchOverrideParameters = {
  maxTouchPoints: (js-uint .ge 1) / null,
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

NetworkCommand = (
  network.AddDataCollector //
  network.AddIntercept //
  network.ContinueRequest //
  network.ContinueResponse //
  network.ContinueWithAuth //
  network.DisownData //
  network.FailRequest //
  network.GetData //
  network.ProvideResponse //
  network.RemoveDataCollector //
  network.RemoveIntercept //
  network.SetCacheBehavior //
  network.SetExtraHeaders
)


network.AuthCredentials = {
  type: "password",
  username: text,
  password: text,
}

network.BytesValue = network.StringValue / network.Base64Value;

network.StringValue = {
  type: "string",
  value: text,
}

network.Base64Value = {
  type: "base64",
  value: text,
}

network.Collector = text

network.CollectorType = "blob"

network.SameSite = "strict" / "lax" / "none" / "default"


network.Cookie = {
    name: text,
    value: network.BytesValue,
    domain: text,
    path: text,
    size: js-uint,
    httpOnly: bool,
    secure: bool,
    sameSite: network.SameSite,
    ? expiry: js-uint,
    Extensible,
}

network.CookieHeader = {
    name: text,
    value: network.BytesValue,
}

network.DataType = "request" / "response"

network.Header = {
  name: text,
  value: network.BytesValue,
}

network.Intercept = text

network.Request = text;

network.SetCookieHeader = {
    name: text,
    value: network.BytesValue,
    ? domain: text,
    ? httpOnly: bool,
    ? expiry: text,
    ? maxAge: js-int,
    ? path: text,
    ? sameSite: network.SameSite,
    ? secure: bool,
}

network.UrlPattern = (
  network.UrlPatternPattern /
  network.UrlPatternString
)

network.UrlPatternPattern = {
    type: "pattern",
    ?protocol: text,
    ?hostname: text,
    ?port: text,
    ?pathname: text,
    ?search: text,
}


network.UrlPatternString = {
    type: "string",
    pattern: text,
}


network.AddDataCollector = (
  method: "network.addDataCollector",
  params: network.AddDataCollectorParameters
)

network.AddDataCollectorParameters = {
  dataTypes: [+network.DataType],
  maxEncodedDataSize: js-uint,
  ? collectorType: network.CollectorType .default "blob",
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
}

network.AddIntercept = (
  method: "network.addIntercept",
  params: network.AddInterceptParameters
)

network.AddInterceptParameters = {
  phases: [+network.InterceptPhase],
  ? contexts: [+browsingContext.BrowsingContext],
  ? urlPatterns: [*network.UrlPattern],
}

network.InterceptPhase = "beforeRequestSent" / "responseStarted" /
                         "authRequired"

network.ContinueRequest = (
  method: "network.continueRequest",
  params: network.ContinueRequestParameters
)

network.ContinueRequestParameters = {
  request: network.Request,
  ?body: network.BytesValue,
  ?cookies: [*network.CookieHeader],
  ?headers: [*network.Header],
  ?method: text,
  ?url: text,
}

network.ContinueResponse = (
  method: "network.continueResponse",
  params: network.ContinueResponseParameters
)

network.ContinueResponseParameters = {
  request: network.Request,
  ?cookies: [*network.SetCookieHeader]
  ?credentials: network.AuthCredentials,
  ?headers: [*network.Header],
  ?reasonPhrase: text,
  ?statusCode: js-uint,
}

network.ContinueWithAuth = (
  method: "network.continueWithAuth",
  params: network.ContinueWithAuthParameters
)

network.ContinueWithAuthParameters = {
  request: network.Request,
  (network.ContinueWithAuthCredentials // network.ContinueWithAuthNoCredentials)
}

network.ContinueWithAuthCredentials = (
  action: "provideCredentials", 
  credentials: network.AuthCredentials
)

network.ContinueWithAuthNoCredentials = (
  action: "default" / "cancel"
)

network.DisownData = (
  method: "network.disownData",
  params: network.DisownDataParameters
)

network.DisownDataParameters = {
  dataType: network.DataType,
  collector: network.Collector,
  request: network.Request,
}

network.FailRequest = (
  method: "network.failRequest",
  params: network.FailRequestParameters
)

network.FailRequestParameters = {
  request: network.Request,
}

network.GetData = (
  method: "network.getData",
  params: network.GetDataParameters
)

network.GetDataParameters = {
  dataType: network.DataType,
  ? collector: network.Collector,
  ? disown: bool .default false,
  request: network.Request,
}

network.ProvideResponse = (
  method: "network.provideResponse",
  params: network.ProvideResponseParameters
)

network.ProvideResponseParameters = {
  request: network.Request,
  ?body: network.BytesValue,
  ?cookies: [*network.SetCookieHeader],
  ?headers: [*network.Header],
  ?reasonPhrase: text,
  ?statusCode: js-uint,
}

network.RemoveDataCollector = (
  method: "network.removeDataCollector",
  params: network.RemoveDataCollectorParameters
)

network.RemoveDataCollectorParameters = {
  collector: network.Collector
}

network.RemoveIntercept = (
  method: "network.removeIntercept",
  params: network.RemoveInterceptParameters
)

network.RemoveInterceptParameters = {
  intercept: network.Intercept
}

network.SetCacheBehavior = (
  method: "network.setCacheBehavior",
  params: network.SetCacheBehaviorParameters
)

network.SetCacheBehaviorParameters = {
  cacheBehavior: "default" / "bypass",
  ? contexts: [+browsingContext.BrowsingContext]
}

network.SetExtraHeaders = (
  method: "network.setExtraHeaders",
  params: network.SetExtraHeadersParameters
)

network.SetExtraHeadersParameters = {
  headers: [*network.Header]
  ? contexts: [+browsingContext.BrowsingContext]
  ? userContexts: [+browser.UserContext]
}

ScriptCommand = (
  script.AddPreloadScript //
  script.CallFunction //
  script.Disown //
  script.Evaluate //
  script.GetRealms //
  script.RemovePreloadScript
)

script.Channel = text;

script.ChannelValue = {
  type: "channel",
  value: script.ChannelProperties,
}

script.ChannelProperties = {
  channel: script.Channel,
  ? serializationOptions: script.SerializationOptions,
  ? ownership: script.ResultOwnership,
}

script.EvaluateResult = (
  script.EvaluateResultSuccess /
  script.EvaluateResultException
)

script.EvaluateResultSuccess = {
  type: "success",
  result: script.RemoteValue,
  realm: script.Realm
}

script.EvaluateResultException = {
  type: "exception",
  exceptionDetails: script.ExceptionDetails
  realm: script.Realm
}

script.ExceptionDetails = {
  columnNumber: js-uint,
  exception: script.RemoteValue,
  lineNumber: js-uint,
  stackTrace: script.StackTrace,
  text: text,
}

script.Handle = text;

script.InternalId = text;

script.LocalValue = (
  script.RemoteReference /
  script.PrimitiveProtocolValue /
  script.ChannelValue /
  script.ArrayLocalValue /
  { script.DateLocalValue } /
  script.MapLocalValue /
  script.ObjectLocalValue /
  { script.RegExpLocalValue } /
  script.SetLocalValue
)

script.ListLocalValue = [*script.LocalValue];

script.ArrayLocalValue = {
  type: "array",
  value: script.ListLocalValue,
}

script.DateLocalValue = (
  type: "date",
  value: text
)

script.MappingLocalValue = [*[(script.LocalValue / text), script.LocalValue]];

script.MapLocalValue = {
  type: "map",
  value: script.MappingLocalValue,
}

script.ObjectLocalValue = {
  type: "object",
  value: script.MappingLocalValue,
}

script.RegExpValue = {
  pattern: text,
  ? flags: text,
}

script.RegExpLocalValue = (
  type: "regexp",
  value: script.RegExpValue,
)

script.SetLocalValue = {
  type: "set",
  value: script.ListLocalValue,
}

script.PreloadScript = text;

script.Realm = text;

script.PrimitiveProtocolValue = (
  script.UndefinedValue /
  script.NullValue /
  script.StringValue /
  script.NumberValue /
  script.BooleanValue /
  script.BigIntValue
)

script.UndefinedValue = {
  type: "undefined",
}

script.NullValue = {
  type: "null",
}

script.StringValue = {
  type: "string",
  value: text,
}

script.SpecialNumber = "NaN" / "-0" / "Infinity" / "-Infinity";

script.NumberValue = {
  type: "number",
  value: number / script.SpecialNumber,
}

script.BooleanValue = {
  type: "boolean",
  value: bool,
}

script.BigIntValue = {
  type: "bigint",
  value: text,
}

script.RealmType = "window" / "dedicated-worker" / "shared-worker" / "service-worker" /
                   "worker" / "paint-worklet" / "audio-worklet" / "worklet"

script.RemoteReference = (
  script.SharedReference /
  script.RemoteObjectReference
)

script.SharedReference = {
   sharedId: script.SharedId

   ? handle: script.Handle,
   Extensible
}

script.RemoteObjectReference = {
   handle: script.Handle,

   ? sharedId: script.SharedId
   Extensible
}

script.RemoteValue = (
  script.PrimitiveProtocolValue /
  script.SymbolRemoteValue /
  script.ArrayRemoteValue /
  script.ObjectRemoteValue /
  script.FunctionRemoteValue /
  script.RegExpRemoteValue /
  script.DateRemoteValue /
  script.MapRemoteValue /
  script.SetRemoteValue /
  script.WeakMapRemoteValue /
  script.WeakSetRemoteValue /
  script.GeneratorRemoteValue /
  script.ErrorRemoteValue /
  script.ProxyRemoteValue /
  script.PromiseRemoteValue /
  script.TypedArrayRemoteValue /
  script.ArrayBufferRemoteValue /
  script.NodeListRemoteValue /
  script.HTMLCollectionRemoteValue /
  script.NodeRemoteValue /
  script.WindowProxyRemoteValue
)

script.ListRemoteValue = [*script.RemoteValue];

script.MappingRemoteValue = [*[(script.RemoteValue / text), script.RemoteValue]];

script.SymbolRemoteValue = {
  type: "symbol",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ArrayRemoteValue = {
  type: "array",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.ObjectRemoteValue = {
  type: "object",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.MappingRemoteValue,
}

script.FunctionRemoteValue = {
  type: "function",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.RegExpRemoteValue = {
  script.RegExpLocalValue,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.DateRemoteValue = {
  script.DateLocalValue,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.MapRemoteValue = {
  type: "map",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.MappingRemoteValue,
}

script.SetRemoteValue = {
  type: "set",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue
}

script.WeakMapRemoteValue = {
  type: "weakmap",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.WeakSetRemoteValue = {
  type: "weakset",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.GeneratorRemoteValue = {
  type: "generator",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ErrorRemoteValue = {
  type: "error",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ProxyRemoteValue = {
  type: "proxy",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.PromiseRemoteValue = {
  type: "promise",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.TypedArrayRemoteValue = {
  type: "typedarray",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ArrayBufferRemoteValue = {
  type: "arraybuffer",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.NodeListRemoteValue = {
  type: "nodelist",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.HTMLCollectionRemoteValue = {
  type: "htmlcollection",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.NodeRemoteValue = {
  type: "node",
  ? sharedId: script.SharedId,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.NodeProperties,
}

script.NodeProperties = {
  nodeType: js-uint,
  childNodeCount: js-uint,
  ? attributes: {*text => text},
  ? children: [*script.NodeRemoteValue],
  ? localName: text,
  ? mode: "open" / "closed",
  ? namespaceURI: text,
  ? nodeValue: text,
  ? shadowRoot: script.NodeRemoteValue / null,
}

script.WindowProxyRemoteValue = {
  type: "window",
  value: script.WindowProxyProperties,
  ? handle: script.Handle,
  ? internalId: script.InternalId
}

script.WindowProxyProperties = {
  context: browsingContext.BrowsingContext
}

script.ResultOwnership = "root" / "none"

script.SerializationOptions = {
  ? maxDomDepth: (js-uint / null) .default 0,
  ? maxObjectDepth: (js-uint / null) .default null,
  ? includeShadowTree: ("none" / "open" / "all") .default "none",
}

script.SharedId = text;

script.StackFrame = {
  columnNumber: js-uint,
  functionName: text,
  lineNumber: js-uint,
  url: text,
}

script.StackTrace = {
  callFrames: [*script.StackFrame],
}

script.RealmTarget = {
  realm: script.Realm
}

script.ContextTarget = {
  context: browsingContext.BrowsingContext,
  ? sandbox: text
}

script.Target = (
  script.ContextTarget /
  script.RealmTarget
)

script.AddPreloadScript = (
  method: "script.addPreloadScript",
  params: script.AddPreloadScriptParameters
)

script.AddPreloadScriptParameters = {
  functionDeclaration: text,
  ? arguments: [*script.ChannelValue],
  ? contexts: [+browsingContext.BrowsingContext],
  ? userContexts: [+browser.UserContext],
  ? sandbox: text
}

script.Disown = (
  method: "script.disown",
  params: script.DisownParameters
)

script.DisownParameters = {
  handles: [*script.Handle]
  target: script.Target;
}

script.CallFunction = (
  method: "script.callFunction",
  params: script.CallFunctionParameters
)

script.CallFunctionParameters = {
  functionDeclaration: text,
  awaitPromise: bool,
  target: script.Target,
  ? arguments: [*script.LocalValue],
  ? resultOwnership: script.ResultOwnership,
  ? serializationOptions: script.SerializationOptions,
  ? this: script.LocalValue,
  ? userActivation: bool .default false,
}

script.Evaluate = (
  method: "script.evaluate",
  params: script.EvaluateParameters
)

script.EvaluateParameters = {
  expression: text,
  target: script.Target,
  awaitPromise: bool,
  ? resultOwnership: script.ResultOwnership,
  ? serializationOptions: script.SerializationOptions,
  ? userActivation: bool .default false,
}

script.GetRealms = (
  method: "script.getRealms",
  params: script.GetRealmsParameters
)

script.GetRealmsParameters = {
  ? context: browsingContext.BrowsingContext,
  ? type: script.RealmType,
}

script.RemovePreloadScript = (
  method: "script.removePreloadScript",
  params: script.RemovePreloadScriptParameters
)

script.RemovePreloadScriptParameters = {
  script: script.PreloadScript
}

StorageCommand = (
  storage.DeleteCookies //
  storage.GetCookies //
  storage.SetCookie
)

storage.PartitionKey = {
  ? userContext: text,
  ? sourceOrigin: text,
  Extensible,
}

storage.GetCookies = (
  method: "storage.getCookies",
  params: storage.GetCookiesParameters
)


storage.CookieFilter = {
  ? name: text,
  ? value: network.BytesValue,
  ? domain: text,
  ? path: text,
  ? size: js-uint,
  ? httpOnly: bool,
  ? secure: bool,
  ? sameSite: network.SameSite,
  ? expiry: js-uint,
  Extensible,
}

storage.BrowsingContextPartitionDescriptor = {
  type: "context",
  context: browsingContext.BrowsingContext
}

storage.StorageKeyPartitionDescriptor = {
  type: "storageKey",
  ? userContext: text,
  ? sourceOrigin: text,
  Extensible,
}

storage.PartitionDescriptor = (
  storage.BrowsingContextPartitionDescriptor /
  storage.StorageKeyPartitionDescriptor
)

storage.GetCookiesParameters = {
  ? filter: storage.CookieFilter,
  ? partition: storage.PartitionDescriptor,
}

storage.SetCookie = (
  method: "storage.setCookie",
  params: storage.SetCookieParameters,
)


storage.PartialCookie = {
  name: text,
  value: network.BytesValue,
  domain: text,
  ? path: text,
  ? httpOnly: bool,
  ? secure: bool,
  ? sameSite: network.SameSite,
  ? expiry: js-uint,
  Extensible,
}

storage.SetCookieParameters = {
  cookie: storage.PartialCookie,
  ? partition: storage.PartitionDescriptor,
}

storage.DeleteCookies = (
  method: "storage.deleteCookies",
  params: storage.DeleteCookiesParameters,
)

storage.DeleteCookiesParameters = {
  ? filter: storage.CookieFilter,
  ? partition: storage.PartitionDescriptor,
}

InputCommand = (
  input.PerformActions //
  input.ReleaseActions //
  input.SetFiles
)

input.ElementOrigin = {
  type: "element",
  element: script.SharedReference
}

input.PerformActions = (
  method: "input.performActions",
  params: input.PerformActionsParameters
)

input.PerformActionsParameters = {
  context: browsingContext.BrowsingContext,
  actions: [*input.SourceActions]
}

input.SourceActions = (
  input.NoneSourceActions /
  input.KeySourceActions /
  input.PointerSourceActions /
  input.WheelSourceActions
)

input.NoneSourceActions = {
  type: "none",
  id: text,
  actions: [*input.NoneSourceAction]
}

input.NoneSourceAction = input.PauseAction

input.KeySourceActions = {
  type: "key",
  id: text,
  actions: [*input.KeySourceAction]
}

input.KeySourceAction = (
  input.PauseAction /
  input.KeyDownAction /
  input.KeyUpAction
)

input.PointerSourceActions = {
  type: "pointer",
  id: text,
  ? parameters: input.PointerParameters,
  actions: [*input.PointerSourceAction]
}

input.PointerType = "mouse" / "pen" / "touch"

input.PointerParameters = {
  ? pointerType: input.PointerType .default "mouse"
}

input.PointerSourceAction = (
  input.PauseAction /
  input.PointerDownAction /
  input.PointerUpAction /
  input.PointerMoveAction
)

input.WheelSourceActions = {
  type: "wheel",
  id: text,
  actions: [*input.WheelSourceAction]
}

input.WheelSourceAction = (
  input.PauseAction /
  input.WheelScrollAction
)

input.PauseAction = {
  type: "pause",
  ? duration: js-uint
}

input.KeyDownAction = {
  type: "keyDown",
  value: text
}

input.KeyUpAction = {
  type: "keyUp",
  value: text
}

input.PointerUpAction = {
  type: "pointerUp",
  button: js-uint,
}

input.PointerDownAction = {
  type: "pointerDown",
  button: js-uint,
  input.PointerCommonProperties
}

input.PointerMoveAction = {
  type: "pointerMove",
  x: float,
  y: float,
  ? duration: js-uint,
  ? origin: input.Origin,
  input.PointerCommonProperties
}

input.WheelScrollAction = {
  type: "scroll",
  x: js-int,
  y: js-int,
  deltaX: js-int,
  deltaY: js-int,
  ? duration: js-uint,
  ? origin: input.Origin .default "viewport",
}

input.PointerCommonProperties = (
  ? width: js-uint,
  ? height: js-uint,
  ? pressure: (0.0..1.0),
  ? tangentialPressure: (-1.0..1.0),
  ? twist: (0..359),
  ; 0 .. Math.PI / 2
  ? altitudeAngle: (0.0..1.5707963267948966),
  ; 0 .. 2 * Math.PI
  ? azimuthAngle: (0.0..6.283185307179586),
)

input.Origin = "viewport" / "pointer" / input.ElementOrigin

input.ReleaseActions = (
  method: "input.releaseActions",
  params: input.ReleaseActionsParameters
)

input.ReleaseActionsParameters = {
  context: browsingContext.BrowsingContext,
}

input.SetFiles = (
  method: "input.setFiles",
  params: input.SetFilesParameters
)

input.SetFilesParameters = {
  context: browsingContext.BrowsingContext,
  element: script.SharedReference,
  files: [*text]
}

WebExtensionCommand = (
  webExtension.Install //
  webExtension.Uninstall
)

webExtension.Extension = text

webExtension.Install = (
   method: "webExtension.install",
   params: webExtension.InstallParameters
)

webExtension.InstallParameters = {
   extensionData: webExtension.ExtensionData,
}

webExtension.ExtensionData = (
   webExtension.ExtensionArchivePath /
   webExtension.ExtensionBase64Encoded /
   webExtension.ExtensionPath
)

webExtension.ExtensionPath = {
   type: "path",
   path: text,
}

webExtension.ExtensionArchivePath = {
   type: "archivePath",
   path: text,
}

webExtension.ExtensionBase64Encoded = {
   type: "base64",
   value: text,
}

webExtension.Uninstall = (
   method: "webExtension.uninstall",
   params: webExtension.UninstallParameters
)

webExtension.UninstallParameters = {
   extension: webExtension.Extension,
}

Local end definition

Message = (
  CommandResponse /
  ErrorResponse /
  Event
)

CommandResponse = {
  type: "success",
  id: js-uint,
  result: ResultData,
  Extensible
}

ErrorResponse = {
  type: "error",
  id: js-uint / null,
  error: ErrorCode,
  message: text,
  ? stacktrace: text,
  Extensible
}

ResultData = (
  BrowserResult /
  BrowsingContextResult /
  EmulationResult /
  InputResult /
  NetworkResult /
  ScriptResult /
  SessionResult /
  StorageResult /
  WebExtensionResult
)

EmptyResult = {
  Extensible
}

Event = {
  type: "event",
  EventData,
  Extensible
}

EventData = (
  BrowsingContextEvent //
  InputEvent //
  LogEvent //
  NetworkEvent //
  ScriptEvent
)

Extensible = (*text => any)

js-int = -9007199254740991..9007199254740991
js-uint = 0..9007199254740991

ErrorCode = "invalid argument" /
            "invalid selector" /
            "invalid session id" /
            "invalid web extension" /
            "move target out of bounds" /
            "no such alert" /
            "no such network collector" /
            "no such element" /
            "no such frame" /
            "no such handle" /
            "no such history entry" /
            "no such intercept" /
            "no such network data" /
            "no such node" /
            "no such request" /
            "no such screencast" /
            "no such script" /
            "no such storage partition" /
            "no such user context" /
            "no such web extension" /
            "session not created" /
            "unable to capture screen" /
            "unable to close browser" /
            "unable to set cookie" /
            "unable to set file input" /
            "unavailable network data" /
            "underspecified storage partition" /
            "unknown command" /
            "unknown error" /
            "unsupported operation"

SessionResult = (
  session.EndResult /
  session.NewResult /
  session.StatusResult /
  session.SubscribeResult /
  session.UnsubscribeResult
)

session.CapabilitiesRequest = {
  ? alwaysMatch: session.CapabilityRequest,
  ? firstMatch: [*session.CapabilityRequest]
}

session.CapabilityRequest = {
  ? acceptInsecureCerts: bool,
  ? browserName: text,
  ? browserVersion: text,
  ? platformName: text,
  ? proxy: session.ProxyConfiguration,
  ? unhandledPromptBehavior: session.UserPromptHandler,
  Extensible
}

session.ProxyConfiguration = {
   session.AutodetectProxyConfiguration //
   session.DirectProxyConfiguration //
   session.ManualProxyConfiguration //
   session.PacProxyConfiguration //
   session.SystemProxyConfiguration
}

session.AutodetectProxyConfiguration = (
   proxyType: "autodetect",
   Extensible
)

session.DirectProxyConfiguration = (
   proxyType: "direct",
   Extensible
)

session.ManualProxyConfiguration = (
   proxyType: "manual",
   ? httpProxy: text,
   ? sslProxy: text,
   ? session.SocksProxyConfiguration,
   ? noProxy: [*text],
   Extensible
)

session.SocksProxyConfiguration = (
   socksProxy: text,
   socksVersion: 0..255,
)

session.PacProxyConfiguration = (
   proxyType: "pac",
   proxyAutoconfigUrl: text,
   Extensible
)

session.SystemProxyConfiguration = (
   proxyType: "system",
   Extensible
)


session.UserPromptHandler = {
  ? alert: session.UserPromptHandlerType,
  ? beforeUnload: session.UserPromptHandlerType,
  ? confirm: session.UserPromptHandlerType,
  ? default: session.UserPromptHandlerType,
  ? file: session.UserPromptHandlerType,
  ? prompt: session.UserPromptHandlerType,
}

session.UserPromptHandlerType = "accept" / "dismiss" / "ignore";

session.Subscription = text

session.StatusResult = {
  ready: bool,
  message: text,
}

session.NewResult = {
  sessionId: text,
  capabilities: {
    acceptInsecureCerts: bool,
    browserName: text,
    browserVersion: text,
    platformName: text,
    setWindowRect: bool,
    userAgent: text,
    ? proxy: session.ProxyConfiguration,
    ? unhandledPromptBehavior: session.UserPromptHandler,
    ? webSocketUrl: text,
    Extensible
  }
}

session.EndResult = EmptyResult

session.SubscribeResult = {
  subscription: session.Subscription,
}

session.UnsubscribeResult = EmptyResult

BrowserResult = (
  browser.CloseResult /
  browser.CreateUserContextResult /
  browser.GetClientWindowsResult /
  browser.GetUserContextsResult /
  browser.RemoveUserContextResult /
  browser.SetClientWindowStateResult /
  browser.SetDownloadBehaviorResult
)

browser.ClientWindow = text;

browser.ClientWindowInfo = {
  active: bool,
  clientWindow: browser.ClientWindow,
  height: js-uint,
  state: "fullscreen" / "maximized" / "minimized" / "normal",
  width: js-uint,
  x: js-int,
  y: js-int,
}

browser.UserContext = text;

browser.UserContextInfo = {
  userContext: browser.UserContext
}

browser.CloseResult = EmptyResult

browser.CreateUserContextResult = browser.UserContextInfo

browser.GetClientWindowsResult = {
  clientWindows: [ * browser.ClientWindowInfo]
}

browser.GetUserContextsResult = {
  userContexts: [ + browser.UserContextInfo]
}

browser.RemoveUserContextResult = EmptyResult

browser.SetClientWindowStateResult = browser.ClientWindowInfo

browser.SetDownloadBehaviorResult = EmptyResult

BrowsingContextResult = (
  browsingContext.ActivateResult /
  browsingContext.CaptureScreenshotResult /
  browsingContext.CloseResult /
  browsingContext.CreateResult /
  browsingContext.GetTreeResult /
  browsingContext.HandleUserPromptResult /
  browsingContext.LocateNodesResult /
  browsingContext.NavigateResult /
  browsingContext.PrintResult /
  browsingContext.ReloadResult /
  browsingContext.SetBypassCSPResult /
  browsingContext.SetViewportResult /
  browsingContext.StartScreencastResult /
  browsingContext.StopScreencastResult /
  browsingContext.TraverseHistoryResult
)

BrowsingContextEvent = (
  browsingContext.ContextCreated //
  browsingContext.ContextDestroyed //
  browsingContext.DomContentLoaded //
  browsingContext.DownloadEnd //
  browsingContext.DownloadWillBegin //
  browsingContext.FragmentNavigated //
  browsingContext.HistoryUpdated //
  browsingContext.Load //
  browsingContext.NavigationAborted //
  browsingContext.NavigationCommitted //
  browsingContext.NavigationFailed //
  browsingContext.NavigationStarted //
  browsingContext.UserPromptClosed //
  browsingContext.UserPromptOpened
)

browsingContext.BrowsingContext = text;

browsingContext.InfoList = [*browsingContext.Info]

browsingContext.Info = {
  children: browsingContext.InfoList / null,
  clientWindow: browser.ClientWindow,
  context: browsingContext.BrowsingContext,
  originalOpener: browsingContext.BrowsingContext / null,
  url: text,
  userContext: browser.UserContext,
  ? parent: browsingContext.BrowsingContext / null,
}

browsingContext.Locator = (
   browsingContext.AccessibilityLocator /
   browsingContext.CssLocator /
   browsingContext.ContextLocator /
   browsingContext.InnerTextLocator /
   browsingContext.XPathLocator
)

browsingContext.AccessibilityLocator = {
   type: "accessibility",
   value: {
    ? name: text,
    ? role: text,
   }
}

browsingContext.CssLocator = {
   type: "css",
   value: text
}

browsingContext.ContextLocator = {
  type: "context",
  value: {
    context: browsingContext.BrowsingContext,
  }
}

browsingContext.InnerTextLocator = {
   type: "innerText",
   value: text,
   ? ignoreCase: bool
   ? matchType: "full" / "partial",
   ? maxDepth: js-uint,
}

browsingContext.XPathLocator = {
   type: "xpath",
   value: text
}

browsingContext.Navigation = text;

browsingContext.Download = text;

browsingContext.BaseNavigationInfo = (
  context: browsingContext.BrowsingContext,
  navigation: browsingContext.Navigation / null,
  timestamp: js-uint,
  url: text,
  ? userContext: browser.UserContext,
)

browsingContext.NavigationInfo = {
  browsingContext.BaseNavigationInfo
}

browsingContext.UserPromptType = "alert" / "beforeunload" / "confirm" / "prompt";

browsingContext.ActivateResult = EmptyResult

browsingContext.CaptureScreenshotResult = {
  data: text
}

browsingContext.CloseResult = EmptyResult

browsingContext.CreateResult = {
  context: browsingContext.BrowsingContext,
  ? userContext: browser.UserContext
}

browsingContext.GetTreeResult = {
  contexts: browsingContext.InfoList
}

browsingContext.HandleUserPromptResult = EmptyResult

browsingContext.LocateNodesResult = {
    nodes: [ * script.NodeRemoteValue ]
}

browsingContext.NavigateResult = {
  navigation: browsingContext.Navigation / null,
  url: text,
}

browsingContext.PrintResult = {
  data: text
}

browsingContext.ReloadResult = browsingContext.NavigateResult

browsingContext.SetBypassCSPResult = EmptyResult

browsingContext.SetViewportResult = EmptyResult

browsingContext.StartScreencastResult = {
   screencast: browsingContext.Screencast,
   path: text
}


browsingContext.Screencast = text

browsingContext.StopScreencastResult = {
   path: text,
   ? error: text
}

browsingContext.TraverseHistoryResult = EmptyResult

browsingContext.ContextCreated = (
 method: "browsingContext.contextCreated",
 params: browsingContext.Info
)

browsingContext.ContextDestroyed = (
 method: "browsingContext.contextDestroyed",
 params: browsingContext.Info
)

browsingContext.NavigationStarted = (
 method: "browsingContext.navigationStarted",
 params: browsingContext.NavigationInfo
)

browsingContext.FragmentNavigated = (
 method: "browsingContext.fragmentNavigated",
 params: browsingContext.NavigationInfo
)

browsingContext.HistoryUpdated = (
  method: "browsingContext.historyUpdated",
  params: browsingContext.HistoryUpdatedParameters
)

browsingContext.HistoryUpdatedParameters = {
  context: browsingContext.BrowsingContext,
  timestamp: js-uint,
  url: text,
  ? userContext: browser.UserContext
}

browsingContext.DomContentLoaded = (
 method: "browsingContext.domContentLoaded",
 params: browsingContext.NavigationInfo
)

browsingContext.Load = (
 method: "browsingContext.load",
 params: browsingContext.NavigationInfo
)

browsingContext.DownloadWillBegin = (
 method: "browsingContext.downloadWillBegin",
 params: browsingContext.DownloadWillBeginParams
)

browsingContext.DownloadWillBeginParams = {
  download: browsingContext.Download,
  suggestedFilename: text,
  browsingContext.BaseNavigationInfo
}

browsingContext.DownloadEnd = (
  method: "browsingContext.downloadEnd",
  params: browsingContext.DownloadEndParams
)

browsingContext.DownloadEndParams = {
  (
    browsingContext.DownloadCanceledParams //
    browsingContext.DownloadCompleteParams
  )
}

browsingContext.DownloadCanceledParams = (
  status: "canceled",
  download: browsingContext.Download,
  browsingContext.BaseNavigationInfo
)

browsingContext.DownloadCompleteParams = (
  status: "complete",
  download: browsingContext.Download,
  filepath: text / null,
  browsingContext.BaseNavigationInfo
)

browsingContext.NavigationAborted = (
 method: "browsingContext.navigationAborted",
 params: browsingContext.NavigationInfo
)

browsingContext.NavigationCommitted = (
 method: "browsingContext.navigationCommitted",
 params: browsingContext.NavigationInfo
)

browsingContext.NavigationFailed = (
 method: "browsingContext.navigationFailed",
 params: browsingContext.NavigationInfo
)

browsingContext.UserPromptClosed = (
  method: "browsingContext.userPromptClosed",
  params: browsingContext.UserPromptClosedParameters
)

browsingContext.UserPromptClosedParameters = {
  context: browsingContext.BrowsingContext,
  accepted: bool,
  type: browsingContext.UserPromptType,
  ? userContext: browser.UserContext,
  ? userText: text
}

browsingContext.UserPromptOpened = (
  method: "browsingContext.userPromptOpened",
  params: browsingContext.UserPromptOpenedParameters
)

browsingContext.UserPromptOpenedParameters = {
  context: browsingContext.BrowsingContext,
  handler: session.UserPromptHandlerType,
  message: text,
  type: browsingContext.UserPromptType,
  ? userContext: browser.UserContext,
  ? defaultValue: text
}

EmulationResult = (
  emulation.SetForcedColorsModeThemeOverrideResult /
  emulation.SetGeolocationOverrideResult /
  emulation.SetLocaleOverrideResult /
  emulation.SetScreenOrientationOverrideResult /
  emulation.SetScriptingEnabledResult /
  emulation.SetScrollbarTypeOverrideResult /
  emulation.SetTimezoneOverrideResult /
  emulation.SetTouchOverrideResult /
  emulation.SetUserAgentOverrideResult
)

emulation.SetForcedColorsModeThemeOverrideResult = EmptyResult

emulation.SetGeolocationOverrideResult = EmptyResult

emulation.SetLocaleOverrideResult = EmptyResult

emulation.SetNetworkConditionsResult = EmptyResult

emulation.SetScreenSettingsOverrideResult = EmptyResult

emulation.SetScreenOrientationOverrideResult = EmptyResult

emulation.SetUserAgentOverrideResult = EmptyResult

emulation.SetScriptingEnabledResult = EmptyResult

emulation.SetScrollbarTypeOverrideResult = EmptyResult

emulation.SetTimezoneOverrideResult = EmptyResult

emulation.SetTouchOverrideResult = EmptyResult

NetworkResult = (
  network.AddDataCollectorResult /
  network.AddInterceptResult /
  network.ContinueRequestResult /
  network.ContinueResponseResult /
  network.ContinueWithAuthResult /
  network.DisownDataResult /
  network.FailRequestResult /
  network.GetDataResult /
  network.ProvideResponseResult /
  network.RemoveDataCollectorResult /
  network.RemoveInterceptResult /
  network.SetCacheBehaviorResult /
  network.SetExtraHeadersResult
)

NetworkEvent = (
    network.AuthRequired //
    network.BeforeRequestSent //
    network.FetchError //
    network.ResponseCompleted //
    network.ResponseStarted
)


network.AuthChallenge = {
  scheme: text,
  realm: text,
}

network.BaseParameters = (
    context: browsingContext.BrowsingContext / null,
    isBlocked: bool,
    navigation: browsingContext.Navigation / null,
    redirectCount: js-uint,
    request: network.RequestData,
    timestamp: js-uint,
    ? userContext: browser.UserContext / null,
    ? intercepts: [+network.Intercept]
)

network.BytesValue = network.StringValue / network.Base64Value;

network.StringValue = {
  type: "string",
  value: text,
}

network.Base64Value = {
  type: "base64",
  value: text,
}

network.Collector = text

network.CollectorType = "blob"

network.SameSite = "strict" / "lax" / "none" / "default"


network.Cookie = {
    name: text,
    value: network.BytesValue,
    domain: text,
    path: text,
    size: js-uint,
    httpOnly: bool,
    secure: bool,
    sameSite: network.SameSite,
    ? expiry: js-uint,
    Extensible,
}

network.DataType = "request" / "response"

network.FetchTimingInfo = {
    timeOrigin: float,
    requestTime: float,
    redirectStart: float,
    redirectEnd: float,
    fetchStart: float,
    dnsStart: float,
    dnsEnd: float,
    connectStart: float,
    connectEnd: float,
    tlsStart: float,

    requestStart: float,
    responseStart: float,

    responseEnd: float,
}

network.Header = {
  name: text,
  value: network.BytesValue,
}

network.Initiator = {
    ? columnNumber: js-uint,
    ? lineNumber: js-uint,
    ? request: network.Request,
    ? stackTrace: script.StackTrace,
    ? type: "parser" / "script" / "preflight" / "other"
}

network.Intercept = text

network.Request = text;

network.RequestData = {
    request: network.Request,
    url: text,
    method: text,
    headers: [*network.Header],
    cookies: [*network.Cookie],
    headersSize: js-uint,
    bodySize: js-uint / null,
    destination: text,
    initiatorType: text / null,
    timings: network.FetchTimingInfo,
}

network.ResponseContent = {
    size: js-uint
}

network.ResponseData = {
    url: text,
    protocol: text,
    status: js-uint,
    statusText: text,
    fromCache: bool,
    headers: [*network.Header],
    mimeType: text,
    bytesReceived: js-uint,
    headersSize: js-uint / null,
    bodySize: js-uint / null,
    content: network.ResponseContent,
    ?authChallenges: [*network.AuthChallenge],
}

network.AddDataCollectorResult = {
  collector: network.Collector
}

network.AddInterceptResult = {
  intercept: network.Intercept
}

network.ContinueRequestResult = EmptyResult

network.ContinueResponseResult = EmptyResult

network.ContinueWithAuthResult = EmptyResult

network.DisownDataResult = EmptyResult

network.FailRequestResult = EmptyResult

network.GetDataResult = {
  bytes: network.BytesValue,
}

network.ProvideResponseResult = EmptyResult

network.RemoveDataCollectorResult = EmptyResult

network.RemoveInterceptResult = EmptyResult

network.SetCacheBehaviorResult = EmptyResult

network.SetExtraHeadersResult = EmptyResult

network.AuthRequired = (
  method: "network.authRequired",
  params: network.AuthRequiredParameters
)

network.AuthRequiredParameters = {
  network.BaseParameters,
  response: network.ResponseData
}

network.BeforeRequestSent = (
  method: "network.beforeRequestSent",
  params: network.BeforeRequestSentParameters
 )

network.BeforeRequestSentParameters = {
  network.BaseParameters,
  ? initiator: network.Initiator,
}

network.FetchError = (
  method: "network.fetchError",
  params: network.FetchErrorParameters
 )

network.FetchErrorParameters = {
  network.BaseParameters,
  errorText: text,
}

network.ResponseCompleted = (
  method: "network.responseCompleted",
  params: network.ResponseCompletedParameters
 )

network.ResponseCompletedParameters = {
  network.BaseParameters,
  response: network.ResponseData,
}

network.ResponseStarted = (
  method: "network.responseStarted",
  params: network.ResponseStartedParameters
 )

network.ResponseStartedParameters = {
  network.BaseParameters,
  response: network.ResponseData,
}

ScriptResult = (
  script.AddPreloadScriptResult /
  script.CallFunctionResult /
  script.DisownResult /
  script.EvaluateResult /
  script.GetRealmsResult /
  script.RemovePreloadScriptResult
)

ScriptEvent = (
  script.Message //
  script.RealmCreated //
  script.RealmDestroyed
)

script.Channel = text;

script.ChannelValue = {
  type: "channel",
  value: script.ChannelProperties,
}

script.ChannelProperties = {
  channel: script.Channel,
  ? serializationOptions: script.SerializationOptions,
  ? ownership: script.ResultOwnership,
}

script.EvaluateResult = (
  script.EvaluateResultSuccess /
  script.EvaluateResultException
)

script.EvaluateResultSuccess = {
  type: "success",
  result: script.RemoteValue,
  realm: script.Realm
}

script.EvaluateResultException = {
  type: "exception",
  exceptionDetails: script.ExceptionDetails
  realm: script.Realm
}

script.ExceptionDetails = {
  columnNumber: js-uint,
  exception: script.RemoteValue,
  lineNumber: js-uint,
  stackTrace: script.StackTrace,
  text: text,
}

script.Handle = text;

script.InternalId = text;

script.LocalValue = (
  script.RemoteReference /
  script.PrimitiveProtocolValue /
  script.ChannelValue /
  script.ArrayLocalValue /
  { script.DateLocalValue } /
  script.MapLocalValue /
  script.ObjectLocalValue /
  { script.RegExpLocalValue } /
  script.SetLocalValue
)

script.ListLocalValue = [*script.LocalValue];

script.ArrayLocalValue = {
  type: "array",
  value: script.ListLocalValue,
}

script.DateLocalValue = (
  type: "date",
  value: text
)

script.MappingLocalValue = [*[(script.LocalValue / text), script.LocalValue]];

script.MapLocalValue = {
  type: "map",
  value: script.MappingLocalValue,
}

script.ObjectLocalValue = {
  type: "object",
  value: script.MappingLocalValue,
}

script.RegExpValue = {
  pattern: text,
  ? flags: text,
}

script.RegExpLocalValue = (
  type: "regexp",
  value: script.RegExpValue,
)

script.SetLocalValue = {
  type: "set",
  value: script.ListLocalValue,
}

script.PreloadScript = text;

script.Realm = text;

script.PrimitiveProtocolValue = (
  script.UndefinedValue /
  script.NullValue /
  script.StringValue /
  script.NumberValue /
  script.BooleanValue /
  script.BigIntValue
)

script.UndefinedValue = {
  type: "undefined",
}

script.NullValue = {
  type: "null",
}

script.StringValue = {
  type: "string",
  value: text,
}

script.SpecialNumber = "NaN" / "-0" / "Infinity" / "-Infinity";

script.NumberValue = {
  type: "number",
  value: number / script.SpecialNumber,
}

script.BooleanValue = {
  type: "boolean",
  value: bool,
}

script.BigIntValue = {
  type: "bigint",
  value: text,
}

script.RealmInfo = (
  script.WindowRealmInfo /
  script.DedicatedWorkerRealmInfo /
  script.SharedWorkerRealmInfo /
  script.ServiceWorkerRealmInfo /
  script.WorkerRealmInfo /
  script.PaintWorkletRealmInfo /
  script.AudioWorkletRealmInfo /
  script.WorkletRealmInfo
)

script.BaseRealmInfo = (
  realm: script.Realm,
  origin: text
)

script.WindowRealmInfo = {
  script.BaseRealmInfo,
  type: "window",
  context: browsingContext.BrowsingContext,
  ? userContext: browser.UserContext,
  ? sandbox: text
}

script.DedicatedWorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "dedicated-worker",
  owners: [script.Realm]
}

script.SharedWorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "shared-worker"
}

script.ServiceWorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "service-worker"
}

script.WorkerRealmInfo = {
  script.BaseRealmInfo,
  type: "worker"
}

script.PaintWorkletRealmInfo = {
  script.BaseRealmInfo,
  type: "paint-worklet"
}

script.AudioWorkletRealmInfo = {
  script.BaseRealmInfo,
  type: "audio-worklet"
}

script.WorkletRealmInfo = {
  script.BaseRealmInfo,
  type: "worklet"
}

script.RealmType = "window" / "dedicated-worker" / "shared-worker" / "service-worker" /
                   "worker" / "paint-worklet" / "audio-worklet" / "worklet"

script.RemoteReference = (
  script.SharedReference /
  script.RemoteObjectReference
)

script.SharedReference = {
   sharedId: script.SharedId

   ? handle: script.Handle,
   Extensible
}

script.RemoteObjectReference = {
   handle: script.Handle,

   ? sharedId: script.SharedId
   Extensible
}

script.RemoteValue = (
  script.PrimitiveProtocolValue /
  script.SymbolRemoteValue /
  script.ArrayRemoteValue /
  script.ObjectRemoteValue /
  script.FunctionRemoteValue /
  script.RegExpRemoteValue /
  script.DateRemoteValue /
  script.MapRemoteValue /
  script.SetRemoteValue /
  script.WeakMapRemoteValue /
  script.WeakSetRemoteValue /
  script.GeneratorRemoteValue /
  script.ErrorRemoteValue /
  script.ProxyRemoteValue /
  script.PromiseRemoteValue /
  script.TypedArrayRemoteValue /
  script.ArrayBufferRemoteValue /
  script.NodeListRemoteValue /
  script.HTMLCollectionRemoteValue /
  script.NodeRemoteValue /
  script.WindowProxyRemoteValue
)

script.ListRemoteValue = [*script.RemoteValue];

script.MappingRemoteValue = [*[(script.RemoteValue / text), script.RemoteValue]];

script.SymbolRemoteValue = {
  type: "symbol",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ArrayRemoteValue = {
  type: "array",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.ObjectRemoteValue = {
  type: "object",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.MappingRemoteValue,
}

script.FunctionRemoteValue = {
  type: "function",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.RegExpRemoteValue = {
  script.RegExpLocalValue,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.DateRemoteValue = {
  script.DateLocalValue,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.MapRemoteValue = {
  type: "map",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.MappingRemoteValue,
}

script.SetRemoteValue = {
  type: "set",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue
}

script.WeakMapRemoteValue = {
  type: "weakmap",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.WeakSetRemoteValue = {
  type: "weakset",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.GeneratorRemoteValue = {
  type: "generator",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ErrorRemoteValue = {
  type: "error",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ProxyRemoteValue = {
  type: "proxy",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.PromiseRemoteValue = {
  type: "promise",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.TypedArrayRemoteValue = {
  type: "typedarray",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.ArrayBufferRemoteValue = {
  type: "arraybuffer",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
}

script.NodeListRemoteValue = {
  type: "nodelist",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.HTMLCollectionRemoteValue = {
  type: "htmlcollection",
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.ListRemoteValue,
}

script.NodeRemoteValue = {
  type: "node",
  ? sharedId: script.SharedId,
  ? handle: script.Handle,
  ? internalId: script.InternalId,
  ? value: script.NodeProperties,
}

script.NodeProperties = {
  nodeType: js-uint,
  childNodeCount: js-uint,
  ? attributes: {*text => text},
  ? children: [*script.NodeRemoteValue],
  ? localName: text,
  ? mode: "open" / "closed",
  ? namespaceURI: text,
  ? nodeValue: text,
  ? shadowRoot: script.NodeRemoteValue / null,
}

script.WindowProxyRemoteValue = {
  type: "window",
  value: script.WindowProxyProperties,
  ? handle: script.Handle,
  ? internalId: script.InternalId
}

script.WindowProxyProperties = {
  context: browsingContext.BrowsingContext
}

script.ResultOwnership = "root" / "none"

script.SerializationOptions = {
  ? maxDomDepth: (js-uint / null) .default 0,
  ? maxObjectDepth: (js-uint / null) .default null,
  ? includeShadowTree: ("none" / "open" / "all") .default "none",
}

script.SharedId = text;

script.StackFrame = {
  columnNumber: js-uint,
  functionName: text,
  lineNumber: js-uint,
  url: text,
}

script.StackTrace = {
  callFrames: [*script.StackFrame],
}

script.Source = {
  realm: script.Realm,
  ? context: browsingContext.BrowsingContext,
  ? userContext: browser.UserContext
}

script.AddPreloadScriptResult = {
  script: script.PreloadScript
}

script.DisownResult = EmptyResult

script.CallFunctionResult = script.EvaluateResult

script.GetRealmsResult = {
  realms: [*script.RealmInfo]
}

script.RemovePreloadScriptResult = EmptyResult

script.Message = (
  method: "script.message",
  params: script.MessageParameters
 )

script.MessageParameters = {
  channel: script.Channel,
  data: script.RemoteValue,
  source: script.Source,
}

script.RealmCreated = (
 method: "script.realmCreated",
 params: script.RealmInfo
)

script.RealmDestroyed = (
  method: "script.realmDestroyed",
  params: script.RealmDestroyedParameters
)

script.RealmDestroyedParameters = {
  realm: script.Realm
}


StorageResult = (
  storage.DeleteCookiesResult /
  storage.GetCookiesResult /
  storage.SetCookieResult
)

storage.PartitionKey = {
  ? userContext: text,
  ? sourceOrigin: text,
  Extensible,
}

storage.GetCookiesResult = {
  cookies: [*network.Cookie],
  partitionKey: storage.PartitionKey,
}

storage.SetCookieResult = {
  partitionKey: storage.PartitionKey
}

storage.DeleteCookiesResult = {
  partitionKey: storage.PartitionKey
}

LogEvent = (
  log.EntryAdded
)

log.Level = "debug" / "info" / "warn" / "error"

log.Entry = (
  log.GenericLogEntry /
  log.ConsoleLogEntry /
  log.JavascriptLogEntry
)

log.BaseLogEntry = (
  level: log.Level,
  source: script.Source,
  text: text / null,
  timestamp: js-uint,
  ? stackTrace: script.StackTrace,
)

log.GenericLogEntry = {
  log.BaseLogEntry,
  type: text,
}

log.ConsoleLogEntry = {
  log.BaseLogEntry,
  type: "console",
  method: text,
  args: [*script.RemoteValue],
}

log.JavascriptLogEntry = {
  log.BaseLogEntry,
  type: "javascript",
}

log.EntryAdded = (
 method: "log.entryAdded",
 params: log.Entry,
)

InputResult = (
  input.PerformActionsResult /
  input.ReleaseActionsResult /
  input.SetFilesResult
)

InputEvent = (
  input.FileDialogOpened
)

input.PerformActionsResult = EmptyResult

input.ReleaseActionsResult = EmptyResult

input.SetFilesResult = EmptyResult

input.FileDialogOpened = (
   method: "input.fileDialogOpened",
   params: input.FileDialogInfo
)

input.FileDialogInfo = {
   context: browsingContext.BrowsingContext,
   ? userContext: browser.UserContext,
   ? element: script.SharedReference,
   multiple: bool,
}

WebExtensionResult = (
  webExtension.InstallResult /
  webExtension.UninstallResult
)

webExtension.Extension = text

webExtension.InstallResult = {
  extension: webExtension.Extension
}

webExtension.UninstallResult = EmptyResult

议题索引

肯定有更好的机制来做这种“等待事件”的事情。
我们是否应该有类似 microtasks 的东西,以确保它在事件循环上的任何其他任务之前运行?
这应该作为附录吗?
我们是否支持单个 session 有 > 1 个连接?
似乎没有任何东西定义 UTF-8 错误使用什么状态码
需要挂接到 session 结束,以允许 UA 在想要时关闭 listener。
定义 sandbox realm 的创建。这将返回一个包装 windowSandboxWindowProxy
详细定义 SandboxProxy 如何工作
定义其工作方式。
尚不清楚这是否是正式定义 user context 概念或其与 storage 交互的最佳方式。
我们是否应该规定具有非 null opener 的顶级 traversables 与其 opener 具有相同的关联用户上下文? 需要检查这是否是现有实现所强制执行的内容。
这是一种相当不精确的表述,但希望它清楚表达了这样的意图: 我们会在开始关闭连接之前把命令响应发送出去。
这也需要泛化为适用于 realms。
这也需要泛化为适用于 realms。
property 规定 ignore cache 标志如何工作。这需要 考虑是否只有资源的首次加载会绕过缓存 (即这是否类似于最初清空缓存然后照常继续),或者不是由 HTML parser 直接加载的资源(例如由脚本或样式表发起的加载)是否也绕过缓存。
我们在这里通过错误暴露了足够多关于失败内容和原因的信息吗? 我们想要什么错误代码?是否会出现这样的问题:local ends 解析 implementation-defined 字符串来弄清实际出了什么问题?
这应当以更明确的方式集成到 update rendering 算法中。
关于关闭最后一个顶级 traversable 时的行为,存在一个开放讨论。我们可以预期关闭 浏览器、关闭 session,或将其留给实现决定。 [w3c/webdriver-bidi 议题 #170]
这应当以更明确的方式集成到 update rendering 算法中。
按当前写法,该算法存在竞争条件,因为当我们尝试导航时, 目标 session history entry 可能已经不存在。一旦我们支持等待历史记录进行导航, 就可以更稳健地处理这一点。
我们是否想暴露 `browsingContext.pageShow 事件?那样的话, 不仅是在 bfcache restore 时,而是每当 `pageshow` 将要被发出时都需要调用它, 并且还要把 persisted 状态添加到数据中。
尚不清楚我们是否应只对具有 active documents 的 browsing contexts 触发此事件;navigation 也可能导致 contexts 变得不可访问, 但由于 bfcache 尚未被丢弃。
将此算法移动到 screen orientation 规范。
这会防止收集与 navigable 无关的数据。 我们仍然需要检索 navigable 来检查 collector 配置, 但这里仍可以接受 null。
这没有取消 auth 的方式。
我们是否应包含 realm 以外的参数?
和 Fetch 中一样,尚不清楚这是否是处理多个 headers、解析问题等的正确方式。
考虑除了 context 之外,还包括发起请求的 document node 的 `sharedId`。
考虑一个“request already sent”错误。
允许设置精确的错误种类 [议题 #508]
遵循 Fetch 的 “HTTP-network-or-cache fetch” 算法中的返回值。
这里的错误代码不对
这未处理孤立代理项
处理 “stale object reference” 情况。
添加 WASM 类型?
WindowProxy 是否应以类似 Node 的风格获得 attributes?
特殊处理 String / Number / 等包装对象?
重新考虑 mirror objects 的生命周期。
children 和 child nodes 是不同的东西。childNodeCount 要么应 引用 childNodes,要么应重命名为 childrenCount
这里的错误代码不对
这里的错误代码不对
TODO:添加 script.evaluate 中描述的 timeout 参数。
扩展此项以同样允许 realm parents,例如用于嵌套 workers?或者获取所有祖先 workers。
我们可能想要比只是 literal match 更复杂的过滤系统。
这里的顺序是否应该定义得更好?
我们想按 browsing context 还是 top-level traversable 来作为键? 差异在于:如果某个事件发生在 frame 中,而该 frame 在 local end 订阅顶级 navigable 的 log events 之前发生了导航,会发生什么。
很多其他东西也需要 logging。CDP 有 LogEntryAdded 类型:xml、 javascript、network、storage、appcache、rendering、security、deprecation、 worker、violation、intervention、recommendation、other。除了由不同方法表示的 js exception 和 console API 类型之外,还有这些类型。
允许 implementation-defined log 类型