能力委托

社区组报告草案

此版本:
https://wicg.github.io/capability-delegation/spec.html
问题跟踪:
GitHub
编辑:
Google Canada

摘要

将使用受限 API 的能力转移给另一个窗口。

本文档状态

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

1. 引言

本节为非规范性内容。

本规范定义了一种机制,脚本可通过该机制将其调用受限 API 的 能力委托给它信任的另一个浏览上下文。这里 关注的是一种动态委托机制,它以受时间约束的方式,将被委托的 能力暴露给目标浏览上下文

1.1. 什么是能力委托?

Web 中的许多能力可以通过 JS 以受限方式使用。例如:

能力委托意味着允许一个框架动态放弃其调用受限 API 的 能力,并将该能力转移给它可以信任的另一个(子)框架。 这里的“dynamic”一词表示委托的效果会持续 一段由被委托能力定义的有限时间。这不同于通过 浏览 上下文中的 iframe allow 属性,对子框架进行能力的静态(加载时)暴露,在这种情况下,该能力会以 不受时间约束的方式暴露给子框架。

1.2. 发起委托与使用能力

能力委托需要两个不同的步骤才能生效。第一步 是“发起”,其中一个浏览上下文通知另一个浏览 上下文有某个特定能力正在被委托。发起之后, 第二个(即接收者)浏览上下文将“使用”被委托的 能力,这通常意味着调用一个由能力定义的方法。虽然 此处的能力委托规范未定义第二步中使用的 API 接口, 但它重新定义了该 API 的内部行为。

因此,本规范由两个不同部分组成:定义用于 发起步骤的 API,然后为一个特定的“使用者”API 定义被委托行为。 对于第二部分,本规范重点关注 Payment Request API 中所需的行为变更,该 API 将 作为未来其他任何会利用能力委托的 API 中类似变更的指南。

1.3. 瞬态可用性

上述两个步骤本质上都受时间约束:

  1. 发起步骤会消耗激活, 因此该步骤只允许在最近发生用户激活之后执行。 此外,此处对用户激活的消耗保证了 委托机制不能在每次用户激活中被使用多于一次。这 防止能力委托被恶意使用,例如反复向多个框架进行委托 尝试,从而有效绕过被委托 API 的用户激活 限制。

  2. 发起步骤成功完成之后,被委托的 API 只会在目标浏览上下文中可供使用几 秒。这里的确切时间限制取决于被委托 API 如何在其自身规范中定义被委托行为。对于 未定义自身时间限制的 API,默认限制将与用户 激活 过期相同。

2. 示例

当某个站点想要在鼠标点击后, 将调用 [payment-request] show() 的能力委托给子框架时,它将向该子框架发布消息, 并带有一个额外的 选项来指定被委托的能力:
window.onclick = () => {
  targetWindow.postMessage('a_message', {delegate: "payment"});
};

收到该消息后,即使该框架没有收到用户 激活,子框架也能够使用 show()

window.onmessage = () => {
  const payRequest = new PaymentRequest(...);
  const payResponse = await payRequest.show();
  ...
}

3. 发起能力委托

当某个浏览上下文想要将某项能力委托给另一个浏览 上下文时,它会向第二个浏览上下文发布消息,并带有一个名为 delegate 的额外 WindowPostMessageOptions 来指定该能力。此选项的值必须是一个feature-identifier。 如果该值不对应任何用户代理支持的 特性,则必须 忽略该选项。

可能的 feature-identifier 值列表见此处

3.1. 对 HTML 规范的猴子补丁

WindowPostMessageOptions IDL 定义将包含一个额外字段,如下所示:

DOMString? delegate;

window post message 的算法中, 以下步骤:

  1. transferoptions["transfer"]。

后面将跟随如下两个额外步骤:

  1. delegateoptions["delegate"]。

  2. 如果 delegate 不为 null,则:

    1. 如果用户代理不支持委托由 delegate 指示的特性, 则抛出一个 "NotSupportedError" DOMException。

    2. 如果 targetWindow关联 Document 不被allowed-to-usedelegate 指示的特性,则抛出一个 "NotAllowedError" DOMException。

    3. 如果 targetOrigin 是单个 U+002A ASTERISK 字符 (*),则抛出一个 "NotAllowedError" DOMException。

      targetOrigin 的默认值为 "/",它将消息限制为同源目标。使用 "*" 之外字符串的额外要求意味着 跨源消息必须指定其所针对的具体源。
    4. sourceincumbentSettings全局对象

    5. 如果 source 不具有瞬态 激活, 则抛出一个 "NotAllowedError" DOMException。

    6. source消耗 用户 激活

4. 跟踪被委托的能力

委托给某个浏览上下文的能力将使用一个名为 Window.DELEGATED_CAPABILITY_TIMESTAMPS 的映射来跟踪。每次将能力 委托给某个 Window 时, 都会在 DELEGATED_CAPABILITY_TIMESTAMPS 中添加一个条目,其键等于 表示该 能力的 feature-identifier, 值等于当前 DOMHighResTimeStamp。 如果该映射 已经有相同键的条目,则现有值将更新为 当前 DOMHighResTimeStamp

4.1. 对 HTML 规范的猴子补丁

window post message 的算法之前, 将插入一个新段落,如下所示:

为了跟踪委托给某个浏览上下文的能力, 每个 Window 都有一个从 feature-identifierDOMHighResTimeStamp映射,名为 DELEGATED_CAPABILITY_TIMESTAMPS。 该映射初始化为空映射。

window post message 的算法中, 将向当前步骤 8 添加两个额外子步骤。第一个额外 子步骤将插入在以下子步骤之后:

  1. 排入一个全局任务 ...

    1. 令 origin 为 incumbentSettings 的 origin 的序列化。

如下所示:

  1. 排入一个全局任务 ... (不变)

    1. delegateoptions["delegate"]。

第二个额外子步骤将插入在以下子步骤之后:

  1. 排入一个全局任务 ...

    1. 令 newPorts 为一个由 ... 组成的新冻结数组

如下所示:

  1. 排入一个全局任务 ... (不变)

    1. 令 newPorts 为一个由 ... 组成的新冻结数组 (除 编号外不变)

    2. 如果 delegate 不为 null,且用户代理支持 委托 delegate,则将 DELEGATED_CAPABILITY_TIMESTAMPS[delegate] 设置为当前 高分辨率 时间

5. 定义被委托能力的行为

任何定义了被委托行为的能力,都会以适合该 能力的方式使用 Window.DELEGATED_CAPABILITY_TIMESTAMPS 中的相应条目。 下面是某个特定能力所需的规范变更。

5.1. 对 Payment Request 规范的猴子补丁

show() 的算法中, 以下步骤将被 替换,以实现被委托行为:

这两个步骤:

  1. 如果 request 的相关全局对象不具有瞬态激活:

    1. 返回一个以 "SecurityError" DOMException 拒绝的 promise。

  2. 消耗相关全局对象的用户激活。

将由以下三个步骤替换:

  1. 如果 request 的相关全局对象不具有瞬态 激活, 且相关全局对象中的时间戳 DELEGATED_CAPABILITY_TIMESTAMPS["payment"] 要么未定义,要么已过期

    1. 返回一个以 "SecurityError" DOMException 拒绝的 promise。

  2. 如果 request 的相关全局对象不具有瞬态激活, 则清除映射条目 DELEGATED_CAPABILITY_TIMESTAMPS["payment"]。

  3. 否则,消耗 相关全局对象的用户 激活

5.2. 对 Fullscreen 规范的猴子补丁

requestFullscreen() 的算法中, 将进行以下变更, 以实现被委托行为:

步骤 5 中的最后一个条件:

  1. 如果以下任一条件为 false,则将 error 设置为 true:...

    • this 的相关全局对象具有瞬态激活,或者 该算法由用户生成的方向变化触发。

将被替换为:

  1. 如果以下任一条件为 false,则将 error 设置为 true:... (不变)

    • this 的相关全局对象具有瞬态激活,或者 this 的相关全局对象中的时间戳 DELEGATED_CAPABILITY_TIMESTAMPS["fullscreen"] 既不是 undefined,也没有过期, 或者 该算法由用户生成的方向变化触发。

在步骤 10 之前:

  1. 令 fullscreenElements 为一个有序集,初始仅包含 this。

将插入以下新步骤:

  1. 如果 this 的相关全局对象不具有瞬态激活,则清除 this 的相关全局对象中的映射条目 DELEGATED_CAPABILITY_TIMESTAMPS["fullscreen"]。

  2. 令 fullscreenElements 为一个有序集,初始仅包含 this。(除 编号外不变)

5.3. [SCREEN-CAPTURE] 规范的猴子补丁

getDisplayMedia() 的算法中, 将进行以下变更, 以实现被委托行为:

步骤 3 中的条件:

  1. 如果 this 的相关全局对象不具有瞬态激活,则返回一个以 name 属性值为 InvalidStateError 的 DOMException 对象拒绝的 promise。

将被替换为:

  1. 如果 this 的相关全局对象不具有瞬态激活,且 this 的相关全局对象中的时间戳 DELEGATED_CAPABILITY_TIMESTAMPS["display-capture"] 要么未定义,要么已过期, 则返回一个以 拒绝的 promise,其拒绝原因是一个 DOMException 对象,且其 name 属性的值为 InvalidStateError

一致性

文档 约定

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

除明确标记为非规范性的节、示例和注记之外, 本规范的全部文本都是规范性的。[RFC2119]

本规范中的示例用“for example”一词引入, 或者使用 class="example" 与规范性文本分开, 如下所示:

这是一个信息性示例的例子。

信息性注记以“Note”一词开头, 并使用 class="note" 与规范性文本分开, 如下所示:

Note,这是一个信息性注记。

一致性 算法

作为算法一部分以命令式措辞表达的要求 (例如“strip any leading space characters” 或“return false and abort these steps”) 应解释为具有引入该算法时所使用的关键词 (“must”、“should”、“may”等)的含义。

以算法或特定步骤形式表述的一致性要求 可以用任何方式实现, 只要最终结果等价即可。 特别是,本规范中定义的算法旨在易于理解, 并不旨在具有高性能。 鼓励实现者进行优化。

索引

由本 规范定义的术语

由引用 定义的术语

参考文献

规范性参考文献

[FULLSCREEN]
Philip Jägenstedt。Fullscreen API 标准。 现行标准。URL:https://fullscreen.spec.whatwg.org/
[HR-TIME-3]
Yoav Weiss。高分辨率时间。URL:https://w3c.github.io/hr-time/
[HTML]
Anne van Kesteren;等。HTML 标准。 现行标准。URL:https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren;Domenic Denicola。Infra 标准。现行标准。URL:https://infra.spec.whatwg.org/
[PAYMENT-REQUEST-1.1]
Marcos Caceres;Rouslan Solomakhin;Ian Jacobs。Payment Request API 1.1。URL:https://w3c.github.io/payment-request/
[PERMISSIONS-POLICY-1]
Ian Clelland。权限 策略。URL:https://w3c.github.io/webappsec-permissions-policy/
[RFC2119]
S. Bradner。用于在 RFC 中 表示要求等级的关键词。1997 年 3 月。当前最佳实践。URL:https://datatracker.ietf.org/doc/html/rfc2119
[SCREEN-CAPTURE]
Jan-Ivar Bruaroey;Elad Alon。屏幕 捕获。URL:https://w3c.github.io/mediacapture-screen-share/
[WebCryptoAPI]
Mark Watson。Web Cryptography API。URL:https://w3c.github.io/webcrypto/
[WEBIDL]
Edgar Chen;Timothy Gu。Web IDL 标准。现行标准。URL:https://webidl.spec.whatwg.org/

信息性参考文献

[PAYMENT-REQUEST]
Marcos Caceres;Rouslan Solomakhin;Ian Jacobs。Payment Request API。URL:https://w3c.github.io/payment-request/