针对新 HTML <permission> 元素的源试用

有许多命令式方法可用于请求在 Web 应用中使用位置信息访问权限等强大功能的权限。这些方法存在诸多挑战,因此 Chrome 权限团队正在尝试一种新的声明式方法:专用 HTML <permission> 元素。此元素从 Chrome 126 开始处于源试用阶段,我们最终希望将其标准化。

请求权限的命令式方法

当 Web 应用需要访问强大的功能时,需要请求权限。例如,当 Google 地图使用 Geolocation API 请求用户的位置信息时,浏览器会向用户发出提示,通常会提供存储该决定的选项。这是权限规范中定义明确的概念

在首次使用时隐式询问,而不是预先明确请求

Geolocation API 是一款强大的 API,采用“首次使用时隐式询问”方法。例如,当应用调用 navigator.geolocation.getCurrentPosition() 方法时,权限提示会在首次调用时自动弹出。再比如 navigator.mediaDevices.getUserMedia()

其他 API(如 Notification APIDevice Orientation and Motion API)通常具有通过 Notification.requestPermission()DeviceMotionEvent.requestPermission() 等静态方法明确请求权限的方式。

使用命令式方法请求权限时遇到的问题

权限垃圾内容

过去,网站可以调用 navigator.mediaDevices.getUserMedia()Notification.requestPermission() 等方法,但在加载网站时也可以立即调用 navigator.geolocation.getCurrentPosition()。在用户与网站互动之前,系统会弹出权限提示。这有时被称为“权限垃圾流量”,会影响两种方式,即在首次使用时隐式请求以及预先明确请求。

加载网站时显示的麦克风权限提示。

浏览器缓解措施和用户手势要求

垃圾权限导致浏览器供应商要求用户手势(例如按钮点击或 keydown 事件)才会显示权限提示。这种方法存在的问题是,浏览器很难(如果不是不可能)确定给定的用户手势是否应导致显示权限提示。也许用户只是因为网页加载时间太长而感到沮丧,随便点击了网页上的某个位置;也许他们确实点击了定位我按钮。一些网站还非常擅长诱骗用户点击内容以触发提示。

另一种缓解措施是添加提示滥用缓解措施,例如一开始就完全屏蔽功能,或者以非模态且不太侵扰的方式显示权限提示。

Chrome 浏览器,显示了

权限情境化

另一个挑战(尤其是在大屏设备上)是权限提示的常见显示方式:位于死亡线上方,即位于应用可以绘制到浏览器窗口的区域之外。用户只点击浏览器窗口底部的按钮,而错过浏览器窗口顶部的提示,这种情况并不少见。在浏览器实施垃圾内容防范措施后,此问题通常会加剧。

打开位置信息权限提示的 Google 地图。触发提示的位置信息访问权限按钮距离较远。

无法轻松撤消

最后,用户很容易迷失在导航界面中。例如,如果用户屏蔽了某项功能的访问权限,则需要他们知道网站信息下拉菜单,在其中重置权限或重新开启已屏蔽的权限。在最糟糕的情况下,这两种方法都需要完全重新加载网页,更新后的设置才能生效。网站无法为用户提供更改现有权限状态的简便快捷方式,而必须费心向用户说明如何更改其设置,如下方 Google 地图屏幕截图底部所示。

Google 地图上的 Chrome 网站控件,用于撤消权限。

如果权限对体验至关重要(例如,视频会议应用的麦克风访问权限),Google Meet 等应用会显示侵扰性对话框,指引用户如何取消屏蔽权限。

Google Meet 说明:如何打开 Chrome 网站控制功能。

声明式 <permission> 元素

为了解决本文中所述的问题,Chrome 权限团队已针对新的 HTML 元素 <permission> 启动了源代码试用。借助此元素,开发者可以声明式地请求使用网站提供的强大功能(目前仅限部分功能)。在最简单的形式下,您可以按以下示例使用它:

<permission type="camera" />

对于 <permission> 是否应为 void 元素,目前仍处于积极讨论。空元素是 HTML 中的自闭合元素,它不能包含任何子节点;在 HTML 中,这意味着它可能没有结束标记。

type 属性

type 属性包含您请求的权限的以空格分隔的列表。在撰写本文时,允许的值包括 'camera''microphone'camera microphone(以空格分隔)。默认情况下,此元素的呈现方式类似于采用极简用户代理样式的按钮。

各种权限元素按钮,包括摄像头、麦克风和摄像头以及麦克风权限。

type-ext 属性

对于允许使用其他参数的某些权限,type-ext 属性接受以空格分隔的键值对,例如,precise:true(用于地理位置信息权限)。

lang 属性

按钮文字由浏览器提供,旨在保持一致,因此无法直接自定义。浏览器会根据文档或父元素链继承的语言,或可选的 lang 属性来更改文本的语言。这意味着开发者无需自行本地化 <permission> 元素。如果 <permission> 元素进入原始试用阶段之后,则可以针对每种权限类型支持多个字符串或图标,以提高灵活性。如果您有兴趣使用 <permission> 元素,并且需要特定的字符串或图标,请与我们联系

行为

当用户与 <permission> 元素互动时,可以循环浏览各个阶段:

  • 如果用户之前未允许某项功能,则可以选择每次访问时都允许该功能,也可以仅为当前访问允许该功能。

    提示用户仅这次访问时或每次访问时允许使用某项功能的权限。

  • 如果用户之前已允许该功能,则可以继续允许或停止允许。

    提示用户继续允许或停止允许的权限。

  • 如果他们之前禁止了某项功能,则可以继续禁止,也可以这次允许。

    权限提示,询问是否继续不允许或仅限这一次允许。

<permission> 元素的文本会根据状态自动更新。例如,如果用户已获准使用某项功能,相应文本会更改为指明该功能已获许可。如果需要先授予权限,文字会更改为邀请用户使用相应功能。将上面的屏幕截图与下面的屏幕截图进行比较,了解这两种状态。

带文字的权限按钮

CSS 设计

为确保用户能够轻松识别该按钮是用于访问强大功能的界面,系统会限制 <permission> 元素的样式。如果样式限制不适用于您的用例,我们非常乐意了解具体原因!虽然无法满足所有样式需求,但我们希望在源代码试用后,能够找到安全的方式来允许对 <permission> 元素进行更多样式设置。下表详细介绍了一些受到限制或适用特殊规则的媒体资源。如果违反了任何规则,<permission> 元素将被停用,并且无法与之交互。任何尝试与其交互的操作都会导致异常,这些异常可以通过 JavaScript 捕获。错误消息将包含有关检测到的违规行为的更多详细信息。

属性 规则

colorbackground-color

分别用于设置文本和背景颜色。两种颜色之间的对比度需要足够,以便文本清晰可辨(对比度至少为 3)。Alpha 渠道必须为 1。

font-sizezoom

必须设置为 smallxxxlarge 的等效值。否则,该元素将被停用。计算 font-size 时,系统会考虑缩放。

outline-offset

负值将更正为 0
margin(所有) 负值将更正为 0

font-weight

200”下的值将更正为“200”。

font-style

normalitalic 以外的值将更正为 normal

word-spacing

超过 0.5em 的值将更正为 0.5em0 下的值将更正为 0

display

inline-blocknone 以外的值将更正为 inline-block

letter-spacing

超过 0.2em 的值将更正为 0.2em-0.05em 下的值将更正为 -0.05em

min-height

默认值为 1em。如果提供,系统会考虑默认值和所提供值之间的最大计算值。

max-height

默认值为 3em。如果提供,系统会考虑默认值和所提供值之间的最小计算值。

min-width

默认值为 fit-content。如果提供,将考虑默认值和所提供的值之间的最大计算值。

max-width

默认值为 fit-content 的三倍。如果提供,系统会考虑默认值和所提供值之间计算的最小值。

padding-top

仅当 height 设置为 auto 时才会生效。在这种情况下,大于 1em 的值将更正为 1em,并且 padding-bottom 将设置为 padding-top 的值。

padding-left

只有在 width 设置为 auto 时才会生效。在这种情况下,大于 5em 的值将更正为 5em,并且 padding-right 将设置为 padding-left. 的值

transform

不允许使用扭曲视觉效果。目前,我们仅接受 2D 平移和按比例放大。

以下 CSS 属性可以照常使用:

  • font-kerning
  • font-optical-sizing
  • font-stretch
  • font-synthesis-weight
  • font-synthesis-style
  • font-synthesis-small-caps
  • font-feature-settings
  • forced-color-adjust
  • text-rendering
  • align-self
  • anchor-name aspect-ratio
  • border(以及所有 border-* 属性)
  • clear
  • color-scheme
  • contain
  • contain-intrinsic-width
  • contain-intrinsic-height
  • container-name
  • container-type
  • counter-*
  • flex-*
  • float
  • height
  • isolation
  • justify-self
  • left
  • order
  • orphans
  • outline-*(之前针对 outline-offset 注明的例外情况)
  • overflow-anchor
  • overscroll-behavior-*
  • page
  • position
  • position-anchor
  • content-visibility
  • right
  • scroll-margin-*
  • scroll-padding-*
  • text-spacing-trim
  • top
  • visibility
  • x
  • y
  • ruby-position
  • user-select
  • width
  • will-change
  • z-index

此外,所有逻辑等效的属性(例如,inline-size 等效于 width)都可以使用,遵循与等效项相同的规则。

伪类

有两个特殊的伪类,可用于根据状态设置 <permission> 元素的样式:

  • :granted:granted 伪类允许在授予权限时使用特殊样式。
  • :invalid:invalid 伪类允许在元素处于无效状态(例如,在跨源 iframe 中传送)时设置特殊样式。
permission {
  background-color: green;
}

permission:granted {
  background-color: light-green;
}

/* Not supported during the origin trial. */
permission:invalid {
  background-color: gray;
}

JavaScript 事件

<permission> 元素应与 Permissions API 搭配使用。可监听多种事件:

  • onpromptdismiss:当用户关闭由元素触发的权限提示(例如,点击关闭按钮或点击提示之外的区域)时,系统会触发此事件。

  • onpromptaction:当用户对元素触发的权限提示执行某些操作来解除该提示时,系统会触发此事件。这并不一定意味着权限状态发生了变化,用户可能采取了维持现状的操作(例如继续允许某项权限)。

  • onvalidationstatuschange:当元素从 "valid" 切换为 "invalid" 时,系统会触发此事件。如果浏览器信任信号的完整性(即用户点击该元素),则该元素被视为 "valid";否则(例如,当该元素被其他 HTML 内容部分遮挡时),则被视为 "invalid"

您可以直接在 HTML 代码 (<permission type="…" onpromptdismiss="alert('The prompt was dismissed');" />) 中内嵌注册这些事件的事件监听器,也可以对 <permission> 元素使用 addEventListener(),如以下示例所示。

<permission type="camera" />
<script>
  const permission = document.querySelector('permission');
  permission.addEventListener('promptdismiss', showCameraWarning);

  function showCameraWarning() {
    // Show warning that the app isn't fully usable
    // unless the camera permission is granted.
  }

  const permissionStatus = await navigator.permissions.query({name: "camera"});
  
  permissionStatus.addEventListener('change', () => {
    // Run the check when the status changes.
    if (permissionStatus.state === "granted") {
      useCamera();
    }
  });

  // Run the initial check.
  if (permissionStatus.state === "granted") {
    useCamera();
  }
</script>

功能检测

如果浏览器不支持某个 HTML 元素,则不会显示该元素。这意味着,如果您的 HTML 代码中包含 <permission> 元素,即使浏览器不知道该元素,也不会发生任何情况。您可能仍希望使用 JavaScript 检测支持情况,例如,通过点击常规 <button> 来创建权限提示。

if ('HTMLPermissionElement' in window) {
  // The `<permission>` element is supported.
}

源试用

如需在您的网站上面向真实用户试用 <permission> 元素,请注册参加初始试用。如需了解如何准备网站以使用源代码试用版,请参阅源代码试用版使用入门。源试用将从 Chrome 126 到 Chrome 131(2025 年 2 月 19 日)运行。

演示

在 GitHub 上浏览演示并查看源代码。以下屏幕截图显示了该浏览器在受支持的浏览器中的体验。

权限元素演示,其中显示了三个权限按钮。

反馈

我们非常期待您分享 <permission> 在您的用例中的运作方式。您可以随时回复代码库中的问题之一,或提交新问题。我们和其他浏览器可以知道您对其代码库中 <permission> 元素的公开信号。

常见问题解答

  • 这与与 Permissions API 搭配使用的常规 <button> 相比有何优势?点击 <button> 是一种用户手势,但浏览器无法验证它是否与请求权限相关联。如果用户点击了 <permission>,浏览器可以确定该点击与权限请求相关。这样一来,浏览器便能简化原本风险更高的流程。例如,允许用户轻松撤消对某项权限的屏蔽。
  • 如果其他浏览器不支持 <permission> 元素,该怎么办?<permission> 元素可用作渐进增强功能。在不受支持的浏览器中,可以使用传统权限流程。例如,基于常规 <button> 的点击。权限团队也在开发 polyfill。为 GitHub 代码库加注星标,以便在其就绪时收到通知。
  • 是否与其他浏览器供应商讨论过此问题?2023 年,W3C TPAC 在一个分组讨论会中积极讨论了 <permission> 元素。您可以阅读公开会话记录。Chrome 团队还要求这两家供应商提供正式的标准立场,请参阅相关链接部分。<permission> 元素是我们与其他浏览器持续讨论的话题,我们希望对其进行标准化。
  • 这实际上应该是一个空元素吗?对于 <permission> 是否应为 void 元素,我们仍然有争议。如果您有反馈意见,请就相应问题进行说明。

致谢

本文档由 Balázs EngedyThomas NguyenPenelope McLachlanMarian HarbachDavid WarrenRachel Andrew 审核。