使用权限 API

本文提供了使用 W3C 权限 API 的基本指南,该 API 提供了一种以编程方式查询与当前上下文相关的 API 权限状态的方法。

请求权限的麻烦…

Web 上的权限是必要的,但对于开发人员来说,它们并不令人愉快。

在过去,不同的 API 以不一致的方式处理它们自己的权限 - 例如 通知 API 有自己用于检查权限状态和请求权限的方法,而 地理位置 API 则没有。

权限 API 为开发人员提供了一种一致的方法,并允许他们在权限方面实现更好的用户体验。具体来说,开发人员可以使用 Permissions.query() 检查在当前上下文中是否授予了使用特定 API 的权限,是否被拒绝,或者是否需要通过提示获取特定用户的权限。在主线程中查询权限 得到广泛支持,在 工作线程 中也得到支持(有一个明显的例外)。

许多 API 现在支持权限查询,例如 剪贴板 API通知 API推送 APIWeb MIDI API。在 API 概述 中提供了许多支持权限的 API 列表,您可以在 此处的兼容性表 中了解浏览器支持情况。

Permissions 有其他方法可以专门请求使用 API 的权限,以及撤销权限,但这些方法已弃用(非标准,或者没有得到广泛支持)。

一个简单的例子

对于本文,我们创建了一个名为 Location Finder 的简单演示。它使用地理位置查询用户的当前位置,并在 Google 地图上标出。

Screenshot showing a map of Greenfield, UK.

您可以 在线运行示例,或 在 GitHub 上查看源代码。大多数代码很简单,下面我们将介绍与权限 API 相关的代码,如果您想研究其他部分,请查看代码本身。

访问权限 API

已向浏览器添加了 Navigator.permissions 属性,以允许访问全局 Permissions 对象。此对象最终将包含用于查询、请求和撤销权限的方法,但目前它只包含 Permissions.query();请参见下文。

查询权限状态

在我们的示例中,权限功能由一个函数处理 - handlePermission()。它首先使用 Permissions.query() 查询权限状态。根据 promise 解决时返回的 PermissionStatus 对象的 state 属性的值,它将以不同的方式做出反应。

"granted"

“启用地理位置”按钮被隐藏,因为如果地理位置已处于活动状态,则不需要它。

"prompt"

“启用地理位置”按钮被隐藏,因为如果用户将被提示授予地理位置权限,则不需要它。然后运行 Geolocation.getCurrentPosition() 函数,该函数会提示用户授予权限;如果授予权限,它会运行 revealPosition() 函数(显示地图),如果拒绝权限,它会运行 positionDenied() 函数(使“启用地理位置”按钮出现)。

"denied"

“启用地理位置”按钮被显示出来(如果页面首次加载时权限状态已设置为拒绝该来源,则此代码也需要在这里)。

js
function handlePermission() {
  navigator.permissions.query({ name: "geolocation" }).then((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.addEventListener("change", () => {
      report(result.state);
    });
  });
}

function report(state) {
  console.log(`Permission ${state}`);
}

handlePermission();

权限描述符

Permissions.query() 方法将一个 PermissionDescriptor 字典作为参数 - 它包含您感兴趣的 API 的名称。一些 API 有更复杂的 PermissionDescriptor,包含其他信息,这些信息继承自默认的 PermissionDescriptor。例如,PushPermissionDescriptor 还应包含一个布尔值,用于指定 userVisibleOnlytrue 还是 false

响应权限状态更改

您会注意到,我们在上面的代码中监听了 change 事件,并将其附加到 PermissionStatus 对象 - 这使我们能够响应我们感兴趣的 API 的权限状态的任何更改。目前我们只是报告状态变化。

结论和未来工作

目前这并没有比我们已经拥有的提供更多内容。如果我们选择从权限提示中永远不共享我们的位置(拒绝权限),那么我们就无法回到权限提示,除非使用浏览器菜单选项。

  • Firefox工具 > 页面信息 > 权限 > 访问您的位置。选择始终询问
  • Chrome汉堡菜单 > 设置 > 显示高级设置。在隐私部分,点击内容设置。在弹出的对话框中,找到位置部分,选择当网站尝试时询问...。最后,点击管理例外情况,并删除您授予给相关网站的权限。

有一些提案,希望能够让网站能够以命令的方式 请求撤销 权限,但进展不大,因为用例不明确,并且遭到了浏览器厂商的反对。请参见有关 从主要规范中删除 permissions.request()从主要规范中删除 permissions.revoke() 的讨论。