十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Puppeteer BrowserContext.overridePermissions 详解:Web 权限授予机制、源码实现与向 setPermission 的迁移

Puppeteer BrowserContext.overridePermissions 详解:Web 权限授予机制、源码实现与向 setPermission 的迁移 Puppeteer BrowserContext.overridePermissions 详解Web 权限授予机制、源码实现与向 setPermission 的迁移【免费下载链接】puppeteerJavaScript API for Chrome and Firefox项目地址: https://gitcode.com/GitHub_Trending/puppeteer1/puppeteer本篇围绕 Puppeteer 官方 API 文档中的BrowserContext.overridePermissions()方法展开说明该方法的签名、参数语义与可用示例基于仓库源码剖析 CDP 与 WebDriver BiDi 两条通道下权限授予的底层实现与行为差异并给出从这一已弃用 API 迁移到setPermission()的对照指南。读完后你可以准确理解 Puppeteer 如何以 origin 为单位批量授予 Web 权限、各权限名称在浏览器协议层的真实映射以及如何编写权限隔离与清理的自动化逻辑。API 定位与弃用说明overridePermissions()是BrowserContext类上的抽象方法作用是为指定origin批量授予一组 Web 权限例如地理位置、摄像头、剪贴板。它主要服务于自动化测试场景当被测页面请求某项权限时可以让弹窗直接通过而不依赖人工交互。需要特别注意官方文档明确标注了该 API 的弃用状态——Warning: This API is now obsolete. in favor of BrowserContext.setPermission().源码中同样带有deprecated in favor of {link BrowserContext.setPermission}标注见 BrowserContext.ts。也就是说该 API 在当前仓库中仍然可用、仍有完整的 CDP 与 BiDi 实现但新代码应当优先使用setPermission()。本文会完整覆盖overridePermissions()的用法并在最后提供迁移对照。方法签名与参数官方文档给出的签名为class BrowserContext { abstract overridePermissions( origin: string, permissions: Permission[], ): Promisevoid; }参数说明参数类型说明originstring要授予权限的源例如https://example.compermissionsPermission[]要授予的权限数组。未列出的所有权限都会被自动拒绝all permissions that are not listed here will be automatically denied返回值Promisevoid这里有两个关键语义值得注意授予是全量替换而非追加对一个 origin 调用该方法时列表外的权限按文档语义被视为拒绝。BiDi 通道的实现会显式把所有未列出的权限逐一置为Denied见下文因此重复调用会以最后一次为准。Permission类型本身也已弃用源码中标注deprecated in favor of {link PermissionDescriptor}见 Browser.ts新 API 使用带描述符对象的PermissionDescriptor替代简单的字符串枚举。用法示例官方文档给出的最小示例——在默认浏览器上下文中覆盖权限const context browser.defaultBrowserContext(); await context.overridePermissions(https://html5demos.com, [geolocation]);补全为一个可直接运行的脚本演示授权 → 打开页面的典型流程import puppeteer from puppeteer; const browser await puppeteer.launch(); // 在默认上下文中为指定 origin 授予 geolocation 权限 const context browser.defaultBrowserContext(); await context.overridePermissions(https://html5demos.com, [geolocation]); const page await context.newPage(); await page.goto(https://html5demos.com); // 页面内 navigator.geolocation.getCurrentPosition 将直接通过授权 await browser.close();由于权限是绑定到浏览器上下文 origin的你也可以在 BrowserContext.newPage() 创建的独立上下文中调用实现按隔离环境授予不同权限。Permission 枚举完整清单overridePermissions()的第二个参数是Permission[]。官方文档链接的Permission类型定义了以下全部取值见 Permission 类型文档及源码 Browser.ts权限值典型用途accelerometer加速度传感器ambient-light-sensor环境光传感器background-sync后台同步camera摄像头视频采集clipboard-read读取剪贴板clipboard-sanitized-write净化写入剪贴板clipboard-write写入剪贴板geolocation地理位置gyroscope陀螺仪idle-detection空闲检测keyboard-lock键盘锁定VR 输入模式magnetometer磁力计microphone麦克风音频采集midiWeb MIDI 设备访问midi-sysexWeb MIDI 系统实时消息Chrome 特有notifications通知payment-handler支付处理器Payment Request APIpersistent-storage持久化存储pointer-lock指针锁定Pointer Lock API传入清单之外的字符串会触发错误而不是被静默忽略下一节的源码与测试都会印证这一点。CDP 通道实现一次Browser.grantPermissions调用在 Chrome DevTools ProtocolCDP通道下该方法的具体实现位于CdpBrowserContextcdp/BrowserContext.tsoverride async overridePermissions( origin: string, permissions: Permission[], ): Promisevoid { const protocolPermissions permissions.map(permission { const protocolPermission WEB_PERMISSION_TO_PROTOCOL_PERMISSION.get(permission); if (!protocolPermission) { throw new Error(Unknown permission: permission); } return protocolPermission; }); await this.#connection.send(Browser.grantPermissions, { origin, browserContextId: this.#id || undefined, permissions: protocolPermissions, }); }从实现可以看出三个要点权限名映射Web 标准的权限名与 CDP 协议层的权限名并不总是一一对应仓库用一张映射表WEB_PERMISSION_TO_PROTOCOL_PERMISSION完成转换定义于 Browser.ts。完整映射关系如下PuppeteerPermissionCDPBrowser.PermissionTypeaccelerometersensorsambient-light-sensorsensorsbackground-syncbackgroundSynccameravideoCaptureclipboard-readclipboardReadWriteclipboard-sanitized-writeclipboardSanitizedWriteclipboard-writeclipboardReadWritegeolocationgeolocationgyroscopesensorsidle-detectionidleDetectionkeyboard-lockkeyboardLockmagnetometersensorsmicrophoneaudioCapturemidimidinotificationsnotificationspayment-handlerpaymentHandlerpersistent-storagedurableStoragepointer-lockpointerLockmidi-sysexmidiSysex注意映射并非单射accelerometer、ambient-light-sensor、gyroscope、magnetometer四个传感器权限在 CDP 层都收敛为同一个sensorsclipboard-read与clipboard-write都映射到clipboardReadWrite。这也解释了为什么 CDP 层无法精确区分只读剪贴板和读写剪贴板。未知权限直接抛错如果传入的值不在映射表中例如测试里故意传入的foo实现会抛出Error(Unknown permission: name)不会静默跳过。上下文作用域请求携带browserContextId: this.#id || undefined。默认上下文的#id为undefined即省略browserContextId字段非默认上下文如browser.createBrowserContext()创建的隔离上下文则显式带上 context id保证权限只授予该上下文内的 origin。另外仓库中还有两处 JSDoc 会把用户引导到这个方法Page.ts 的注释提示需要授予地理位置等权限时应考虑使用BrowserContext.overridePermissionsInput.ts 的示例中也出现了.overridePermissions(your origin, [...])的用法可见它在地理位置、剪贴板等依赖权限的 API 中是配套的基础设施。BiDi 通道实现显式拒绝所有未列出的权限在 WebDriver BiDi 通道下BidiBrowserContext的实现位于 bidi/BrowserContext.ts行为与 CDP 有微妙差异override async overridePermissions( origin: string, permissions: Permission[], ): Promisevoid { const permissionsSet new Set( permissions.map(permission { const protocolPermission WEB_PERMISSION_TO_PROTOCOL_PERMISSION.get(permission); if (!protocolPermission) { throw new Error(Unknown permission: permission); } return permission; }), ); await Promise.all( Array.from(WEB_PERMISSION_TO_PROTOCOL_PERMISSION.keys()).map( permission { const result this.userContext.setPermissions( origin, { name: permission, }, permissionsSet.has(permission) ? Bidi.Permissions.PermissionState.Granted : Bidi.Permissions.PermissionState.Denied, ); this.#overrides.push({origin, permission}); // TODO: some permissions are outdated and setting them to denied does // not work. if (!permissionsSet.has(permission)) { return result.catch(error { this.#logger?.(DEBUG_PREFIXES.error)?.(error); }); } return result; }, ), ); }与 CDP 的一次批量授予不同BiDi 实现遍历映射表中的全部权限对每个权限单独调用userContext.setPermissions()列表内的置为Granted列表外的置为Denied。这正是文档中未列出的权限自动拒绝这一语义在 BiDi 侧的显式落地。还有两点值得注意每次设置的组合会被推入this.#overrides用于后续的权限清理逻辑源码中的 TODO 注释承认部分过时权限设置为 denied 并不生效因此对拒绝操作的失败只记录日志而不抛出保证一次调用不会因为某个边缘权限而整体失败而被授予的权限若失败则会正常向上抛出。权限作用域、清理与测试验证与上下文隔离的关系权限授予绑定在浏览器上下文 origin上天然随上下文的隔离边界生效。配套方法 BrowserContext.clearPermissionOverrides() 可以清空该上下文的所有权限覆盖其在 CDP 通道下对应Browser.resetPermissions调用见 cdp/BrowserContext.ts同样会按browserContextId限定作用域。官方文档给出的授予—使用—清理完整循环示例const context browser.defaultBrowserContext(); context.overridePermissions(https://example.com, [clipboard-read]); // do stuff .. context.clearPermissionOverrides();测试套件覆盖的行为仓库测试test/src/browsercontext.test.ts中有一个专门的describe(BrowserContext.overridePermissions, ...)套件见 browsercontext.test.ts覆盖了以下关键行为可作为该 API 行为的可靠证据空数组等于全部拒绝await context.overridePermissions(server.EMPTY_PAGE, [])后验证权限被拒绝未知权限名被拒绝调用overridePermissions(server.EMPTY_PAGE, [foo])会因映射表查不到foo而抛出Unknown permission错误授予生效验证授予[geolocation]后通过页面内的地理位置 API 验证授权实际生效上下文间隔离测试中同时操作了context与otherContext分别授予不同权限并验证互不影响——这正是browserContextId参数在协议层发挥的作用。此外page.test.ts 与 idle_override.test.ts 也在使用该方法为测试页面授予geolocation/ 空闲检测权限配合 Page.setGeolocation() 等设备模拟能力工作。迁移指南从 overridePermissions 到 setPermission由于overridePermissions()已弃用新项目建议使用 BrowserContext.setPermission())。两者差异对比维度overridePermissions(origin, Permission[])已弃用setPermission(origin, ...items)推荐权限表达简单的字符串枚举PermissionPermissionDescriptor对象 PermissionState状态状态粒度只有授予一种效果其余隐式拒绝每个权限可显式设置granted/denied/promptorigin 通配仅接受具体 origin 字符串接受string \| *CDP 通道下*会被转换为对所有 origin 生效源码中origin * ? undefined : origin描述符扩展字段无支持userVisibleOnly、sysex、allowWithoutSanitization、panTiltZoom等 CDP 协议字段见 cdp/BrowserContext.tsBiDi 限制可用拒绝操作失败会被容忍BiDi 通道下origin *以及allowWithoutSanitization、panTiltZoom、userVisibleOnly会抛出UnsupportedOperation见 bidi/BrowserContext.ts典型迁移对照// 旧批量授予已弃用 await context.overridePermissions(https://html5demos.com, [geolocation]); // 新显式设置单个权限状态 await context.setPermission(https://html5demos.com, { permission: {name: geolocation}, state: granted, }); // 新同时控制多个权限且可以显式拒绝或保持询问 await context.setPermission( https://html5demos.com, {permission: {name: camera}, state: granted}, {permission: {name: microphone}, state: denied}, );选择建议如果只是给这个 origin 开白一批权限迁移成本最低的方式就是把原来的Permission[]逐项转换为setPermission的{permission: {name}, state: granted}参数如果需要区分 granted/denied/prompt 三态、给全部 origin 授权或使用传感器类权限的扩展描述符则应当使用新 API。小结BrowserContext.overridePermissions(origin, permissions)按上下文 origin批量授予权限未列出的权限自动拒绝签名、参数与示例见 官方 API 文档。CDP 实现通过WEB_PERMISSION_TO_PROTOCOL_PERMISSION映射表转换权限名后发送Browser.grantPermissions未知权限直接抛错BiDi 实现则遍历全部已知权限逐项 Granted/Denied并对部分过时权限的拒绝失败做了容忍。该 API 及其Permission类型均已标注弃用官方替代方案是 BrowserContext.setPermission()它提供三态权限控制、*origin 通配限 CDP与权限描述符扩展字段。相关文档BrowserContext 类BrowserContext.setPermission()BrowserContext.clearPermissionOverrides()Permission 类型Browser.defaultBrowserContext()【免费下载链接】puppeteerJavaScript API for Chrome and Firefox项目地址: https://gitcode.com/GitHub_Trending/puppeteer1/puppeteer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表