这是
实验性技术
检查
浏览器兼容性表格
要小心谨慎在生产中使用这之前。
This article provides a basic guide to using the W3C Permissions API, which provides a programmatic way to query the status of API permissions attributed to the current context.
Let's face it, permissions on the Web are a necessary evil, and they are not much fun to deal with as developers.
Historically, different APIs handle their own permissions inconsistently — for example the Notifications API allows for explicit checking of permission status and requesting permission, whereas the Geolocation API doesn't (which causes problems if the user denied the initial permission request, as we'll see below).
权限 API provides the tools to allow developers to implement a better user experience as far as permissions are concerned. For example, it can query whether permission to use a particular API is granted or denied, and specifically request permission to use an API.
At the moment, implementation of the API is at an early stage, so support in browsers is pretty spotty:
Permissions.query()
, which queries permission status.
More features will be added as time progresses.
For this article, we have put together a simple demo called Location Finder. It uses Geolocation to query the user's current location and plot it out on a Google Map:
You can run the example live ,或 view the source code on Github . Most of the code is simple and unremarkable — below we'll just be walking through the Permissions API-related code, so check the code yourself if you want to study any of the other parts.
Navigator.permissions
property has been added to the browser to allow access to the global
权限
object. This object will eventually include methods for querying, requesting, and revoking permissions, although currently it only contains
Permissions.query()
; see below.
In our example, the Permissions functionality is handled by one function —
handlePermission()
. This starts off by querying the permission status using
Permissions.query()
. Depending on the value of the
state
特性为
PermissionStatus
object returned when the promise resolves, it reacts differently:
"granted"
The "Enable Geolocation" button is hidden, as it isn't needed if Geolocation is already active.
"prompt"
Geolocation.getCurrentPosition()
function is then run, which prompts the user for permission; it runs the
revealPosition()
function if permission is granted (which shows the map), or the
positionDenied()
function if permission is denied (which makes the "Enable Geolocation" button appear).
"denied"
The "Enable Geolocation" button is revealed (this code needs to be here too, in case the permission state is already set to denied for this origin when the page is first loaded).
function handlePermission() {
navigator.permissions.query({name:'geolocation'}).then(function(result) {
if (result.state == 'granted') {
report(result.state);
geoBtn.style.display = 'none';
} else if (result.state == 'prompt') {
report(result.state);
geoBtn.style.display = 'none';
navigator.geolocation.getCurrentPosition(revealPosition,positionDenied,geoSettings);
} else if (result.state == 'denied') {
report(result.state);
geoBtn.style.display = 'inline';
}
result.onchange = function() {
report(result.state);
}
});
}
function report(state) {
console.log('Permission ' + state);
}
handlePermission();
Permissions.query()
method takes a
PermissionDescriptor
dictionary as a parameter — this contains the name of the API you are interested in. Some APIs have more complex
PermissionDescriptor
s containing additional information, which inherit from the default
PermissionDescriptor
. For example, the
PushPermissionDescriptor
should also contain a Boolean that specifies if
userVisibleOnly
is
true
or
false
.
Starting in Firefox 47, you can now revoke existing permissions, using the
Permissions.revoke()
method. This works in exactly the same way as the
Permissions.query()
method, except that it causes an existing permission to be reverted back to its default state when the promise successfully resolves (which is usually
prompt
). See the following code in our demo:
var revokeBtn = document.querySelector('.revoke');
...
revokeBtn.onclick = function() {
revokePermission();
}
...
function revokePermission() {
navigator.permissions.revoke({name:'geolocation'}).then(function(result) {
report(result.state);
});
}
revoke()
function has been disabled by default starting in Firefox 51, since its design has been brought into question in the
Web Applications Security Working Group
. It can be re-enabled by setting the preference
dom.permissions.revoke.enable
to
true
.
You'll notice that there is an
onchange
event handler in the code above, attached to the
PermissionStatus
object — this allows us to respond to any changes in the permission status for the API we are interested in. At the moment we are just reporting the change in state.
At the moment this doesn't offer much more than what we had already. If we choose to never share our location from the permission prompt (deny permission), then we can't get back to the permission prompt without using the browser menu options:
However, future additions to browser functionality should provide the
request()
method, which will allow us to programatically request permissions, any time we like. These should hopefully be available soon.