This document specifies an API that allows web applications to request
a wake lock. A wake lock prevents some aspect of the device from
entering a power-saving state (e.g., preventing the system from turning
off the screen).
Implementors need to be aware that this specification is extremely
unstable. Implementors who are not taking part in the
discussions will find the specification changing out from under them in
incompatible ways. Vendors interested in implementing this
specification before it eventually reaches the Candidate Recommendation
phase should subscribe to the repository
on GitHub and take part in the discussions.
Introduction
Modern operating systems achieve longer battery life by implementing
aggressive power management, meaning that shortly after the lack of
user activity, a host device may lower the screen brightness, turn the
screen off and even let the CPU go into a deep power state, allowing to
sip as little power as possible.
Though this is great for prolonged battery life, it can sometime hinder
good, valid use-cases such as:
Use turn-by-turn navigation while walking and driving and not
interacting with the phone.
Allow an external device to read a boarding card with a barcode on
a phone.
Showing a presentation where each slide is shown for a prolonged
period.
Perform longer computations before the device goes into deep sleep
mode, such as media processing.
A wake lock will generally prevent something from happening, but UAs
(and the underlying OS) may time limit a wake lock given the battery
status (wall power connected, discharging, low battery level), or even
disallow wake locks in the case a power saving mode is activated.
Any active wake lock MUST also prevent the page from entering UA
induced CPU suspension as
defined by [[PAGE-LIFECYCLE]].
This specification defines the following wake lock types:
A screen wake lock prevents the screen from turning off.
Only visible documents can acquire the wake lock.
A system wake lock prevents the CPU from entering a deep
power state. This may also prevent communication chips such as cellular
or Wi-Fi from sleeping.
A user agent can deny a wake lock of a
particular wake lock type for a particular {{Document}} by any
implementation-specific reason, for example, a user or platform setting
or preference.
The [[PERMISSIONS]] API provides a uniform way for websites to request
permissions from users and query which permissions they have.
It is recommended that a UA shows some form of unobtrusive notification
that informs the user when a wake lock is active, as well as provides
the user with the means to block the ongoing operation, or
simply dismiss the notification.
To obtain permission for wake lock type |type|, run
these steps in parallel. This async algorithm returns either
{{PermissionState["granted"]}} or {{PermissionState["denied"]}}.
Let |permissionDesc:WakeLockPermissionDescriptor| be a newly
created {{WakeLockPermissionDescriptor}}.
Set |permissionDesc|'s {{PermissionDescriptor/name}} member to
"`wake-lock`".
Set |permissionDesc|'s {{WakeLockPermissionDescriptor/type}} to
|type|.
Let |resultPromise:Promise| be the result of running query a
permission with |permissionDesc|.
Await |resultPromise| to settle.
If |resultPromise| rejects, return {{PermissionState["denied"]}}.
Otherwise, let |status:PermissionStatus| be the result of
|resultPromise|.
Let |state:PermissionState| be the value of
|status|.{{PermissionStatus/state}}.
If |state| is {{PermissionState["prompt"]}}, run the following
steps:
If the current global object is not a {{Window}},
return {{PermissionState["denied"]}}.
If the current global object does not have [=transient
activation=], return {{PermissionState["denied"]}}.
The term platform wake lock refers to platform interfaces
with which the user agent interacts to query state and acquire and
release a wake lock.
A platform wake lock can be defined by the underlying platform
(e.g. in a native wake lock framework) or by the user agent, if it has
direct hardware control.
Let |document:Document| be the [=environment settings object /
responsible document=] of the current settings object.
If
|document| is not allowed to use the policy-controlled
feature named "`wake-lock`", reject |promise| with a
{{"NotAllowedError"}} {{DOMException}} and return |promise|.
If the user agentdenies the wake lock of this
|type| for |document|, reject |promise| with a
{{"NotAllowedError"}} {{DOMException}} and return |promise|.
If the current global object's
[=WorkerGlobalScope/owner set=] [= list/is empty =], reject
|promise| with a {{"NotAllowedError"}} {{DOMException}} and
return |promise|.
If |type| is {{ WakeLockType["screen"] }}, reject |promise|
with a {{"NotAllowedError"}} {{DOMException}}, and return
|promise|.
If the |document|'s [=Document/browsing context=] is `null`,
reject |promise| with a {{"NotAllowedError"}} {{DOMException}}
and return |promise|.
If |document| is not [=Document/fully active=], reject
|promise| with a {{"NotAllowedError"}} {{DOMException}}, and
return |promise|.
If |type| is {{WakeLockType["screen"] }} and |document| is
hidden, reject |promise| with a {{"NotAllowedError"}}
{{DOMException}}, and return |promise|.
Run the following steps in parallel, but abort when
|type| is {{WakeLockType["screen"]}} and |document| is hidden:
Let |state:PermissionState| be the result of awaiting
obtain permission steps with |type|:
If |state| is {{PermissionState["denied"]}}, then reject
|promise| with a {{"NotAllowedError"}} {{DOMException}}, and
abort these steps.
Let |lock:WakeLockSentinel| be a new {{WakeLockSentinel}}
object with its {{WakeLockSentinel/type}} attribute set to
|type|.
Let |success:boolean| be the result of awaiting acquire a
wake lock with |lock| and |type|:
If |success| is `false` then reject |promise| with a
{{"NotAllowedError"}} {{DOMException}}, and abort these
steps.
Run release wake lock with |lock:WakeLockSentinel| set
to this object and |type:WakeLockType| set to the value of this
object's {{WakeLockSentinel/type}} attribute.
It is used to notify scripts that a given {{WakeLockSentinel}}
object's handle has been released, either due to the
{{WakeLockSentinel/release()}} method being called or because the
wake lock was released by the user agent.
Managing Wake Locks
This section applies to each wake lock type equally and
independently, unless a particular wake lock type is explicitly
mentioned.
The user agent acquires the wake
lock by requesting the underlying operating system to apply the
lock. The lock is considered acquired only when the request to the
operating system succeeds.
Conversely, the user agent releases the wake lock by requesting the
underlying operating system to no longer apply the wake lock. The lock
is considered released only when the request to the operating system
succeeds.
The wake lock is applicable if the state of
the operating system permits application of the lock (e.g. there is
sufficient battery charge).
The screen wake lock MUST NOT be applicable after the
screen is manually switched off by the user until it is switched on
again. Manually switching off the screen MUST NOT affect the
applicability of the system wake lock.
Detects abnormal operation: such as infinite loops and tasks
exceeding imposed time limits (if any).
Battery is considered low and discharging.
The user turns on some kind of device power conservation mode.
Handling document loss of full activity
When the user agent determines that a [=environment settings object /
responsible document=] of the current settings object is no
longer [=Document/fully active=], it must run these steps:
Let |document:Document| be the [=environment settings object /
responsible document=] of the current settings object.
When the user agent determines that the visibility state of
the [=environment settings object / responsible document=] of the
current settings object changes, it must run these steps:
Let |document:Document| be the [=environment settings object /
responsible document=] of the current settings object.
If |document|'s visibility state is `"visible"`, abort
these steps.
To acquire a wake lock for a given |lock:WakeLockSentinel|
and |type:WakeLockType|, run these steps in parallel:
If the wake lock for type |type| is not applicable, return
`false`.
Set |active:boolean| to `true` if the platform wake lock
has an active wake lock for |type|.
Otherwise, ask the underlying operation system to acquire the
wake lock of type |type| and set |active| to `true` if the
operation succeeded, or else `false`.
If |active| is `true`:
Let |document:Document| be the [=environment settings object
/ responsible document=] of the current settings object.
Ask the underlying operation system to release the wake lock
of type |type| and let |success:boolean| be `true` if the
operation succeeded, or else `false`.
If |success| is `true` and |type| is `"screen"` run the
following:
Reset the platform-specific inactivity timer after which
the screen is actually turned off.
Application of a wake lock causes various device components such as
display or CPU to operate at higher power levels than they otherwise
would. This can lead to undesirable and potentially dangerous effects
such as excessive heating and faster than normal battery charge
depletion. The latter is particularly relevant to mobile devices which
may not have a stationary power source readily available. Complete
battery depletion at an unexpected time can lead to inability of the
user to make or receive calls and use network services, including the
emergency call service. Implementations should consider preventing wake
lock application if they determine that the remaining battery capacity
is low.
When the user agent does not acquire wake lock even
though a browsing context has requested it, this can be observed by the
browsing context and can possibly disclose sensitive information about
the state of the device such as that battery level is low.
This example allows the user to request a screen wake lock by clicking
on a checkbox, but updates the checkbox checked state in case the wake
lock state changes:
In this example, two different wake lock requests are created and
released independently:
let lock1 = await navigator.wakeLock.request("screen");
let lock2 = await navigator.wakeLock.request("screen");
lock1.release();
lock2.release();
Dependencies
Document's hidden attribute,
and visibility
state are defined in [[PAGE-VISIBILITY]].
This specification defines conformance criteria for a single product: a
user agent that implements the interfaces that it contains.
Acknowledgments
We would like to offer our sincere thanks to Mounir Lamouri, Sergey
Konstantinov, Matvey Larionov, Dominique Hazael-Massieux, Domenic
Denicola, Thomas Steiner, Raphael Kubo da Costa for their contributions
to this work.