屏幕唤醒锁 API

W3C 工作草案

关于本文档的更多信息
此版本:
https://www.w3.org/TR/2024/WD-screen-wake-lock-20241024/
最新发布版本:
https://www.w3.org/TR/screen-wake-lock/
最新编辑草案:
https://w3c.github.io/screen-wake-lock/
历史记录:
https://www.w3.org/standards/history/screen-wake-lock/
提交历史
测试套件:
https://wpt.live/screen-wake-lock/
实现报告:
https://www.w3.org/wiki/DAS/Implementations
编辑者:
Kenneth Rohde Christiansen (英特尔公司)
Marcos Cáceres (苹果公司)
前编辑者:
Raphael Kubo da Costa (英特尔公司)
(Yandex)
(Yandex)
反馈:
GitHub w3c/screen-wake-lock (拉取请求, 新建问题, 开放问题)
质量保证负责人
Wanming Lin (英特尔)

摘要

本文档规定了一个 API,允许 Web 应用请求屏幕唤醒锁。在合适的条件下并且获得许可后,屏幕唤醒锁可以防止系统关闭设备的屏幕。

本文档状态

本节描述了本文档在发布时的状态。当前 W3C 出版物列表及本技术报告的最新修订可在 W3C 技术报告索引 https://www.w3.org/TR/ 查阅。

实现者需要注意,此规范极不稳定。未参与讨论的实现者可能会发现规范发生了不兼容的更改。有兴趣在规范最终进入候选推荐阶段前进行实现的厂商,建议订阅 GitHub 仓库并参与讨论。

本文档由 设备与传感器工作组Web 应用工作组 以工作草案形式发布,采用推荐流程

作为工作草案发布,并不意味着 W3C 及其成员已认可。

本文档为草稿,随时可能被更新、替换或废弃。将本文档作为其他内容引用是不合适的,只能作为进展中的工作。

本文档由遵循W3C 专利政策的工作组产生。 W3C 维护着 公开专利披露列表(设备与传感器工作组)公开专利披露列表(Web 应用工作组) ,用于各工作组相关成果;这些页面也包括专利披露说明。任何知晓专利且认为其包含必要声明的人必须根据 W3C 专利政策第6节披露相关信息。

本文档遵循 2023年11月3日 W3C 流程文档管理。

1. 介绍

本节为非规范性内容。

现代操作系统通过积极的电源管理实现更长的电池续航,这意味着在用户活动缺失后不久,主设备可能会降低屏幕亮度、关闭屏幕,甚至让 CPU 进入深度省电状态,尽可能限制能耗。

虽然这有利于延长电池寿命,但有时会影响某些使用场景,例如扫码、阅读电子书、跟随菜谱、向观众演示等。参见 唤醒锁:使用场景

唤醒锁一般会阻止某些行为发生,但 UA(以及底层操作系统)可能会根据电池状态(连接电源、正在放电、低电量)对唤醒锁进行时限,或者在激活省电模式时直接禁止唤醒锁。

2. 唤醒锁

本规范定义了如下唤醒锁类型

  1. 屏幕唤醒锁用于防止屏幕关闭。只有可见文档可以获取屏幕唤醒锁。

在 API 中,唤醒锁类型通过 WakeLockType 枚举值表示。

注意

其它规范可能会定义不同的唤醒锁类型。

3. 策略控制

屏幕唤醒锁 API 定义了一个以字符串 "screen-wake-lock" 标识的策略控制特性。其默认允许列表'self'

注意

4. 权限与用户提示

[PERMISSIONS] API 为网站提供了统一的方式向用户请求权限,并查询现有权限。

用户代理可以因实现相关原因(如平台设置或用户偏好)拒绝唤醒锁 某一特定唤醒锁类型,针对某一特定 Document

建议用户代理以不打扰用户的方式,显示唤醒锁处于激活状态的通知,并为用户提供阻止进行中的操作或直接关闭通知的手段。

4.1 "screen-wake-lock" 强大功能

"screen-wake-lock" 强大功能启用本规范定义的能力。

4.2 权限算法

"screen-wake-lock" 强大功能定义了权限撤销算法。要调用屏幕唤醒锁权限撤销算法,请执行以下步骤:

  1. document当前全局对象关联 Document
  2. lockListdocument.[[ActiveLocks]]["screen"]。
  3. 对于 locklockList 中的每一项:
    1. documentlock 和 "screen" 运行释放唤醒锁

5. 概念

本规范中提及的任务源屏幕唤醒锁任务源

平台唤醒锁指的是用户代理与之交互以查询状态、获取和释放唤醒锁的平台接口。

平台唤醒锁可以由底层平台(如原生唤醒锁框架)定义,也可以由用户代理实现(如果其具备硬件控制能力)。

6. Document 接口扩展

6.1 内部插槽

内部插槽 初始值 描述
[[ActiveLocks]] 一个 有序映射,将唤醒锁类型映射为空列表 一个 有序映射,将唤醒锁类型映射为 WakeLockSentinel 对象列表,这些对象与本Document相关联。

8. WakeLock 接口

WakeLock 接口允许文档获取 屏幕唤醒锁

WebIDL[SecureContext, Exposed=(Window)]
interface WakeLock {
  Promise<WakeLockSentinel> request(optional WakeLockType type = "screen");
};

8.1 request() 方法

request(type) 方法的步骤如下:

  1. documentthis相关全局对象关联 Document
  2. 如果 document 不是 完全激活,则返回 一个被拒绝的 promise,包含 "NotAllowedError" DOMException
  3. 如果 document 不被允许使用名为 "screen-wake-lock" 的 策略控制特性,则返回 一个被拒绝的 promise,包含 "NotAllowedError" DOMException
  4. 如果 用户代理对该 type 拒绝该 document 的唤醒锁, 则返回 一个被拒绝的 promise,包含 "NotAllowedError" DOMException
  5. 如果 document可见性状态为 "hidden",则返回 一个被拒绝的 promise,包含 "NotAllowedError" DOMException
  6. promise一个新的 promise
  7. 并行运行以下步骤:
    1. state请求使用 "screen-wake-lock" 的结果。
    2. 如果 state 为 "denied",则:
      1. 屏幕唤醒锁任务源 上针对 document相关全局对象 队列一个任务,拒绝 promise,错误为 "NotAllowedError" DOMException
      2. 中止这些步骤。
    3. 屏幕唤醒锁任务源 针对 document相关全局对象 队列一个任务,运行以下步骤:
      1. 如果 document 不是 完全激活,则:
        1. 拒绝 promise,错误为 "NotAllowedError" DOMException
        2. 中止这些步骤。
      2. 如果 document可见性状态为 "hidden",则:
        1. 拒绝 promise,错误为 "NotAllowedError" DOMException
        2. 中止这些步骤。
      3. 如果 document.[[ActiveLocks]]["screen"] 为空,则并行执行以下步骤:
        1. 使用 "screen" 调用 获取唤醒锁
          注意
      4. lock 为一个新的 WakeLockSentinel 对象,其 type 属性设为 type
      5. lock 添加到 document.[[ActiveLocks]]["screen"]。
      6. lock 解析 promise
  8. 返回 promise

9. WakeLockSentinel 接口

WebIDL[SecureContext, Exposed=(Window)]
interface WakeLockSentinel : EventTarget {
  readonly attribute boolean released;
  readonly attribute WakeLockType type;
  Promise<undefined> release();
  attribute EventHandler onrelease;
};

WakeLockSentinel 对象用于操作 平台唤醒锁,并在手动释放或底层 平台唤醒锁被释放前一直保持。它的存在会维持某个 平台唤醒锁在指定 唤醒锁类型下处于激活状态,释放所有该类型的 WakeLockSentinel 实例后,底层 平台唤醒锁也会被释放。

注意

9.1 内部插槽

WakeLockSentinel 实例会创建如下 内部插槽

内部插槽 初始值 描述(非规范性)
[[Released]] false 指定的 WakeLockSentinel 是否已被释放。

9.2 released 属性

released getter 步骤是返回 this.[[Released]]

注意

9.3 type 属性

type getter 步骤是返回 this唤醒锁类型

9.4 release() 方法

release() 方法步骤如下:

  1. 如果 this[[Released]]false, 则以 lockthistypethistype 属性,运行 释放唤醒锁
  2. 返回 一个解析为 undefined 的 promise。

9.5 onrelease 属性

onrelease 属性是 "onrelease" 事件处理器 IDL 属性,其 事件处理器事件类型为 "release"。

用于通知脚本某个 WakeLockSentinel 对象的句柄已被释放,无论是通过调用 release() 方法,还是由 用户代理释放唤醒锁。

注意
注意

9.6 垃圾回收

当一个 WakeLockSentinel 对象注册了一个或多个 "release" 事件监听器,且该对象尚未被释放时, 必须Window 对象(调用构造函数的窗口) 到该 WakeLockSentinel 对象保持强引用。

当通过某个 WakeLockSentinel 对象在 屏幕唤醒锁任务源上排队了一个任务时, 必须Window 对象(构造函数的窗口) 到该 WakeLockSentinel 对象保持强引用。

10. WakeLockType 枚举

为了描述唤醒锁类型,本规范定义了以下枚举来表示唤醒锁类型

WebIDLenum WakeLockType { "screen" };
screen
屏幕唤醒锁类型。

11. 唤醒锁管理

本节同等且独立地适用于每一种唤醒锁类型,除非明确提及了某个特定的唤醒锁类型

用户代理获取唤醒锁的方式是请求底层操作系统应用该锁。不会检查对底层操作系统请求的可能返回值。换言之,用户代理必须将唤醒锁的获取视为仅供建议

相反,用户代理释放唤醒锁的方式,是请求底层操作系统不再应用该唤醒锁。只有当对操作系统的请求成功时,才认为该锁已被释放。

当操作系统的状态允许应用该锁(例如电量充足)时,唤醒锁即为适用

在用户手动关闭屏幕后,屏幕唤醒锁不得适用,直到屏幕再次被打开。

注意

11.1 自动释放唤醒锁

用户代理可在任何时候释放唤醒锁。例如,在以下情况下:

11.2 处理文档失去全部活动

当一个Document document不再完全激活时,用户代理必须执行以下步骤:

  1. 对于 lockdocument.[[ActiveLocks]]["screen"] 中的每一项:
    1. documentlock 和 "screen" 运行 释放唤醒锁

11.3 处理文档失去可见性

本规范定义了以下页面可见性更改步骤,给定可见性状态statedocument

  1. 如果 state 不是 "hidden",则中止这些步骤。
  2. 对于 lockdocument.[[ActiveLocks]]["screen"] 中的每一项:
    1. documentlock 和 "screen" 运行 释放唤醒锁

11.4 获取唤醒锁算法

要为给定的 type获取唤醒锁, 执行以下步骤:

  1. 如果类型为 type 的唤醒锁不可适用,中止这些步骤。
  2. 请求底层操作系统获取该唤醒锁,类型为 type

11.5 释放唤醒锁算法

要为给定的 documentlocktype释放唤醒锁, 执行以下步骤:

  1. 如果 document.[[ActiveLocks]][type] 不包含 lock,中止这些步骤。
  2. document.[[ActiveLocks]][type] 中移除 lock
  3. 如果 document.[[ActiveLocks]][type] 为空,则并行执行以下步骤:
    1. 请求底层操作系统释放类型为该 type 的唤醒锁,并令 success 在操作成功时为 true,否则为 false
    2. 如果 successtruetype"screen",则执行以下操作:
      1. 重置平台特定的不活动计时器,以便在该时间后屏幕才会真正关闭。
      注意
  4. lock[[Released]]设为 true
  5. 触发一个事件,名称为 "release",目标为 lock

12. 安全与隐私注意事项

屏幕唤醒锁可能导致各类设备组件——尤其是显示器——以高于平时的功耗运行。这可能带来不良影响,例如阻止设备自动锁定以及更快的电量消耗。对移动设备而言,更快的电量消耗尤为令人担忧,因为它们通常无法随时获得固定电源。电量在意外时刻耗尽,可能导致用户无法拨打或接听电话以及使用网络服务,包括紧急呼叫服务。

在某些情况下(例如电池容量较低,或用户将设备置于省电模式),实现可以忽略屏幕唤醒锁请求。

建议用户代理提供某种界面或指示器,使用户能够知道屏幕唤醒锁何时处于活动状态。提供此类界面有助于终端用户识别某个特定 Web 应用是否对设备产生了负面的能耗影响,并在需要时采取措施。

13. 示例

本节为非规范性内容。

示例 1:获取并释放屏幕唤醒锁
function tryKeepScreenAlive(minutes) {
  navigator.wakeLock.request("screen").then(lock => {
    setTimeout(() => lock.release(), minutes * 60 * 1000);
  });
}

tryKeepScreenAlive(10);

本示例允许用户通过点击复选框来请求屏幕唤醒锁,但在唤醒锁状态变化时会更新复选框的选中状态:

const checkbox = document.createElement("input");
checkbox.setAttribute("type", "checkbox");
document.body.appendChild(checkbox);

const sentinel = await navigator.wakeLock.request("screen");
checkbox.checked = !sentinel.released;
sentinel.onrelease = () => checkbox.checked = !sentinel.released;

在此示例中,创建了两个不同的唤醒锁请求,并分别释放:

let lock1 = await navigator.wakeLock.request("screen");
let lock2 = await navigator.wakeLock.request("screen");

lock1.release();
lock2.release();

14. 一致性

除标记为非规范性的章节外,本规范中的所有作者指南、图示、示例和注记均为非规范性内容。除此之外的所有内容均为规范性内容。

本文档中的关键词 MAYMUSTMUST NOTRECOMMENDED 应按 BCP 14 [RFC2119] 与 [RFC8174] 的描述进行解释,并且仅当它们如这里所示全部大写时才应用这些解释。

本规范为单一产品定义了一致性标准:实现其中接口的 用户代理

A. 致谢

本节为非规范性内容。

我们谨向 Mounir Lamouri、Sergey Konstantinov、Matvey Larionov、Dominique Hazael-Massieux、Domenic Denicola、Thomas Steiner、Anne van Kesteren 对本工作的贡献致以诚挚的感谢。

B. 变更

本节为非规范性内容。

本节记录了自先前发布以来的变更。

B.1 自 2017 年 12 月 14 日 CR 以来的变更

C. 索引

C.1 本规范定义的术语

C.2 引用定义的术语

D. IDL 索引

WebIDL[SecureContext]
partial interface Navigator {
  [SameObject] readonly attribute WakeLock wakeLock;
};

[SecureContext, Exposed=(Window)]
interface WakeLock {
  Promise<WakeLockSentinel> request(optional WakeLockType type = "screen");
};

[SecureContext, Exposed=(Window)]
interface WakeLockSentinel : EventTarget {
  readonly attribute boolean released;
  readonly attribute WakeLockType type;
  Promise<undefined> release();
  attribute EventHandler onrelease;
};

enum WakeLockType { "screen" };

E. 参考文献

E.1 规范性参考

[dom]
DOM Standard. Anne van Kesteren. WHATWG. Living Standard. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript Language Specification. Ecma International. URL: https://tc39.es/ecma262/multipage/
[html]
HTML Standard. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[infra]
Infra Standard. Anne van Kesteren; Domenic Denicola. WHATWG. Living Standard. URL: https://infra.spec.whatwg.org/
[PERMISSIONS]
Permissions. Marcos Caceres; Mike Taylor. W3C. 19 March 2024. W3C Working Draft. URL: https://www.w3.org/TR/permissions/
[PERMISSIONS-POLICY]
Permissions Policy. Ian Clelland. W3C. 25 September 2024. W3C Working Draft. URL: https://www.w3.org/TR/permissions-policy-1/
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels. S. Bradner. IETF. March 1997. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc2119
[RFC8174]
Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words. B. Leiba. IETF. May 2017. Best Current Practice. URL: https://www.rfc-editor.org/rfc/rfc8174
[WEBIDL]
Web IDL Standard. Edgar Chen; Timothy Gu. WHATWG. Living Standard. URL: https://webidl.spec.whatwg.org/

E.2 说明性参考

[wake-lock-use-cases]
Wake Lock: Use cases. Marcos Caceres; Natasha Rooney; Dominique Hazaël-Massieux. W3C. 14 August 2014. W3C Working Group Note. URL: https://www.w3.org/TR/wake-lock-use-cases/