Skip to content

Commit

Permalink
Screen Wake lock - clarify release and permissions-policy (mdn#32352)
Browse files Browse the repository at this point in the history
  • Loading branch information
hamishwillee authored Feb 20, 2024
1 parent 4086289 commit 20ee91c
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 3 deletions.
83 changes: 83 additions & 0 deletions files/en-us/web/api/permissions/query/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ A {{jsxref("Promise")}} that resolves to a {{domxref("PermissionStatus")}} objec

## Examples

### Display news based on geolocation permission

This example shows how you might display news related to the current location if the `geolocation` permission is granted, and otherwise prompt the user to enable granting access to the location.

```js
navigator.permissions.query({ name: "geolocation" }).then((result) => {
if (result.state === "granted") {
Expand All @@ -57,6 +61,85 @@ navigator.permissions.query({ name: "geolocation" }).then((result) => {
});
```

### Test support for various permissions

This example shows the result of querying each of the permissions.

The code uses `navigator.permissions.query()` to query each permission, logging either the permission status or the fact that the permission is not supported on the browser.
Note that the `query()` is called inside a `try...catch` block because the associated `Promise` will reject if the permission is not supported.

```html hidden
<pre id="log"></pre>
```

```js hidden
const logElement = document.querySelector("#log");
function log(text) {
logElement.innerText = `${logElement.innerText}${text}\n`;
logElement.scrollTop = logElement.scrollHeight;
}
```

```css hidden
#log {
height: 320px;
overflow: scroll;
padding: 0.5rem;
border: 1px solid black;
}
```

```js
// Array of permissions
const permissions = [
"accelerometer",
"accessibility-events",
"ambient-light-sensor",
"background-sync",
"camera",
"clipboard-read",
"clipboard-write",
"geolocation",
"gyroscope",
"local-fonts",
"magnetometer",
"microphone",
"midi",
"notifications",
"payment-handler",
"persistent-storage",
"push",
"screen-wake-lock",
"storage-access",
"top-level-storage-access",
"window-management",
];

processPermissions();

// Iterate through the permissions and log the result
async function processPermissions() {
for (const permission of permissions) {
const result = await getPermission(permission);
log(result);
}
}

// Query a single permission in a try...catch block and return result
async function getPermission(permission) {
try {
const result = await navigator.permissions.query({ name: permission });
return `${permission}: ${result.state}`;
} catch (error) {
return `${permission} (not supported)`;
}
}
```

The log from running the code is shown below:

{{EmbedLiveSample('Test support for various permissions',"100%", "370px")}}

## Specifications

{{Specifications}}
Expand Down
4 changes: 3 additions & 1 deletion files/en-us/web/api/permissions_api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ The Permissions API provides the tools to allow developers to implement a consis

The `permissions` property has been made available on the {{domxref("Navigator")}} object, both in the standard browsing context and the worker context ({{domxref("WorkerNavigator")}} — so permission checks are available inside workers), and returns a {{domxref("Permissions")}} object that provides access to the Permissions API functionality.

Once you have this object you can then perform permission-related tasks, for example querying a permission using the {{domxref("Permissions.query()")}} method to return a promise that resolves with the {{domxref("PermissionStatus")}} for a specific API.
Once you have this object you can then use the {{domxref("Permissions.query()")}} method to return a promise that resolves with the {{domxref("PermissionStatus")}} for a specific API.
Note that if the status is `prompt` the user must acknowledge a prompt before accessing the feature, and that the mechanism for launching this prompt will depend on the specific API — it is not defined as part of the Permissions API.

### Permission-aware APIs

Expand All @@ -39,6 +40,7 @@ A non-exhaustive list of permission-aware APIs includes:
- [Notifications API](/en-US/docs/Web/API/Notifications_API): `notifications`
- [Payment Handler API](/en-US/docs/Web/API/Payment_Handler_API): `payment-handler`
- [Push API](/en-US/docs/Web/API/Push_API): `push`
- [Screen Wake Lock API](/en-US/docs/Web/API/Screen_Wake_Lock_API): `screen-wake-lock`
- [Sensor APIs](/en-US/docs/Web/API/Sensor_APIs): `accelerometer`, `gyroscope`, `magnetometer`, `ambient-light-sensor`
- [Storage Access API](/en-US/docs/Web/API/Storage_Access_API): `storage-access`, `top-level-storage-access`
- [Storage API](/en-US/docs/Web/API/Storage_API): `persistent-storage`
Expand Down
29 changes: 27 additions & 2 deletions files/en-us/web/api/screen_wake_lock_api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ The Screen Wake Lock API prevents the screen from turning off, dimming or lockin
There are plenty of use cases for keeping a screen on, including reading an ebook, map navigation, following a recipe, presenting to an audience, scanning a QR/barcode or applications that use voice or gesture control, rather than tactile input (the default way to keep a screen awake).

You acquire a {{DOMxRef("WakeLockSentinel")}} object by calling the {{domxref('WakeLock.request','navigator.wakeLock.request()')}} {{jsxref('Promise')}}-based method that resolves if the platform allows it. A request may be rejected for a number of reasons, including system settings (such as power save mode or low battery level) or if the document is not active or visible.
It is good practice to store a reference to the sentinel object to allow the application to later control release.

The sentinel is attached to the underlying system wake lock. It can be released by the system, again if the battery power is too low or the document is not active or visible. It can also be released manually via the {{domxref('WakeLockSentinel.release()')}} method. It is good practice to store a reference to the sentinel object to control release later and also to reacquire the lock if need be.
The sentinel is attached to the underlying system wake lock. It can be released by the system, again if the battery power is too low or the document is not active or visible. It can also be released manually via the {{domxref('WakeLockSentinel.release()')}} method.
After being released a `WakeLockSentinel` can no longer be used. If a screen wake lock is required again/still, the application will need to request a new one.

The Screen Wake Lock API should be used to keep the screen on to benefit usability. It's a good idea to show some feedback on the interface to show if wake lock is active and a way for the user to disable it if they wish.

Expand All @@ -36,8 +38,13 @@ The Screen Wake Lock API should be used to keep the screen on to benefit usabili
### Extensions to other interfaces

- {{domxref("Navigator.wakelock")}} {{ReadOnlyInline}}

- : Returns a {{domxref("WakeLock")}} object instance, from which all other functionality can be accessed.

- [`Permissions-Policy: screen-wake-lock`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy/screen-wake-lock)
- : Access to the API is gated by the [`Permissions-Policy`](/en-US/docs/Web/HTTP/Headers/Permissions-Policy) directive `screen-wake-lock`.
See [Security considerations](#security_considerations) below.

## Examples

### Feature detection
Expand Down Expand Up @@ -119,7 +126,25 @@ You can find the [complete code on GitHub here](https://github.com/mdn/dom-examp
## Security considerations

Access to the Screen Wake Lock API is controlled by the [Permissions Policy](/en-US/docs/Web/HTTP/Permissions_Policy) directive {{HTTPHeader("Permissions-Policy/screen-wake-lock","screen-wake-lock")}}.
The default allowlist for `screen-wake-lock` is `self`.

When using the [Permissions Policy](/en-US/docs/Web/HTTP/Permissions_Policy), the default allowlist for `screen-wake-lock` is `self`.
This allows lock wake usage in same-origin nested frames but prevents third-party content from using locks.
Third party usage can be enabled by the server first setting the `Permissions-Policy` header to grant permission a particular third party origin.

```http
Permissions-Policy: screen-wake-lock=(self b.example.com)
```

Then the `allow="screen-wake-lock"` attribute must be added the frame container element for sources from that origin:

```html
<iframe src="https://b.example.com" allow="screen-wake-lock"/></iframe>
```

Browsers may also block the screen lock in a particular document for an implementation specific reason, such as a user or platform setting.
They are expected to provide some unobtrusive mechanism to inform the user when wake lock is active, and to provide users the ability to remove the application's screen lock.

The [Permissions API](/en-US/docs/Web/API/Permissions_API) `screen-wake-lock` permission can be used to test whether access to use the screen lock is `granted`, `denied` or `prompt` (requires user acknowledgement of a prompt).

## Specifications

Expand Down
1 change: 1 addition & 0 deletions files/en-us/web/api/wakelocksentinel/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ The screen wake lock prevents device screens from dimming or locking when an app
A screen wake lock is requested using the {{domxref('WakeLock.request()','navigator.wakeLock.request()')}} method, which returns a {{jsxref('Promise')}} that fulfills with a `WakeLockSentinel` object if the lock is granted.

An acquired screen wake lock can be released manually via the {{domxref('WakeLockSentinel.release','release()')}} method, or automatically via the platform screen wake lock. The latter may occur if the document becomes inactive or loses visibility, if the device is low on power, or if the user turns on a power save mode.
A released `WakeLockSentinel` cannot be re-used: a new sentinel must be be requested using {{domxref('WakeLock.request()','navigator.wakeLock.request()')}} if a new lock is needed.
Releasing all `WakeLockSentinel` instances of a given wake lock type will cause the underlying platform wake lock to be released.

An event is fired at the `WakeLockSentinel` if the platform lock is released, allowing applications to configure their UI, and re-request the lock if needed.
Expand Down

0 comments on commit 20ee91c

Please sign in to comment.