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.

Wake Locks

A wake lock prevents some aspect of the device or operating system from entering a power-saving state.

This specification defines two wake lock types:

  1. Screen wake lock which prevents device's screen from turning off so that the user can still see the information displayed on the screen.
  2. System wake lock which prevents device's CPU from entering a standby mode so that the programs can continue running.
One type of wake lock can imply the effects of another: for example, screen wake lock logically implies that the program which displays information on the screen continues running, as if the system wake lock were also applied. But to avoid dependence on such implementation details which may not always be true, this specification treats all types of wake locks as independent.

A user agent MAY deny wake lock of a particular type or all types on per-browsing context basis, and MUST do so in cases explicitly defined by this specification.

A user agent MAY check user settings or request user permission in order to decide whether it will deny wake lock of a particular type for a particular browsing context.

If the browsing context is not a top-level browsing context and its active document's origin is not the same as that of the active document of its top-level browsing context, the user agent MUST deny wake lock.

The same-origin requirement prevents unauthorized nested third-party content from requesting a wake lock on behalf of the top-level page.

An alternative approach could be requiring a permission as defined in [[!PERMISSIONS]] which would effectively delegate decisions about wake lock in nested browsing contexts to the user agent. The downside is that permission inheritance model is currently non-portable between implementations and sometimes inconsistent even within the same implementation. For more details see e.g. this Chromium design document.

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.

Extensions to the Navigator interface

        partial interface Navigator {
          Promise<WakeLock> getWakeLock(WakeLockType type);
        };
      

For each Navigator object, there is a wake lock resolution for each wake lock type which is one of:

Each wake lock resolution is initially set to pending wake lock resolution.

The getWakeLock() method, when invoked with an argument type, MUST run the following steps:

  1. Let wakeLockResolution be the wake lock resolution for wake lock type type.
  2. If wakeLockResolution is pending wake lock resolution and the user agent does not support the wake lock type denoted by type, or has otherwise determined it will deny wake lock of this type for this browsing context, set wakeLockResolution to rejected wake lock resolution.
  3. If wakeLockResolution is pending wake lock resolution and the user agent has determined it will not deny wake lock of this type for this browsing context, create and initialize a wake lock object of type type and let wakeLock be that object. Set wakeLockResolution to wakeLock.
  4. If wakeLockResolution is rejected wake lock resolution, return a promise rejected with a new unsupported wake lock type exception and abort these steps.
  5. If wakeLockResolution is a WakeLock object, return a promise resolved with wakeLockResolution and abort these steps.
  6. Let wakeLockPromise be a new promise. Return wakeLockPromise and run the remaining steps in parallel.
  7. Determine whether the user agent will deny wake lock of this type for this browsing context.
  8. If the user agent has determined that it will deny the wake lock, set wakeLockResolution to rejected wake lock resolution, reject wakeLockPromise with a new unsupported wake lock type exception and abort these steps.
  9. Create and initialize a wake lock object of type type and let wakeLock be that object.
  10. Set wakeLockResolution to wakeLock.
  11. Resolve wakeLockPromise with wakeLock.

An unsupported wake lock type exception is a DOMException whose name is "WakeLockTypeNotSupported".

The WakeLock interface

The WakeLock interface allows the page to request wake locks of a particular type, to determine the current wake lock state and to receive notifications when the wake lock state is changed.

        interface WakeLock : EventTarget {
          readonly attribute WakeLockType type;
          readonly attribute boolean active;
          attribute EventHandler onactivechange;
          WakeLockRequest createRequest();
        };
      
type
Wake lock type associated with this WakeLock object.
active
Indicates whether wake lock if this type is currently acquired by the user agent.
onactivechange
Event handler with the corresponding event handler event type of activechange. Fired when current wake lock status indicated by the active attribute changes.

To create and initialize a WakeLock object of type type, the following steps MUST be performed:

  1. Create a new WakeLock object in the Realm of this Navigator object and let wakeLock be that object.
  2. Set type attribute of wakeLock to type.
  3. If the wake lock of type type is currently acquired, set active attribute of wakeLock to true, otherwise to false.
  4. Return wakeLock.

Internally, each WakeLock object contains request counter which is initially set to zero. Each time the createRequest() method is called on the object, the request counter is increased by one.

A WakeLock object has an outstanding wake lock request when its request counter is greater than zero.

When the createRequest() method is invoked, the following steps MUST be performed:

  1. Create a new WakeLockRequest object in the Realm of this WakeLock object and let wakeLockRequest be that object.
  2. Set wakeLockRequest's owner wake lock reference to this WakeLock object.
  3. Return wakeLockRequest.
This additional WakeLockRequest object is added to address the issue with multiple components requesting wake lock on the same page independently.

The WakeLockRequest interface

        interface WakeLockRequest {
          void cancel();
        };
      

Each WakeLockRequest object has an implicit owner wake lock reference to the WakeLock object through which this object was created. When the cancel() method is invoked, the following steps MUST be performed:

  1. If the cancel() method has already been invoked on this object, abort these steps.
  2. Let wakeLock be the object referred to by this object's owner wake lock reference. Decrease wakeLock's request counter by one.

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.

A browsing context is requesting the wake lock of type type if and only if the following procedure returns true:

  1. Let navigator be the Navigator object associated with this browsing context.
  2. Let wakeLockResolution be the wake lock resolution associated with navigator and type.
  3. If wakeLockResolution is either pending wake lock resolution or rejected wake lock resolution, return false and abort these steps.
  4. If type is "screen" and browsing context's active document is hidden, return false and abort these steps.
  5. If wakeLockResolution, which is a WakeLock object, has an outstanding wake lock request, return true, otherwise return false.
The additional visibility requirement for screen wake lock is to prevent keeping the screen on when the page is not visible, such as when the browser is minimized. As this condition is transient and not under control of the web page, the specification chooses to automatically acquire and release the lock when visibility changes rather than having the page to deal with it, e.g by re-requesting the lock each time the page becomes visible again.

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 when the device is manually locked by the user. Putting the device into the locked state MUST NOT affect the applicability of the system wake lock.

Whether the wake lock is applicable is a transient condition, e.g. when the battery charge is low but then the battery is recharged. So like the visibility requirement, this is part of automatic wake lock management and not part of the decision process whether to allow or deny the wake lock.

The user agent MUST acquire the wake lock of type type when all of the following conditions become true:

  1. The wake lock of type type is applicable.
  2. There is at least one browsing context that is requesting the wake lock of type type.

The user agent MUST release the wake lock when any of the conditions above become false.

Whenever user agent acquires or releases a wake lock, the user agent MUST perform the following steps for each WakeLock object:

  1. If WakeLock object's type attribute is not equal to type, abort these steps.
  2. Queue a task which updates the WakeLock object's active attribute and fires an event named activechange at the WakeLock object.

In the task described above, the WakeLock objects's active attribute MUST be set to true if the wake lock has been acquired or to false if the wake lock has been released.

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.

The ability to observe the global state of a wake lock can create a communication channel between two otherwise isolated browsing contexts. One context can request wake lock which changes the global wake lock state, and another context can observe this change by subscribing to events in WakeLock.

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

This example acquires a screen wake lock and releases it after a while:

        navigator.getWakeLock("screen").then(function(wakeLock) {
          var request = wakeLock.createRequest();
          setTimeout(function() {
            request.cancel();
          }, 1000);
        });
      

This example requests a screen wake lock and listens to wake lock state changes:

        var request;
        navigator.getWakeLock("screen").then(function(wakeLock) {
          request = wakeLock.createRequest();
          document.getElementById("wakeLockActive").innerHTML = wakeLock.active;
          wakeLock.onactivechange = function() {
            document.getElementById("wakeLockActive").innerHTML = wakeLock.active;
          };
        });
      

In this example, two screen wake lock requests are created and cancelled independently:

        var request1;
        navigator.getWakeLock("screen").then(function(wakeLock) {
          request1 = wakeLock.createRequest();
        });

        // ...

        var request2;
        navigator.getWakeLock("screen").then(function(wakeLock) {
          request2 = wakeLock.createRequest();
        });

        // ...

        request1.cancel();
        request2.cancel();
      

Dependencies

The following concepts and interfaces are defined in [[!WHATWG-HTML]]:

The following concepts and interfaces are defined in [[!WHATWG-DOM]]:

The following concepts and interfaces are defined in [[!WEBIDL-LS]]:

The following concepts are defined in [[!PROMISES-GUIDE]]:

The following concepts and interfaces are defined in [[!ECMASCRIPT]]:

The following concepts and interfaces are defined in [[!PAGE-VISIBILITY]]:

Use cases

The use cases and requirements are documented in [[WAKE-LOCK-USE-CASES]].

This specification defines conformance criteria for a single product: a user agent that implements the interfaces that it contains.

The user agent MUST implement the APIs defined in this specification in a manner that conforms to the ECMAScript Bindings defined in [[!WEBIDL]].

Acknowledgments

We would like to offer our sincere thanks to Mounir Lamouri, Sergey Konstantinov, Matvey Larionov, Dominique Hazael-Massieux (via the HTML5Apps project) for their contributions to this work.