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:

More use-cases can be found in Use Cases and Requirements.

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:

  1. A screen wake lock prevents the screen from turning off. Only visible documents can acquire the wake lock.
  2. 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.

Policy control

The Wake Lock API defines a policy-controlled feature identified by the string `"wake-lock"`. Its default allowlist is `["self"]`.

Permissions and user prompts

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.

The WakeLockPermissionDescriptor dictionary

The `"wake-lock"` powerful feature is defined as follows:

The permission descriptor type is represented by the WakeLockPermissionDescriptor dictionary, which extends the {{PermissionDescriptor}} with a type member, allowing for more fine-grained permissions.

          dictionary WakeLockPermissionDescriptor : PermissionDescriptor {
            required WakeLockType type;
          };
        

The {{PermissionDescriptor.name}} is `"wake-lock"`.

Permission algorithms

To block a permission, run these steps:

  1. Let |document:Document| be the [=environment settings object / responsible document=] of the current settings object.
  2. Let |descriptor:WakeLockPermissionDescriptor| be an instance of {{WakeLockPermissionDescriptor}}.
  3. Set |descriptor|'s permission state to {{PermissionState["denied"]}}.
  4. Let |type| be |descriptor|'s {{WakeLockPermissionDescriptor/type}} member.
  5. Let |record| be the platform wake lock's state record associated with |document| and |type|.
  6. [=list/For each=] |lock:WakeLockSentinel| in |record|.{{[[ActiveLocks]]}}:
    1. Run release a wake lock with |lock| and |type|.

To obtain permission for wake lock type |type|, run these steps in parallel. This async algorithm returns either {{PermissionState["granted"]}} or {{PermissionState["denied"]}}.

  1. Let |permissionDesc:WakeLockPermissionDescriptor| be a newly created {{WakeLockPermissionDescriptor}}.
  2. Set |permissionDesc|'s {{PermissionDescriptor/name}} member to "`wake-lock`".
  3. Set |permissionDesc|'s {{WakeLockPermissionDescriptor/type}} to |type|.
  4. Let |resultPromise:Promise| be the result of running query a permission with |permissionDesc|.
  5. Await |resultPromise| to settle.
  6. If |resultPromise| rejects, return {{PermissionState["denied"]}}.
  7. Otherwise, let |status:PermissionStatus| be the result of |resultPromise|.
  8. Let |state:PermissionState| be the value of |status|.{{PermissionStatus/state}}.
  9. If |state| is {{PermissionState["prompt"]}}, run the following steps:
    1. If these obtain permission steps were not triggered by user activation, return {{PermissionState["denied"]}}.
    2. Return the result of requesting permission to use with |permissionDesc|.
  10. Otherwise, return |state|.

The WakeLockType enum

For the purpose of wake lock type description, this specification defines the following enumeration:

        enum WakeLockType { "screen", "system" };
      
screen
Screen wake lock type.
system
System wake lock type.

Concepts and state record

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.

Each platform wake lock (one per wake lock type) has an associated state record per [=environment settings object / responsible document=] with the following internal slots:

Internal slot Initial value Description (non-normative)
[[\ActiveLocks]] The empty list. A list of {{WakeLockSentinel}} objects, representing active wake locks associated with the [=environment settings object / responsible document=].

Extensions to the `Navigator` interface

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

The wakeLock attribute's getter, when invoked, MUST return the same instance of the WakeLock object.

Extensions to the `WorkerNavigator` interface

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

The wakeLock attribute's getter, when invoked, MUST return the same instance of the WakeLock object.

The WakeLock interface

The {{WakeLock}} interface allows the page to acquire wake locks of a particular type.

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

The request() method

The request(|type:WakeLockType|) method, when invoked, MUST run the following steps:

  1. Let |promise:Promise| be a new promise.
  2. Let |document:Document| be the [=environment settings object / responsible document=] of the current settings object.
    1. If |document| is not allowed to use the policy-controlled feature named "`wake-lock`", reject |promise| with a {{"NotAllowedError"}} {{DOMException}} and return |promise|.
    2. If the user agent denies the wake lock of this |type| for |document|, reject |promise| with a {{"NotAllowedError"}} {{DOMException}} and return |promise|.
  3. If the current global object is the {{DedicatedWorkerGlobalScope}} object:
    1. If the current global object's [=WorkerGlobalScope/owner set=] [= list/is empty =], reject |promise| with a {{"NotAllowedError"}} {{DOMException}} and return |promise|.
    2. If |type| is {{ WakeLockType["screen"] }}, reject |promise| with a {{"NotAllowedError"}} {{DOMException}}, and return |promise|.
  4. Otherwise, if the current global object is the {{Window}} object:
    1. If the |document|'s [=Document/browsing context=] is `null`, reject |promise| with a {{"NotAllowedError"}} {{DOMException}} and return |promise|.
    2. If |document| is not [=Document/fully active=], reject |promise| with a {{"NotAllowedError"}} {{DOMException}}, and return |promise|.
    3. If |type| is {{WakeLockType["screen"] }} and |document| is hidden, reject |promise| with a {{"NotAllowedError"}} {{DOMException}}, and return |promise|.
  5. Run the following steps in parallel, but abort when |type| is {{WakeLockType["screen"]}} and |document| is hidden:
    1. Let |state:PermissionState| be the result of awaiting obtain permission steps with |type|:
      1. If |state| is {{PermissionState["denied"]}}, then reject |promise| with a {{"NotAllowedError"}} {{DOMException}}, and abort these steps.
    2. Let |lock:WakeLockSentinel| be a new {{WakeLockSentinel}} object with its {{WakeLockSentinel/type}} attribute set to |type|.
    3. Let |success:boolean| be the result of awaiting acquire a wake lock with |lock| and |type|:
      1. If |success| is `false` then reject |promise| with a {{"NotAllowedError"}} {{DOMException}}, and abort these steps.
    4. Resolve |promise| with |lock|.
  6. If aborted, run these steps:
    1. Reject |promise| with a {{"NotAllowedError"}} {{DOMException}}.
  7. Return |promise|.

The WakeLockSentinel interface

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

A {{WakeLockSentinel}} object provides a handle to a platform wake lock, and it holds on to it until it is either manually released or until the underlying platform wake lock is released. Its existence keeps a platform wake lock for a given wake lock type active, and releasing all {{WakeLockSentinel}} instances of a given wake lock type will cause the underlying platform wake lock to be released.

The type attribute corresponds to the {{WakeLockSentinel}}'s wake lock type.

The release() method

The {{WakeLockSentinel/release()}} method, when invoked, MUST run the following steps:

  1. Let |promise:Promise| be a new promise.
  2. Run the following steps in parallel:
    1. 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.
    2. Resolve |promise|.
  3. Return |promise|.

The onrelease attribute

The {{WakeLockSentinel/onrelease}} attribute is an event handler whose corresponding event handler event type is release.

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.

Auto-releasing wake locks

A user agent may release a wake lock at any time it:

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:

  1. Let |document:Document| be the [=environment settings object / responsible document=] of the current settings object.
  2. Let |screenRecord| be the platform wake lock's state record associated with |document| and wake lock type {{ WakeLockType["screen"] }}.
  3. [=list/For each=] |lock:WakeLockSentinel| in |screenRecord|.{{[[ActiveLocks]]}}:
    1. Run release a wake lock with |lock| and {{ WakeLockType["screen"] }}.
  4. Let |systemRecord| be the platform wake lock's state record associated with |document| and wake lock type {{ WakeLockType["system"] }}.
  5. [=list/For each=] |lock:WakeLockSentinel| in |systemRecord|.{{[[ActiveLocks]]}}:
    1. Run release a wake lock with |lock| and {{ WakeLockType["system"] }}.

Handling document loss of visibility

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:

  1. Let |document:Document| be the [=environment settings object / responsible document=] of the current settings object.
  2. If |document|'s visibility state is `"visible"`, abort these steps.
  3. Let |screenRecord| be the platform wake lock's state record associated with wake lock type {{ WakeLockType["screen"] }}.
  4. [=list/For each=] |lock:WakeLockSentinel| in |screenRecord|.{{[[ActiveLocks]]}}:
    1. Run release a wake lock with |lock| and {{ WakeLockType["screen"] }}.

Acquire wake lock algorithm

To acquire a wake lock for a given |lock:WakeLockSentinel| and |type:WakeLockType|, run these steps in parallel:

  1. If the wake lock for type |type| is not applicable, return `false`.
  2. Set |active:boolean| to `true` if the platform wake lock has an active wake lock for |type|.
  3. 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`.
  4. If |active| is `true`:
    1. Let |document:Document| be the [=environment settings object / responsible document=] of the current settings object.
    2. Let |record| be the platform wake lock's state record associated with |document| and |type|.
    3. Add |lock| to |record|.{{[[ActiveLocks]]}}.
  5. Return |active|.

Release wake lock algorithm

To release a wake lock for a given |lock:WakeLockSentinel| and |type:WakeLockType|, run these steps in parallel:

  1. Let |document:Document| be the [=environment settings object / responsible document=] of the current settings object.
  2. Let |record| be the platform wake lock's state record associated with |document| and |type|.
  3. If |record|.{{[[ActiveLocks]]}} does not contain |lock|, abort these steps.
  4. Remove |lock| from |record|.{{[[ActiveLocks]]}}.
  5. If the internal slot {{[[ActiveLocks]]}} of all the platform wake lock's state records are all empty, then run the following steps in parallel:
    1. 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`.
    2. If |success| is `true` and |type| is `"screen"` run the following:
      1. Reset the platform-specific inactivity timer after which the screen is actually turned off.
  6. Queue a task to fire an event named "`release`" at |lock|.

Security and privacy considerations

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.

Examples

        function tryKeepScreenAlive(minutes) {
          navigator.wakeLock.request("screen").then(lock => {
            setTimeout(() => lock.release(), minutes * 60 * 1000);
          });
        }

        tryKeepScreenAlive(10);
      

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:

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

        navigator.wakeLock.request("screen").then(lock => {
          checkbox.checked = true;

          const listener = (ev) => {
            checkbox.checked = false;
            ev.target.removeEventListener('release', listener);
          };

          lock.addEventListener('release', listener);
        });
      

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.