HTML 权限元素

社区组报告草案,

此版本:
https://wicg.github.io/PEPC/permission-elements.html
问题跟踪:
GitHub
规范内联问题
编辑:
Daniel VogelheimGoogle LLC

摘要

用于在页面内请求浏览器权限的 HTML 元素。

本规范定义了一组新的 HTML 元素,其共同目标是为用户提供一种 从页面内控制浏览器权限及相关 能力的方式。

对此新元素施加适当的样式和 UI 约束,可确保用户 理解点击该元素意味着什么,从而使浏览器能够高度 确信用户有意作出权限决定。 这些权限元素旨在比当前由脚本触发的权限流程更易于访问、更安全且更加 用户友好。

本文档的状态

本规范由 Web 平台孵化器 社区组发布。 它不是 W3C 标准,也不处于 W3C 标准化流程中。 请注意,根据 W3C 社区贡献者许可协议 (CLA), 退出权受到限制,并且还适用其他条件。 详细了解 W3C 社区组和业务组

1. 简介

用户 代理向网站公开强大功能,这些功能对某些用例非常重要, 但也很容易被滥用。此类强大功能中可以说最典型的 示例是摄像头访问,它对于在线会议等许多用例 至关重要,但未经请求便激活摄像头会造成严重的隐私问题。为处理此问题,用户 代理使用权限来询问用户是否希望允许某项特定 访问。

这些权限请求最初是一种相当直接的传递机制:网站会 请求某项能力,而用户代理会立即提示用户对该请求 作出决定。然而,垃圾信息和滥用迫使用户代理 采取更具倾向性的方式来保护用户的安全、隐私和 注意力。当前的情况是,用户会收到大量权限请求, 而用户往往并不清楚这些请求可能产生什么后果。

本规范引入了一种新机制,通过页面内元素请求并启动对 强大功能的访问,并内置防止 滥用的保护措施。此机制旨在将权限请求与其实际使用的上下文 关联起来,从而减少“权限轰炸”,同时 为实现提供更可靠的用户意图信号。

2. HTML 权限元素的共同行为:InPagePermissionMixin

本规范中的元素具有许多共同行为,这些行为 由InPagePermissionMixin 及其相关状态、 算法和渲染规则进行定义。

InPagePermissionMixin 接口混入定义如下:

interface mixin InPagePermissionMixin {
  readonly attribute boolean isValid;
  readonly attribute InPagePermissionMixinBlockerReason invalidReason;
  readonly attribute PermissionState initialPermissionStatus;
  readonly attribute PermissionState permissionStatus;

  attribute EventHandler onpromptaction;
  attribute EventHandler onpromptdismiss;
  attribute EventHandler onvalidationstatuschange;
};

使用此混入的元素应支持以下 内容属性

isValid
查询元素当前是否可以激活。
invalidReason
返回表示元素当前无法激活原因的字符串。
onpromptdismiss
当用户关闭因与该元素交互而产生的权限提示时发出通知
onpromptaction
当用户回答了因与该元素交互而产生的权限提示时发出通知 (无论肯定还是否定)。
onvalidationstatuschange
当验证状态发生变化时发出通知。

isValid 属性反映该 权限元素当前是否未被阻止。

invalidReason 属性是一个 枚举属性,它反映权限 元素的内部状态。其值集合为InPagePermissionMixinBlockerReason

元素会观察全局lang 属性, 以选择本地化文本。

元素上的全局 tabindex 内容属性的默认 值 为 0。

以下是包含InPagePermissionMixin 的元素必须支持的事件处理器(及其对应的事件处理器事件类型):

onpromptaction 事件
onpromptdismiss 事件
onvalidationstatuschange 事件

2.1. Mixin 内部状态

HTML 权限元素表示 由用户可请求的权限所管控的能力, 用户可以激活这些元素,使网站开始访问相应能力。 这些元素的核心在于,此类请求应由用户 触发,而不是由页面脚本触发。为强制执行 此要求,元素会检查激活事件是否为受信任的。 此外,它还会监视多种条件,例如元素是否 (部分)被遮挡,或者最近是否被移动。元素维护一个内部[[BlockerList]] 来跟踪这些情况。

InPagePermissionMixin 元素具有以下内部槽:

2.2. Mixin可导航对象上的支持状态

为了支持InPagePermissionMixin可导航对象维护一个元素的有序集合,即[[PermissionElements]]。此有序 集合用于评估类型为unsuccesful_registration阻止器

2.3. Mixin 激活和激活阻止器

权限元素系列的关键目标是反映用户的 有意识选择,我们需要确保用户不会轻易被欺骗 而激活它。为此,权限元素会维护一个 阻止原因列表,这些原因可能永久或暂时阻止元素 被激活。

这些行为中的大多数对于所有权限元素都应相同。 为简单起见,我们还会包含仅适用于一个元素或某些 元素的阻止器。

enum InPagePermissionMixinBlockerReason {
  // 无阻止原因。
  "",

  // 所有 InPagePermissionMixin 使用者均支持的阻止原因。
  "illegal_subframe", "unsuccesful_registration",
  "recently_attached", "intersection_changed",
  "intersection_out_of_viewport_or_clipped",
  "intersection_occluded_or_distorted", "style_invalid",

  // HTMLPermissionElement 特有的阻止原因。
  "type_invalid",
};

权限元素会跟踪“阻止器”,即元素(当前)无法激活的原因。 这些阻止器具有三种生命周期:永久、临时和到期。

永久 阻止器

一旦元素具有永久阻止器,它将被永久禁用。 这类阻止器用于网站所有者应当修复的问题。 一个示例是位于 fencedframe 内的 permission 元素。

临时 阻止器

这种阻止器仅在阻止条件仍然存在时有效。 一个示例是当前不在视野中的 permission 元素。所有临时阻止器都会在条件不再适用后 转变为到期阻止器

到期 阻止器

这种阻止器仅在固定时间段内有效。它用于 阻止诸如“点击劫持”之类的滥用场景。一个示例是 最近被移动过的 permission 元素。

阻止器名称 阻止器类型 示例条件 顺序提示
type_invalid 永久 设置了不受支持的权限类型 时。 1
illegal_subframe 永久 元素在 fencedframe 内使用时。 2
unsuccesful_registration 临时 同一文档中插入了过多针对同一 强大功能的其他元素时。 3
recently_attached 到期 元素刚刚附加到 DOM 时。 4
intersection_changed 到期 元素正在移动时。 6
intersection_out_of_viewport_or_clipped 临时 元素未处于或未完全处于视口中时。 7
intersection_occluded_or_distorted 临时 元素完全位于视口中, 但仍未完全可见时(例如部分位于其他内容之后)。 8
style_invalid 临时 9
要使用InPagePermissionMixinBlockerReason reason 和可选标志 expires 添加阻止器
  1. 断言reason 不是 ""。 (InPagePermissionMixinBlockerReason 中的空字符串表示不存在阻止器。 为什么要添加一个不产生阻止作用的空字符串阻止器?)

  2. timestamp 为 None。

  3. 如果 expires,则令 timestamp当前高分辨率时间 加上阻止器延迟

  4. 向内部[[BlockerList]]追加一个包含 reasontimestamp 的条目。

阻止器延迟为 500ms。
要使用InPagePermissionMixinBlockerReason reason 添加到期阻止器
  1. 断言reason阻止器 原因表中列为“到期”。

  2. 使用 reason 和 true添加阻止器

要使用InPagePermissionMixinBlockerReason reason 添加临时阻止器
  1. 断言reason阻止器 原因表中列为“临时”。

  2. 使用 reason 和 false添加阻止器

要使用InPagePermissionMixinBlockerReason reason 添加永久阻止器
  1. 断言reason阻止器 原因表中列为“永久”。

  2. 使用 reason 和 false添加阻止器

要从 element 中使用 InPagePermissionMixinBlockerReason reason 移除阻止器
  1. 断言reason阻止器 原因表中列为“临时”。

  2. 对于 element[[BlockerList]] 中的每个 entry

    1. 如果 entry 的 reason 与 reason相等, 则从 element[[BlockerList]]移除 entry

  3. 使用 reason 和 true添加阻止器

要确定一个InPagePermissionMixin element阻止器
  1. blockers 为使用阻止器排序算法对 element[[BlockerList]] 进行排序的结果。

  2. 如果 blockers 不为,且 blockers[0] 正在阻止,则返回 blockers[0]。

  3. 不返回任何内容。

要确定两个阻止器 ab阻止器排序
  1. really large number 为 99。

  2. 断言阻止器原因表中没有任何 顺序提示等于或 大于 really large number

  3. 如果 a 正在阻止,则令 a hint阻止器 原因表a原因对应的 顺序提示;否则令 a hintreally large number

  4. 如果 b 正在阻止,则令 b hint阻止器 原因表b原因对应的 顺序提示;否则令 b hintreally large number

  5. 返回 a hint 是否小于或等于 b hint

如果满足以下条件,则InPagePermissionMixin阻止器列表的 entry 正在阻止
  1. entry 没有阻止器时间戳

  2. 或者 entry 具有阻止器时间戳,且该阻止器时间戳 大于或等于当前高分辨率时间

注:本规范以列表[[BlockerList]] 的形式维护阻止器,该列表 可能会无限增长(因为某些阻止器类型只是到期, 但不会被移除)。 选择这种结构是为了便于说明,而不是为了 提高效率。除这里定义的少数算法之外,此阻止器结构的细节 不可观察,这应当为实现以更高效的方式处理它 提供充足空间。

2.4. Mixin 算法

一个InPagePermissionMixin elementisValid 获取器步骤为:
  1. 返回 element阻止器是否为 Nothing。

一个InPagePermissionMixin elementinvalidReason 获取器步骤为:
  1. 如果 element阻止器为 Nothing,则返回 ""

  2. 否则,返回 element阻止器的原因字符串。

一个InPagePermissionMixin elementinitialPermissionStatus 获取器步骤为:
  1. 返回 element 的内部[[InitialPermissionStatus]]

一个InPagePermissionMixin elementpermissionStatus 获取器步骤为:
  1. 返回为 element获取当前 权限状态的结果。

如何为一个InPagePermissionMixin element 获取当前权限状态 取决于包含该混入的具体元素。 因此,每个元素都必须定义自己的算法。

2.5. Mixin 事件算法

要为 element 可能分派 onvalidstatechange
  1. oldState[[LastNotifiedValidState]]

  2. newStateelement阻止器是否为 Nothing。

  3. [[LastNotifiedValidState]] 设置为 newState

  4. oldReason[[LastNotifiedInvalidReason]]

  5. newReasonelementinvalidReason

  6. [[LastNotifiedInvalidReason]] 设置为 newReason

  7. 如果 oldState != newStateoldReason != newReason, 则:

    1. event 为一个新的Event

    2. 使用 typeonvalidationstatuschange”、 bubbles true 和 cancelable true初始化 event

    3. event分派element

要为 element 分派 onpromptaction
  1. event 为一个新的Event

  2. 使用 typeonpromptaction”、 bubbles true 和 cancelable true初始化 event

  3. event分派element

要为 element 分派 onpromptdismiss
  1. event 为一个新的Event

  2. 使用 typeonpromptdismiss”、 bubbles true 和 cancelable true初始化 event

  3. event分派element

3. 共同渲染和样式限制

权限元素是不可退化部件,主要 像 button 一样渲染。 按钮标签在很大程度上应由浏览器而非页面 决定,并以文本和图标的形式反映[[Features]] 中列出的一个或多个 强大功能。该元素还可以传达 底层强大功能当前状态的信息。实际渲染由各 元素定义。

页面可以影响权限元素的样式,但会受到 防止滥用的约束(例如字体和标签本身的最小及 最大尺寸)。页面还可以通过 lang 属性为文本选择区域设置。

权限元素支持回退内容,尚不支持相应元素的 浏览器将显示这些内容。请注意, 即使浏览器支持相应权限元素,也存在 回退到其回退内容的情况。

3.1. 呈现

详细描述用户代理 UI 的先例并不多。 给用户代理保留更多自由度可能更好。

权限元素包含由浏览器选择的内容、文本,或许还有一个 图标。激活它们通常会提示用户作出选择。 这提供了两部分用户可以交互的用户界面。 用户 代理可以在很大程度上自由决定这两者——元素的渲染以及 后续的权限 提示——采用它认为最能传达元素意图的方式。

权限元素呈现的 UI 选项包括:

鼓励用户 代理以与程序或其运行平台中类似用法一致的方式 命名或描述强大功能

非常非规范性的示例可能包括:

3.2. 样式

权限元素会限制可应用于它们的样式。 这些约束分为三类:

  1. 如果条件不满足,则停用该元素。

  2. 由用户代理定义的样式表强制应用某些样式。

  3. 用户代理对其他样式强制实施界限,这些界限 无法轻易用 CSS 表达。例如,当样式界限是 相对于元素的计算样式表示时。

3.2.1. 停用元素的条件

如果其中一个条件未满足,则添加一个 类型为style_invalid临时阻止器

'color'、'background-color' 默认设置为用户代理的默认 button 颜色。 两种颜色之间的对比度必须至少为 3。 Alpha 必须为 1。
'font-size' 如果指定值表示为<relative-size>

定义“alpha”。

3.2.2. 用户代理定义的样式表

权限元素应使用以下样式渲染:

@namespace "http://www.w3.org/1999/xhtml";
permission, geolocation {
  opacity: 1.0;
  line-height: normal !important;
  whitespace: nowrap !important;
  user-select: none !important;
  appearance: auto !important;
  box-sizing: content-box !important;
  vertical-align: middle !important;
  text-emphasis: initial !important;
  text-shadow: initial !important;
}

3.2.3. 用户代理定义的其他样式界限

权限元素为样式定义了若干界限。例如,我们希望 字体大小受到约束。样式界限说明如下。

为了便于表示,我们设想可以在 CSS 规则中通过 computed 访问元素的计算 值,就像可以通过 inherit 关键字访问元素的继承值一样。 那么,以下样式表可表示这些样式界限:

@namespace "http://www.w3.org/1999/xhtml";
permission {
  outline-offset: clamp(0, computed, none); /* 不允许负的 outline-offset。 */
  font-weight: clamp(200, computed, none);  /* 不允许低于 200 的 font-weight。 */
  word-spacing: clamp(0, computed, 0.5em);  /* word-spacing 介于 0..0.5em */
  letter-spacing: clamp(-0.05em, commputed, 0.2em);  /* letter-spacing 介于 -0.05..0.2em */

  min-height: clamp(1em, computed, none);
  max-height: clamp(none, computed, 3em);
  min-width: clamp(none, computed, calc(fit-content));

  border-width: clamp(none, computed, 1em);

  font-style: if(computed = "normal" or computed = "italic", computed, "normal");
  display: if (computed = "inline-block" or computed = "none", computed, "inline-block");
  cursor: if (computed = "pointer" or computed = "not-allowed", computed, "pointer")
}

此外,还会根据难以用 CSS 表达的条件应用一些规则。

如果heightauto,则应用:

@namespace "http://www.w3.org/1999/xhtml";
permission {
  padding-top: clamp(1em, computed, none);
  padding-bottom: calc(padding-top);
}

如果widthauto,则应用:

@namespace "http://www.w3.org/1999/xhtml";
permission {
  padding-left: clamp(none, computed, 5em);
  padding-right: calc(padding-left);
}

如果元素不具备以下全部条件,则应用以下样式表:

@namespace "http://www.w3.org/1999/xhtml";
permission {
  max-width: clamp(none, computed, calc(3 * fit-content));
}

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

未在上文或本节规则中列出,且在逻辑上不等同于 此处提到的某个属性的属性,将被忽略。

3.3. 回退

不支持某个特定权限元素的用户 代理会将其识别为HTMLUnknownElement 并将其子项渲染为 普通 HTML。 支持此类元素的用户 代理通常应按§ 3 共同渲染和样式限制中的描述 渲染元素,但在一种情况下仍 必须渲染回退内容

如果内部[[BlockerList]] 包含一个记录,其 阻止原因type_invalid, 则 permission 元素应渲染回退内容, 而不是 permission 的通常渲染。

在此添加示例。

4. permission 元素

注: permission 元素是最初提出的页面内权限 元素,可以与任何强大功能或功能组合配合使用。 虽然我们不希望预先限制未来的标准讨论,但目前 预计此元素将被删除,转而采用后续章节中详细说明的 更具体元素。

permission 元素可以请求任意强大功能

类别
流式内容
短语内容
交互式内容
可感知内容
可以使用此元素的上下文
需要短语内容的地方。
内容模型
流式内容
内容属性
全局属性
权限元素属性
type — 此元素适用的权限类型。
lang — 类似于全局lang 属性。
无障碍考量
DOM 接口
HTMLPermissionElement

添加无障碍 考量。

对照当前提案检查属性、 事件处理器和无效原因的名称。

permission 元素的内容(如有)是其回退内容

type 属性控制 permission 元素被激活时的行为。它是一个枚举属性, 其值为强大功能名称。它既没有 缺失值默认状态,也没有无效值默认状态。

lang 属性与 全局lang 属性相同。 permission 元素会观察该属性,以选择本地化文本。

tabindex 全局内容属性在 permission 元素上的默认 值为 0。

[Exposed=Window]
interface HTMLPermissionElement : HTMLElement {
  [HTMLConstructor] constructor();
  [CEReactions, Reflect] attribute DOMString type;
  static boolean isTypeSupported(DOMString type);
};
HTMLPermissionElement includes InPagePermissionMixin;

type 属性反映 type 元素属性。

isTypeSupported(type) 静态操作用于确定给定的DOMString type, 即给定的枚举形式的强大功能是否受支持。 它可预测创建 permission 元素并为其分配给定 type 字符串是否可行,或者是否会创建 一个被type_invalid 永久阻止器阻止的元素。

4.1. permission 元素内部状态

permission 元素具有与InPagePermissionMixin 相同的内部槽,如§ 2.1 Mixin 内部状态中所述。

4.2. permission 元素的特殊行为

permission 元素具有一些出人意料的行为,以支持其 安全属性:

4.2.1. type 属性

权限类型不能修改。随意修改权限类型 可能导致用户困惑,因此我们希望阻止这种情况。不过, 由于页面可能动态创建 permission 元素,我们仍需要提供 修改它的 API。为此,我们区分新初始化状态和 空状态或无效状态(无权限),前者允许设置 类型,后者则不允许。

示例:

// 更改有效类型:
var pepc = document.createElement("permission");
pepc.type = "camera";  // 可以。
pepc.type;  // "camera"。
pepc.type = "geolocation";  // 不可以。若作为初始赋值则可以。
pepc.type;  // "camera"。反映未发生变化的内部状态。

// 设置无效类型:
pepc = document.createElement("permission");
pepc.type = "icecream";  // 冰淇淋不是强大的浏览器功能。不可以。
pepc.type;  // ""。反映内部状态。
pepc.type = "camera";  // 仍然不可以,因为 type 已经设置过。
                       // 若作为初始赋值则可以。
pepc.type;  // ""。反映未发生变化的内部状态。

HTMLPermissionElement 的type 获取器步骤为:
  1. 如果[[Features]] 为 null:返回 ""

  2. 返回一个字符串,其中包含[[Features]] 中所有强大功能名称的连接结果, 并以“ ”分隔。

HTMLPermissionElement 的type 设置器步骤为:
  1. 如果[[Features]] 不为 null:返回。

  2. [[Features]] 设置为 «»。

  3. features 为使用输入字符串调用解析类型字符串的结果。

  4. 如果 features 为 None,则返回。

  5. 将每个强大功能名称追加[[Features]] 有序集合中。

  6. [[InitialPermissionStatus]] 设置为获取当前 权限状态的结果。

注:受支持的强大功能集合由实现定义

要查询某项功能(或一组功能)是否受支持:

HTMLPermissionElement 的isTypeSupported() 方法 使用DOMString type 参数时的步骤为:
  1. features 为使用 type 调用解析类型字符串的结果。

  2. 返回 features 是否不为 None。

要将给定字符串 type 解析为类型 字符串
  1. list 为将 type 解析为由空白分隔的 强大功能名称字符串的结果。

  2. 如果发生任何错误,则返回 None。

  3. 检查强大功能集合是否受 用户代理HTMLPermissionElement 所支持。如果不支持,则返回 None。

  4. 返回 list

4.3. permission 元素算法

HTMLPermissionElement constructor() 的步骤为:
  1. 将内部[[Features]] 槽初始化为 null。

  2. 将内部[[BlockerList]] 初始化为 «»。

  3. 将内部[[LastNotifiedValidState]] 初始化为 false。

  4. 将内部[[LastNotifiedInvalidReason]] 初始化为空 字符串。

  5. 将内部[[InitialPermissionStatus]] 初始化为获取当前 权限状态的结果。

HTMLPermissionElement插入步骤为:
  1. 如果[[Features]] 为 null,则将[[Features]] 设置为 «»。

  2. 将内部[[BlockerList]] 初始化为 «»。

  3. this追加节点可导航对象[[PermissionElements]]

  4. 将内部[[IntersectionRect]] 初始化为 undefined。

  5. 使用 IntersectionObserver 回调和 «[ "rootMargin" → "-4px" ]» 构造新的IntersectionObserver, 并将内部[[IntersectionObserver]] 初始化为其结果。

  6. 调用[[IntersectionObserver]].observe(this)。

  7. 如果[[Features]] 为空,则使用原因type_invalid 添加永久阻止器

  8. 如果this类型不允许,则使用unsuccesful_registration 添加临时阻止器

  9. 使用原因 recently_attached 添加到期阻止器

  10. 如果this节点可导航对象可遍历可导航对象 是一个围栏可导航对象,则使用illegal_subframe 添加永久阻止器

  11. this可能分派 onvalidstatechange

HTMLPermissionElement移除步骤为:
  1. 节点可导航对象[[PermissionElements]]移除this

  2. this节点可导航对象重新检查类型 许可性

  3. this可能分派 onvalidstatechange

给定 event 时,一个 permission element激活行为为:
  1. 断言element[[Features]] 不为 null。

  2. 如果 element[[Features]] 为空,则返回。

  3. 如果 event.isTrusted 为 false,则返回。

  4. 如果 element.isValid 为 false,则返回。

  5. descriptor 为为 element构建权限 描述符的结果。

  6. 请求使用descriptor 描述的强大功能的权限。

  7. 如果上一步被用户取消或关闭,则在 this分派 onpromptdismiss 并返回。

    [PERMISSIONS] 规范假定请求使用权限 总会成功。也就是说,它假定用户总会作出 选择,并且算法总会给出与该选择对应的 grant/deny 答案。但你无法强迫用户这样做。 一些用户代理可能一方面为明确 拒绝提供一种 UI 控件(例如“拒绝”按钮),另一方面为取消或关闭 请求对话框提供另一种控件(例如右上角的“X”按钮)。尽管底层规范中 没有明确的挂钩,我们仍在此区分这两种操作。

  8. this分派 onpromptaction

要为一个HTMLPermissionElement element 构建权限描述符

[Permissions] 规范假定描述符描述的是 不带参数的单个权限(例如 enableHighAccuracy 的等效项)。 在此,我们假定一种表达能力更强的权限模型。 这需要解决——很可能应在上游 [Permissions] 中解决,并在此处作相应调整。

  1. result 为一个新的PermissionDescriptor

  2. 填充 result

  3. 返回 result

HTMLPermissionElement 的IntersectionObserver 回调实现 IntersectionObserverCallback 并运行以下步骤:
  1. 断言IntersectionObserverroot文档

  2. entries 为第一个回调参数的值,即 交叉观察器条目列表

  3. 断言entries为空

  4. entryentries 的最后一个

  5. 如果 entry.isVisible, 则:

    1. 使用intersection_occluded_or_distorted 移除阻止器

    2. 使用intersection_out_of_viewport_or_clipped 移除阻止器

  6. 否则:

    1. 如果 entry.intersectionRatio >= 1,则:

      1. reasonintersection_occluded_or_distorted

    2. 否则:

      1. reasonintersection_out_of_viewport_or_clipped

    3. 使用 reason添加临时 阻止器

  7. 如果[[IntersectionRect]] 不等于 entry.intersectionRect, 则使用 intersection_changed 添加到期阻止器

  8. [[IntersectionRect]] 设置为 entry.intersectionRect

  9. this可能分派 onvalidstatechange

是否需要定义 字典相等性?

要确定一个 element类型是否允许
  1. 断言element节点可导航对象[[PermissionElements]] 包含 element

  2. count 为 0。

  3. 对于 element节点可导航对象[[PermissionElements]] 中的每个 current

    1. 如果 currentelement,则中断

    2. 如果 element.[[Features]]current.[[Features]] 相等,则将 count 加 1。

  4. 返回 count 是否小于 3。

要为一个 document 重新检查类型许可性
  1. 对于 document[[PermissionElements]] 中的每个 current

    1. 如果 current类型允许,则从 current 中使用 unsuccesful_registration 移除阻止器

要为一个HTMLPermissionElement element 获取当前权限状态
  1. typeselement 的内部[[Features]]

  2. 如果 types 为 null 或 types, 则返回prompt

  3. currentgranted

  4. 对于 types 中的每个 type

    1. state 为针对 type获取当前权限 状态的结果。

    2. 假定以下顺序,令 currentcurrentstate 中较小者: granted > prompt > denied

  5. 返回 current

“没有有效权限类型” 的 PermissionState 应为何值尚不明确。 此处我根据 Chrome 的实现选择了“prompt”,但该 选择是任意的。

5. geolocation 元素

HTML geolocation 元素可以请求访问 "geolocation"

类别
流式内容
短语内容
交互式内容
可感知内容
可以使用此元素的上下文
需要短语内容的地方。
内容模型
流式内容
内容属性
全局属性
权限元素属性
autolocate — 是否立即定位(如果权限已授予)。
watch — 是读取一次位置,还是持续监视位置。
无障碍考量
DOM 接口
HTMLGeolocationElement

isValidinvalidReason, 以及全局 langtabindex 内容属性,以及 onpromptactiononpromptdismissonvalidationstatuschange 事件处理器遵循§ 2 HTML 权限元素的共同行为: InPagePermissionMixin中的描述。

autolocate 属性决定 geolocation 元素是否应立即开始定位(如果 权限已授予)。

watch 属性决定 geolocation 元素是报告一次位置还是持续报告。

[Exposed=Window]
interface HTMLGeolocationElement : HTMLElement {
  [HTMLConstructor] constructor();

  readonly attribute GeolocationPosition? position;
  readonly attribute GeolocationPositionError? error;
  [CEReactions, Reflect] attribute boolean autolocate;
  [CEReactions, Reflect] attribute boolean watch;

  attribute EventHandler onlocation;
};
HTMLGeolocationElement includes InPagePermissionMixin;

如果用户已决定允许访问地理位置信息,则 只读属性positionerror 会反映当前 GeolocationPositionGeolocationPositionError 值,就像 PositionCallbackPositionErrorCallback 回调(分别)会返回的值一样

如果布尔属性autolocate 为 true, 且用户已经授予 "geolocation" 权限,则 geolocation 元素附加到文档时应立即检索位置。如果在 插入时权限尚未授予,则此属性不起作用。

如果布尔属性watch 设置为 true,则每次位置变化时都会调用onlocation 事件,其行为与watchPosition 一致。

当位置可用时,会在 onlocation 事件处理器上 分派一个Event。 分派事件时,位置或关于位置检索失败的信息 可通过positionerror 属性获取。根据 watch 元素,此操作可能发生一次(缺失或为 false 时), 或持续发生(为 true 时)。

HTMLGeolocationElement 旨在映射Geolocation 接口。 两者存在直接对应关系:

position PositionCallback 的结果。
error PositionErrorCallback 的结果。
watch 使用watchPosition()
¬ watch 使用getCurrentPosition()

5.1. geolocation 元素内部状态

geolocation 元素使用InPagePermissionMixin 的所有内部槽,如§ 2.1 Mixin 内部状态中所述。此外, geolocation 还具有以下内部槽:

5.2. geolocation 元素算法

HTMLGeolocationElement constructor() 的步骤为:
  1. 将内部[[Features]] 槽初始化为 « "geolocation" »

  2. 将内部[[BlockerList]] 初始化为 «»。

  3. 将内部[[LastNotifiedValidState]] 初始化为 false。

  4. 将内部[[LastNotifiedInvalidReason]] 初始化为空 字符串。

  5. 将内部[[InitialPermissionStatus]] 初始化为获取当前 权限状态的结果。

  6. 将内部[[watchIDs]] 初始化为 « watchID »,其中 watchID 是一个大于零的、由实现定义unsigned long

  7. 将内部[[position]] 初始化为 null。

  8. 将内部[[positionError]] 初始化为 null。

HTMLGeolocationElement插入步骤为:
  1. 将内部[[BlockerList]] 初始化为 «»。

  2. this追加节点可导航对象[[PermissionElements]]

  3. 将内部[[IntersectionRect]] 初始化为 undefined。

  4. 使用 IntersectionObserver 回调和 «[ "rootMargin" → "-4px" ]» 构造新的IntersectionObserver, 并将内部[[IntersectionObserver]] 初始化为其结果。

  5. 调用[[IntersectionObserver]].observe(this)。

  6. 如果[[Features]] 为空,则使用原因type_invalid 添加永久阻止器

  7. 如果this类型不允许,则使用unsuccesful_registration 添加临时阻止器

  8. 使用原因 recently_attached 添加到期阻止器

  9. 如果this节点可导航对象可遍历可导航对象 是一个围栏可导航对象,则使用illegal_subframe 添加永久阻止器

  10. this可能分派 onvalidstatechange

  11. 可能自动定位

HTMLGeolocationElement移除步骤为:
  1. 节点可导航对象[[PermissionElements]]移除this

  2. this节点可导航对象重新检查类型 许可性

  3. this可能分派 onvalidstatechange

给定 event 时,HTMLGeolocationElement element激活行为为:
  1. 断言element[[Features]] 不为 null。

  2. 如果 element[[Features]] 为空,则返回。

  3. 如果 event.isTrusted 为 false,则返回。

  4. 如果 element.isValid 为 false,则返回。

  5. descriptor 为为 element构建权限 描述符的结果。

  6. 请求使用descriptor 描述的强大功能的权限。

  7. 如果上一步被用户取消或关闭,则在 this分派 onpromptdismiss 并返回。

    [Permissions] 规范假定请求使用权限 总会成功。也就是说,它假定用户总会作出 选择,并且算法总会给出与该选择对应的 grant/deny 答案。但你无法强迫用户这样做。 一些用户代理可能一方面为明确 拒绝提供一种 UI 控件(例如“拒绝”按钮),另一方面为取消或关闭 请求对话框提供另一种控件(例如右上角的“X”按钮)。尽管底层规范中 没有明确的挂钩,我们仍在此区分这两种操作。

  8. this分派 onpromptaction

  9. 获取位置

position 获取器步骤为返回 [[position]] 的值。
error 获取器步骤为返回 [[positionError]] 的值。
可能自动定位
  1. 如果获取当前 权限状态的结果不是 granted, 则返回。

  2. 如果autolocate 不为 true,则返回。

  3. 获取位置

获取位置
  1. positionCallback 为一个执行以下步骤的PositionCallback

    1. this[[positionError]] 设置为 undefined。

    2. this[[position]] 设置为PositionCallback 的 position 参数。

    3. this分派 onlocation

  2. errorCallback 为一个执行以下步骤的PositionErrorCallback

    1. this[[position]] 设置为 undefined。

    2. this[[positionError]] 设置为PositionCallback 的 positionError 参数。

    3. this分派 onlocation

  3. positionOptions 为 «[]»

  4. geolocation相关全局对象Geolocation

  5. 如果thiswatch 为 true:

    1. 使用 geolocationpositionCallbackerrorCallbackpositionOptionsthis[[watchIDs]] 请求位置

  6. 否则:

    1. 使用 geolocationpositionCallbackerrorCallbackpositionOptions 请求位置

5.3. geolocation 元素事件算法

要为 element 分派 onlocation
  1. event 为一个新的Event

  2. 使用typeonlocation初始化 event

  3. event分派element

6. 安全与隐私考量

注:安全与隐私考量可在说明文档中的 此处此处找到, 参见说明文档。 本节最终将包含这些说明文档章节中 适合纳入规范的转述。

索引

本规范定义的 术语

通过引用定义的 术语

参考文献

规范性参考文献

[COMPOSITING-2]
合成与混合模块第 2 级。 编辑草案。URL:https://drafts.csswg.org/compositing-2/
[CSS-ALIGN-3]
Elika Etemad; Tab Atkins Jr.。CSS 盒对齐模块 第 3 级。URL:https://drafts.csswg.org/css-align/
[CSS-ANCHOR-POSITION-1]
Tab Atkins Jr.; Elika Etemad; Ian Kilpatrick。CSS 锚点定位模块第 1 级。URL:https://drafts.csswg.org/css-anchor-position-1/
[CSS-BACKGROUNDS-3]
Elika Etemad; Brad Kemper。CSS 背景与 边框模块第 3 级。URL:https://drafts.csswg.org/css-backgrounds/
[CSS-BORDERS-4]
Elika Etemad; 等。CSS 边框与盒装饰 模块第 4 级。URL:https://drafts.csswg.org/css-borders-4/
[CSS-BREAK-3]
Rossen Atanassov; Elika Etemad。CSS 分片模块 第 3 级。URL:https://drafts.csswg.org/css-break/
[CSS-COLOR-ADJUST-1]
Elika Etemad; 等。CSS 颜色调整 模块第 1 级。URL:https://drafts.csswg.org/css-color-adjust-1/
[CSS-CONDITIONAL-5]
Chris Lilley; 等。CSS 条件规则 模块第 5 级。URL:https://drafts.csswg.org/css-conditional-5/
[CSS-DISPLAY-4]
Elika Etemad; Tab Atkins Jr.。CSS 显示模块 第 4 级。URL:https://drafts.csswg.org/css-display-4/
[CSS-FLEXBOX-1]
Elika Etemad; Tab Atkins Jr.; Rossen Atanassov。CSS 弹性盒布局模块第 1 级。URL:https://drafts.csswg.org/css-flexbox/
[CSS-FONTS-4]
Chris Lilley。CSS 字体模块第 4 级。 URL:https://drafts.csswg.org/css-fonts-4/
[CSS-LISTS-3]
Elika Etemad; Tab Atkins Jr.。CSS 列表与计数器 模块第 3 级。URL:https://drafts.csswg.org/css-lists-3/
[CSS-OVERSCROLL-1]
Majid Valipour。CSS 过度滚动行为模块 第 1 级。URL:https://drafts.csswg.org/css-overscroll-1/
[CSS-PAGE-3]
Elika Etemad。CSS 分页媒体模块第 3 级。URL:https://drafts.csswg.org/css-page-3/
[CSS-POSITION-3]
Elika Etemad; Tab Atkins Jr.。CSS 定位布局 模块第 3 级。URL:https://drafts.csswg.org/css-position-3/
[CSS-RUBY-1]
Elika Etemad; 等。CSS 旁注标记布局模块 第 1 级。URL:https://drafts.csswg.org/css-ruby-1/
[CSS-SCROLL-ANCHORING-1]
Tab Atkins Jr.。CSS 滚动锚定模块 第 1 级。URL:https://drafts.csswg.org/css-scroll-anchoring/
[CSS-SCROLL-SNAP-1]
Matt Rakow; 等。CSS 滚动捕捉模块第 1 级。URL:https://drafts.csswg.org/css-scroll-snap-1/
[CSS-SIZING-3]
Tab Atkins Jr.; Elika Etemad。CSS 盒尺寸模块 第 3 级。URL:https://drafts.csswg.org/css-sizing-3/
[CSS-SIZING-4]
Tab Atkins Jr.; Elika Etemad; Jen Simmons。CSS 盒 尺寸模块第 4 级。URL:https://drafts.csswg.org/css-sizing-4/
[CSS-TEXT-4]
Elika Etemad; 等。CSS 文本模块第 4 级。URL:https://drafts.csswg.org/css-text-4/
[CSS-UI-4]
Tab Atkins Jr.; Florian Rivoal。CSS 基本用户界面 模块第 4 级。URL:https://drafts.csswg.org/css-ui-4/
[CSS-WILL-CHANGE-1]
Tab Atkins Jr.。CSS Will Change 模块第 1 级。URL:https://drafts.csswg.org/css-will-change/
[CSS2]
Bert Bos; 等。层叠样式表第 2 级修订版 1 (CSS 2.1)规范。URL:https://drafts.csswg.org/css2/
[DOM]
Anne van Kesteren。DOM 标准。现行标准。 URL:https://dom.spec.whatwg.org/
[FENCED-FRAME]
围栏框架。社区组报告草案。 URL:https://wicg.github.io/fenced-frame/
[GEOLOCATION]
Marcos Caceres; Reilly Grant。地理位置。 URL:https://w3c.github.io/geolocation/
[GEOMETRY-1]
Sebastian Zartner; Yehonatan Daniv。几何接口 模块第 1 级。URL:https://drafts.csswg.org/geometry/
[HR-TIME-3]
Yoav Weiss。高分辨率时间。URL:https://w3c.github.io/hr-time/
[HTML]
Anne van Kesteren; 等。HTML 标准。 现行标准。URL:https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola。Infra 标准。现行标准。URL:https://infra.spec.whatwg.org/
[INTERSECTION-OBSERVER]
Stefan Zager; Emilio Cobos Álvarez; Traian Captan。交叉观察器。URL:https://w3c.github.io/IntersectionObserver/
[MANIFEST-APP-INFO]
Aaron Gustafson。Web 应用清单——应用 信息。URL:https://w3c.github.io/manifest-app-info/
[MEDIAQUERIES-5]
Tab Atkins Jr.; 等。媒体查询第 5 级。URL:https://drafts.csswg.org/mediaqueries-5/
[Permissions]
Marcos Caceres; Mike Taylor。权限。URL: https://w3c.github.io/permissions/
[SVG2]
Amelia Bellamy-Royds; 等。可缩放矢量图形(SVG) 2。URL:https://svgwg.org/svg2-draft/
[WEBIDL]
Edgar Chen; Timothy Gu。Web IDL 标准。现行 标准。URL:https://webidl.spec.whatwg.org/

IDL 索引

interface mixin InPagePermissionMixin {
  readonly attribute boolean isValid;
  readonly attribute InPagePermissionMixinBlockerReason invalidReason;
  readonly attribute PermissionState initialPermissionStatus;
  readonly attribute PermissionState permissionStatus;

  attribute EventHandler onpromptaction;
  attribute EventHandler onpromptdismiss;
  attribute EventHandler onvalidationstatuschange;
};

enum InPagePermissionMixinBlockerReason {
  // 无阻止原因。
  "",

  // 所有 InPagePermissionMixin 使用者均支持的阻止原因。
  "illegal_subframe", "unsuccesful_registration",
  "recently_attached", "intersection_changed",
  "intersection_out_of_viewport_or_clipped",
  "intersection_occluded_or_distorted", "style_invalid",

  // HTMLPermissionElement 特有的阻止原因。
  "type_invalid",
};

[Exposed=Window]
interface HTMLPermissionElement : HTMLElement {
  [HTMLConstructor] constructor();
  [CEReactions, Reflect] attribute DOMString type;
  static boolean isTypeSupported(DOMString type);
};
HTMLPermissionElement includes InPagePermissionMixin;

[Exposed=Window]
interface HTMLGeolocationElement : HTMLElement {
  [HTMLConstructor] constructor();

  readonly attribute GeolocationPosition? position;
  readonly attribute GeolocationPositionError? error;
  [CEReactions, Reflect] attribute boolean autolocate;
  [CEReactions, Reflect] attribute boolean watch;

  attribute EventHandler onlocation;
};
HTMLGeolocationElement includes InPagePermissionMixin;

问题索引

详细描述用户代理 UI 的先例并不多。 给用户代理保留更多自由度可能更好。
定义“alpha”。
在此添加示例。
添加无障碍考量。
对照当前提案检查属性、事件处理器和无效原因的名称。
[PERMISSIONS] 规范假定请求使用权限 总会成功。也就是说,它假定用户总会作出 选择,并且算法总会给出与该选择对应的 grant/deny 答案。但你无法强迫用户这样做。 一些用户代理可能一方面为明确 拒绝提供一种 UI 控件(例如“拒绝”按钮),另一方面为取消或关闭 请求对话框提供另一种控件(例如右上角的“X”按钮)。尽管底层规范中 没有明确的挂钩,我们仍在此区分这两种操作。
[Permissions] 规范假定描述符描述的是 不带参数的单个权限(例如 enableHighAccuracy 的等效项)。 在此,我们假定一种表达能力更强的权限模型。 这需要解决——很可能应在上游 [Permissions] 中解决,并在 此处作相应调整。
是否需要定义字典相等性?
“没有有效权限类型”的 PermissionState 应为何值尚不明确。 此处我根据 Chrome 的实现选择了“prompt”,但该 选择是任意的。
[Permissions] 规范假定请求使用权限 总会成功。也就是说,它假定用户总会作出 选择,并且算法总会给出与该选择对应的 grant/deny 答案。但你无法强迫用户这样做。 一些用户代理可能一方面为明确 拒绝提供一种 UI 控件(例如“拒绝”按钮),另一方面为取消或关闭 请求对话框提供另一种控件(例如右上角的“X”按钮)。尽管底层规范中 没有明确的挂钩,我们仍在此区分这两种操作。