Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62
Subscribe to my email list now at http://jauyeung.net/subscribe/
We have to get user consent when we want to do anything that changes the user experience. For example, we need to get user permission to show notifications or access their hardware.
Modern browsers are standardized in how permissions are obtained. It’s all in the Permissions API.
APIs that rely on the Permissions API for permissions include the Clipboard API, Notifications API, Push API, and Web MIDI API.
The navigator
object has the permissions
property in both the standard browser and worker contexts. It gives us a way to get the permissions. However, the way we request permissions is different for each API.
This API is experimental so check if the browsers you target are supported.
Querying Permissions
The navigation.permissions
object lets us query permissions set with the query
method.
It returns a promise which gets us the state of the permission. For example, we can write the following to check for permission for the geolocation API:
(async () => {
const result = await navigator.permissions.query({
name: 'geolocation'
});
console.log(result.state);
})();
The possible values for result.state
are 'granted'
, 'denied'
, or 'prompt'
.
There’s also one for Web Workers that do the same thing.
The object that we passed into the query
method is the permission descriptor object, which has the following properties:
-
name
— name of the API which we want to get the permission for. Firefox only supportsgeolocation
,notifications
,push
, andpersistent-storage
-
userVisibleOnly
— indicates whether we want to show notification for every message or be able to send silent push notifications. Default value isfalse
. -
sysex
— applies to MIDI only. Indicates whether we need to receive system exclusive messages. Default value isfalse
.
Requesting Permission
Requesting permission is different between APIs. For example, the Geolocation API will show a prompt for permission when we call getCurrentPosition()
as follows:
navigator.geolocation.getCurrentPosition((position) => {
console.log('Geolocation permissions granted');
console.log(`Latitude: ${position.coords.latitude}`);
console.log(`Longitude: ${position.coords.longitude}`);
});
The Notifications API has a requestPermission
method to request permissions:
Notification.requestPermission((result) => {
console.log(result);
});
Watching for Permission Changes
The navigator.permissions.query
promise resolves to a PermissionStatus
object. We can use it to set an onchange
event handler function to watch for permission changes.
For example, we can expand on this example to add an event handler function to watch for changes for the permission of the Geolocation API:
(async () => {
const result = await navigator.permissions.query({
name: 'geolocation'
});
console.log(result.state);
})();
We can write:
(async () => {
const permissionStatus = await navigator.permissions.query({
name: 'geolocation'
});
permissionStatus.onchange = () => {
console.log(permissionStatus.state);
}
})();
The permissionStatus.state
will have the permission for the Geolocation API.
It’ll log whenever the permission changes, such as when we change the permission setting in the browser.
Revoking Permissions
We can revoke permission by using the revoke
method.
To call it, we can access it from the navigator.permissions
object as follows:
navigator.permissions.revoke(descriptor);
Where descriptor
is the permission descriptor which we described above.
It returns a Promise that resolves with the permission status object indicating the result of the request.
This method throws a TypeError if getting the permission descriptor failed or the permission doesn’t exist or is unsupported by browsers.
The name
property of the permission descriptor can accept one of the following values 'geolocation'
, 'midi'
, 'notifications'
, and 'push'
.
Other properties remain the same as the query
method.
For example, we can use it by writing:
(async () => {
const permissionStatus = await navigator.permissions.revoke({
name: 'geolocation'
});
console.log(permissionStatus);
})();
Note that we’ve to set dom.permissions.revoke.enable
to true
in Firefox 51 or later to use this method. It’s not enabled in Chrome.
The Permissions API lets us check and revoke browser permissions in a uniform way.
Requesting permissions are different for each API. This isn’t changing any time soon.
This is an experimental API, so using it in production is probably premature.