Manifest protocol_handlers
发布于 更新于
按 MDN,protocol_handlers 成员“指定一个对象数组,这些对象是该 Web 应用可以注册并处理的协
议”,并且“协议处理程序会把该应用注册进操作系统的应用偏好设置;这项注册把一个特定应用与给定
的协议方案关联起来”。MDN 自己给的说明是:“当在网页上使用 mailto:// 协议处理程序时,已注册
的邮件应用会被打开。”
- 图例
- 支持
- 部分支持
- 需开启标志
- 不支持
- 未知
| 浏览器 / 平台 | 支持 | 版本 | 置信度 | 来源 | 备注 |
|---|---|---|---|---|---|
| Chrome (Android) | 不支持 | — | 中 | 来源 | 1 |
| Chrome (Desktop) | 支持 | 96 | 中 | 来源 | — |
| Edge (Desktop) | 支持 | 96 | 中 | 来源 | — |
| Safari (iOS) | 不支持 | — | 中 | 来源 | 2 |
| Safari (macOS) | 不支持 | — | 中 | 来源 | 3 |
| Firefox (Desktop) | 不支持 | — | 中 | 来源 | 4 |
| Samsung Internet | 不支持 | — | 中 | 来源 | 5 |
- 仅桌面端可注册。
- Safari 未实现 `protocol_handlers` manifest 成员(MDN 兼容性表,2026-10-03 核对)。
- Safari 未实现 `protocol_handlers` manifest 成员(MDN 兼容性表,2026-10-03 核对)。
- 桌面版 Firefox 不依据 manifest 安装 Web 应用,也未实现 `protocol_handlers`(MDN 兼容性表,2026-10-03 核对)。
- Chromium 仅在桌面安装中提供 manifest 协议处理程序;Samsung Internet 未列出支持(MDN 兼容性表,2026-10-03 核对)。
MDN 把该成员标记为实验性。其 manifests.webapp.protocol_handlers 的
browser-compat-data 条目记录 Chrome 96 起支持,Edge 与 Opera 被标记为镜像 Chrome 的数据。
Firefox 与 Safari 记录为不支持,Android 上的 Chrome 同样记录为不支持;其余移动端条目
(Firefox for Android、Opera Android、iOS 上的 Safari、三星浏览器,以及 Android 与 iOS 的
WebView)记录为对上述引擎的镜像。
每个条目把一个 protocol 与一个 url 配成一对。按 MDN,protocol 是“一个必需的字符串,内
容为要处理的协议;例如:mailto、ms-word、web+jngl”,而 url 是“位于应用 scope 之内
的必需 HTTPS URL,用于处理该协议”,其中”%s 令牌会被替换为以该协议处理程序的方案开头的
URL”。MDN 还补充:“如果 url 是相对 URL,基准 URL 就是清单的 URL。”
MDN 的示例声明该应用“应被注册为处理 web+jngl 与 web+jnglstore 协议”:
{ "protocol_handlers": [ { "protocol": "web+jngl", "url": "/lookup?type=%s" }, { "protocol": "web+jnglstore", "url": "/shop?for=%s" } ]}MDN 描述了接下来发生的事:“在把 Web 应用注册为协议处理程序之后,当用户从浏览器或原生应用中
点击带有特定方案(例如 mailto:// 或 web+music://)的超链接时,已注册的 PWA 就会打开并接
收该 URL。”
Manifest Incubations 规范把这件事拆成两个角色。在安装时,“用户代理 SHOULD 向操作系统注册协 议处理程序”;此后“点击一个已注册的协议会启动已注册的应用。如果它就是这个 Web 应用,那么执行 [HTML] 中定义的 [invoke a protocol handler] 步骤,其中用户代理 SHOULD 导航到 url,并把相应 的浏览上下文设为一个新的顶级浏览上下文”。当多个应用声明同一协议时,规范预期“由操作系统让用 户选择应由哪个应用打开,并且也允许用户设置默认应用”。
规范自带的示例把替换过程说得很具体:对于位于
https://example.com/manifest.webmanifest 的清单,一个 web+music 处理程序配
"url": "/play?songId=%s",在 web+music://#1234 上被激活时,“用户代理会实例化一个新的顶
级浏览上下文,并导航到 https://example.com/play?songId=web+music://%231234”。
如何检测被替换的 URL 并回退
Section titled “如何检测被替换的 URL 并回退”按 MDN,%s 会被替换为“以该协议处理程序的方案开头的 URL”。所引用的来源没有把未经替换的
模板定义为回退 URL,因此该路由应当只接受文档所述的替换后形状,并让缺失或无效的值进入回退分
支:
// 清单指向的路由:/lookup?type=%s//// 注意这里的解析方式。MDN:"URLSearchParams 构造函数把加号(+)解释为空格,// 这可能会带来问题。"而在规范的示例结果中,"web+music" 的 "+" 在查询字符串里是// 字面保留的,所以要读取原始值。const encoded = location.search.match(/[?&]type=([^&]*)/)?.[1];let value = null;
try { value = encoded ? decodeURIComponent(encoded) : null;} catch { // 未经替换或格式错误的值,不是已处理的协议 URL。}
if (value?.startsWith('web+jngl:')) { // 这个值具有 MDN 所记录的、%s 被替换后的形状。 showLookupFor(value.slice('web+jngl:'.length));} else { // 缺失,或者不是 web+jngl URL。渲染带自身搜索框的普通查询页, // 而不是去解析一个并不存在的值。 showLookupForm();}- 按 MDN,把处理程序的
url保持在应用scope之内并使用 HTTPS。规范的处理步骤会跳过 任何归一化后 URL“不在清单 scope 之内”的条目,也会跳过protocol或url为 undefined 的条目。 - 不要指望任意方案都会被接受。在规范的示例中,第二个处理程序“会被忽略,因为所提供的协议
既不以
web+开头,也不属于安全名单内的方案”。 - 不要把同一个 URL 注册两次:按规范的处理步骤,如果已处理列表中已包含该归一化 URL,该条 目会被跳过。
- 权限提示并非必然出现,而呈现的列表可能被截短。按规范,“用户代理 SHOULD 在把某个协议
处理程序描述
protocol_handlers注册为宿主操作系统中该协议的默认处理程序之前,先向用 户请求许可”,并且“MAY 截短该列表……以便与宿主操作系统的惯例或限制保持一致”。 - 把注册当作依赖操作系统的事,而且它并不只发生在安装时。按 MDN,“把应用注册为处理 URL 方 案是依赖操作系统的。这项关联通常在应用安装期间完成,但也可以在之后从一个已安装的应用中 完成。”
- 解析整个 URL,而不是某个载荷。
%s被替换为“以该协议处理程序的方案开头的 URL”(MDN) ——在规范的示例里,查询值是完整的web+music://#1234,其中片段标记写作%23。 - 注意这项注册可能在无声中变成默认。规范的隐私说明提醒:“取决于操作系统的能力,协议处理 程序可能在用户并不明确知情的情况下成为某个协议的『默认』处理程序”,并列出了用户代理可 以采取的保护措施,包括移除该注册。
- Manifest protocol_handlers:为自定义 URL 方案注册 PWA ——能力视角的条目,包含更早的命令式注册 API。
- Manifest Protocol Handlers 支持情况——该成员的兼容 性数据集。
- Manifest scope——界定规范会接受哪些处理程序 URL 的成员。