跳转到内容

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
  1. 仅桌面端可注册。
  2. Safari 未实现 `protocol_handlers` manifest 成员(MDN 兼容性表,2026-10-03 核对)。
  3. Safari 未实现 `protocol_handlers` manifest 成员(MDN 兼容性表,2026-10-03 核对)。
  4. 桌面版 Firefox 不依据 manifest 安装 Web 应用,也未实现 `protocol_handlers`(MDN 兼容性表,2026-10-03 核对)。
  5. Chromium 仅在桌面安装中提供 manifest 协议处理程序;Samsung Internet 未列出支持(MDN 兼容性表,2026-10-03 核对)。

源数据: /compatibility/protocol-handlers.json · 全球使用占比: 37 % (StatCounter 2026-05)

来源: 规范 · MDN · 最近核验 2026-06-24 · 置信度: 中 (由来源计算)

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”。

按 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。
  • 注意这项注册可能在无声中变成默认。规范的隐私说明提醒:“取决于操作系统的能力,协议处理 程序可能在用户并不明确知情的情况下成为某个协议的『默认』处理程序”,并列出了用户代理可 以采取的保护措施,包括移除该注册。