能力 · API
registerProtocolHandler() 与 manifest 协议处理程序
发布于
把 Web 应用注册为 mailto: 或 web+music: 这类 URL 协议的处理程序,有两条路。navigator.registerProtocolHandler(scheme, url) 由页面发起、向用户弹出询问,在普通标签页里就能用;manifest 的 protocol_handlers 成员在 PWA 安装时向操作系统注册,不需要页面发起任何提示。两者都执行 HTML 标准的「normalize protocol handler parameters」步骤,所以协议与 URL 的规则完全一致:方法会抛异常的值,在 manifest 里会被静默丢弃。
registerProtocolHandler() 在桌面端 Firefox 2 与 Chrome 13 起就有,Edge 79 与 Opera 11.6 跟进;Chrome 77 起 url 只接受 http: 与 https:。Safari 没有实现,Android 上没有任何浏览器暴露它(BCD api.Navigator.registerProtocolHandler)。unregisterProtocolHandler() 只存在于 Chromium,始于 Chrome 38。manifest 成员是 Chrome 96 与 Edge 96 的桌面专属功能,完整支持情况见兼容性表。
navigator.registerProtocolHandler(scheme, url)navigator.unregisterProtocolHandler(scheme, url){ "protocol_handlers": [ { "protocol": "web+music", "url": "/play?song=%s" } ]}两个方法都返回 undefined。注册在调用返回后并行进行,没有可等待的 Promise,也无法得知用户是否接受了提示。两者都带 [SecureContext],url 的同源要求本身也蕴含了这一点。激活带已注册协议的链接时,浏览器把完整链接做百分号编码、替换掉 %s,然后在新的顶层浏览上下文中导航到结果。
方法参数与 manifest 条目成员一一对应。
| 方法参数 | manifest 成员 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
scheme |
protocol |
DOMString |
是 | 检查前先转小写。必须是安全名单内的协议,或以 web+ 开头后接一个或多个小写 ASCII 字母(web+music 可以,web+music2 与 web+ 不行)。末尾带冒号即无效。 |
url |
url |
DOMString |
是 | 必须包含字面量 %s。方法按文档解析、成员按 manifest URL 解析;结果必须是文档同源的 http: 或 https: URL,manifest 还要求位于其 scope 之内。 |
安全名单内的协议是 bitcoin、ftp、ftps、geo、im、irc、ircs、magnet、mailto、matrix、mms、news、nntp、openpgp4fpr、sftp、sip、sms、smsto、ssh、tel、urn、webcal、wtai 与 xmpp。manifest 处理时会跳过缺少 protocol 或 url、规范化失败、超出 scope,或 url 与前面条目重复的项,并且不报告原因。
registerProtocolHandler() 与 unregisterProtocolHandler() 同步抛出。manifest 成员不抛任何异常,无效条目在处理阶段被丢弃。
| 异常 | 条件 |
|---|---|
SecurityError |
scheme 既不在安全名单内,也不是 web+ 加小写字母,包括带冒号的 "mailto:";解析后的 url 不是 http: 或 https:,或与文档不同源;浏览器拦截了注册,例如注册 http 本身。Chrome 还会在 Isolated Web App 中抛出,并提示改用 manifest 成员。 |
SyntaxError |
url 不含 %s;url 解析失败,%s 位于 host 或端口时必然如此。 |
示例为部署在 https://player.example/ 的播放器注册 web+music。处理路由是 /play?song=%s,点击 web+music:track/42 会在该源打开 /play,song 参数经 URLSearchParams 解码后仍是 web+music:track/42。
在设置页提供注册入口并给出手动回退
Section titled “在设置页提供注册入口并给出手动回退”先检测方法是否存在,再同时捕获两个异常名:这里的 SecurityError 多半是协议名写错,而用户拒绝提示时页面根本不会知道。Safari 和所有 Android 浏览器走回退分支,向用户说明如何改为粘贴链接。
const button = document.querySelector("#register-handler");
if (typeof navigator.registerProtocolHandler !== "function") { button.hidden = true; document.querySelector("#paste-link-help").hidden = false;} else { button.addEventListener("click", () => { try { navigator.registerProtocolHandler("web+music", "/play?song=%s"); button.textContent = "已请求,请在浏览器提示中确认"; } catch (err) { if (err.name === "SecurityError" || err.name === "SyntaxError") { console.error(`${err.name}: ${err.message}`); } else { throw err; } } });}HTML 标准要求浏览器记住被拒绝的注册、不再重复提示,所以拒绝后再点一次可能毫无反应;在按钮的帮助文字里把这一点说清楚。
在 manifest 中声明同一处理程序并读取启动 URL
Section titled “在 manifest 中声明同一处理程序并读取启动 URL”manifest 带上该条目后,已安装的用户无需提示即可获得关联。路由在 song 查询参数里收到整条链接(含协议),需要自己去掉前缀。
{ "name": "Player", "start_url": "/", "scope": "/", "protocol_handlers": [ { "protocol": "web+music", "url": "/play?song=%s" } ]}const launched = new URL(location.href).searchParams.get("song");
if (launched && launched.startsWith("web+music:")) { const trackId = launched.slice("web+music:".length); // "track/42" loadTrack(trackId);} else { showLibrary(); // 直接打开,而不是通过协议链接}路由要放在 manifest 的 scope 之内:超出 scope 的 url 会从处理后的 manifest 中被丢弃,安装照常完成,却没有处理程序,也没有任何警告。
移除用户不再需要的处理程序
Section titled “移除用户不再需要的处理程序”unregisterProtocolHandler() 接受同样的两个参数,只存在于 Chromium。要和 registerProtocolHandler() 分开检测,因为 Firefox 有前者没有后者。
function forgetHandler() { if (typeof navigator.unregisterProtocolHandler !== "function") { return false; // Firefox:只能在浏览器自己的设置里移除 } navigator.unregisterProtocolHandler("web+music", "/play?song=%s"); return true;}通过方法取消注册不影响 manifest 建立的关联;那一份随已安装应用一起移除。
- Manifest protocol_handlers,该成员自己的条目,含处理细节
- Manifest 文件处理程序(file_handlers),针对文件类型的同类操作系统注册
- 处理文件
- HTML Standard: registerProtocolHandler() method(html.spec.whatwg.org)
- HTML Standard: safelisted schemes(html.spec.whatwg.org)
- Web App Manifest incubations: protocol_handlers member(wicg.github.io)
- URL protocol handler registration for PWAs(developer.chrome.com)
- Handle protocols in Progressive Web Apps(learn.microsoft.com)
规范
- 图例
- 支持
- 部分支持
- 需开启标志
- 不支持
- 未知
| 浏览器 / 平台 | 支持 | 版本 | 置信度 | 来源 | 备注 |
|---|---|---|---|---|---|
| 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 核对)。