WebUSB API:从网页连接非标准 USB 设备
发布于
一句话: WebUSB 让网页可以请求访问操作系统标准设备类(键盘、鼠标等)之外的 USB 设备——这些设备原本需要原生驱动或原生应用——方式是向用户展示一个权限提示,与特定设备 配对,无需下载任何驱动。它是一份 WICG 规范,既不是 W3C 标准,也不在 W3C 标准化轨道 上。
WebUSB 由 Web 平台孵化社区组(WICG)以社区组草案报告的形式发布;规范声明它“既不是 W3C 标准,也不在 W3C 标准化轨道上”。MDN 将该 API 标记为实验性且非 Baseline, “因为它在部分最广泛使用的浏览器中不可用”。
WebUSB 存在的原因
Section titled “WebUSB 存在的原因”许多 USB 设备属于有操作系统驱动支持的标准化设备类,也可以通过 WebHID API 从网页访 问。而那些不属于标准类的设备,历来需要原生代码才能访问,这“使得这些设备无法被网页使 用”。WebUSB 让网页可以直接访问这些非标准化的设备服务。
安全上下文与瞬态激活
Section titled “安全上下文与瞬态激活”WebUSB 仅在安全上下文中可用。调用 requestDevice() 时,调用脚本必须处于瞬态激
活状态(即近期发生过用户手势);若在没有用户手势的情况下调用,返回的 Promise 会以
SecurityError 被拒绝。
请求与复用设备
Section titled “请求与复用设备”navigator.usb .requestDevice({ filters: [{ vendorId: 0x2341 }] }) .then((device) => { console.log(device.productName); // "Arduino Micro" console.log(device.manufacturerName); // "Arduino LLC" }) .catch((error) => { console.error(error); });requestDevice() 会对候选设备进行过滤(例如按 vendorId),根据规范,“UA 可能在
调用此函数时显示权限提示”。设备一旦获得授权后,navigator.usb.getDevices() 便可返
回此前已获授权的设备,而不会再次弹出提示:
navigator.usb.getDevices().then((devices) => { devices.forEach((device) => { console.log(device.productName); });});UA “也可能在设备连接处于活动状态时显示一个指示器”。
WebUSB 的安全模型依赖于 requestDevice() 的权限提示,并结合权限策略
(Permissions Policy)集成,而非采用设备端的允许列表(规范中说明,曾考虑过类似
CORS 的方案但未被采纳)。此外,规范定义的 USB 屏蔽列表(Blocklist) 会限制对特定
设备的访问,识别依据是 vendorId、productId 与 bcdDevice。另外,受保护的接口类
无论是否在屏蔽列表中,都会被单独限制访问 WebUSB。
同一时刻只能有一个执行上下文声明(claim)某个 USB 接口——若多个执行上下文尝试声明
同一接口,claimInterface() 会失败。
USBDevice 提供已配对设备的元数据以及用于控制它的方法。设备被组织为
USBConfiguration → USBInterface → USBAlternateInterface → USBEndpoint 的层
级结构,每一层都提供该层级的信息。传输结果由 USBInTransferResult/
USBOutTransferResult(以及用于流式端点的等时传输变体)表示。
设备可以通过 WebUSB 平台能力描述符(Platform Capability Descriptor)的
iLandingPage 字段声明一个着陆页——“设备制造商希望用户访问以控制其设备的着陆页”。
UA 的角色仅是建议性的:它“可以(MAY)在设备连接时建议用户导航到该 URL”。浏览器通过
一个规范定义的 GET_URL 设备请求获取该地址,该请求返回一个 URL 描述符(包含协议前
缀与 UTF-8 编码的 URL 字符串)。
在 Worker 中的可用性
Section titled “在 Worker 中的可用性”MDN 指出该特性在 Web Worker 中可用(WorkerNavigator.usb),此外主线程上还有
Navigator.usb。
- 在调用任何 WebUSB 方法之前先进行特性检测:
navigator.usb。 - 通过 HTTPS 提供页面——WebUSB 仅在安全上下文中可用。
- 仅在具有瞬态激活(用户手势)的脚本中调用
requestDevice();否则调用会以SecurityError被拒绝。 - 使用
filters(例如vendorId)将选择器范围限定到目标设备。 - 在后续访问中调用
getDevices()以复用此前已获授权的设备,而无需再次弹出提 示。 - 上线前检查当前浏览器兼容性——MDN 将 WebUSB 标记为实验性且非 Baseline。
- 如果你的设备声明了
iLandingPage,请记住浏览器的导航建议是可选的(MAY),并 非保证行为。