PT 助手 Plus 跨浏览器兼容实践指南:同一套代码如何在 Chrome、Edge 与 Firefox 上跑通

发布时间:2026/9/20 12:18:39
PT 助手 Plus 跨浏览器兼容实践指南:同一套代码如何在 Chrome、Edge 与 Firefox 上跑通 PT 助手 Plus 跨浏览器兼容实践指南同一套代码如何在 Chrome、Edge 与 Firefox 上跑通【免费下载链接】PT-Plugin-PlusPT 助手 Plus为 Microsoft Edge、Google Chrome、Firefox 浏览器插件Web Extensions主要用于辅助下载 PT 站的种子。项目地址: https://gitcode.com/GitHub_Trending/pt/PT-Plugin-Plus在 Firefox 的 PT 站点页面上右键一个 .torrent 链接选发送到 qBittorrent页面弹出一句Could not establish connection而同一个操作在 Chrome 里正常。PT 助手 PlusPT-Plugin-Plus是一款覆盖 Chrome、Edge、Firefox 的 Web Extensions 插件专门做种子搜索与发送它的跨浏览器兼容不是靠一套 Firefox 专用分支硬撑而是靠 manifest 策略、能力检测和权限动态申请三个层面的取舍。整个插件的消息流向是固定的options 页和内容脚本把请求发给 background由PTPlugin类统一分发核心链路见 src/background/service.ts 和 src/background/controller.ts。一份 manifest 进三个商店public/manifest.json 是唯一的 manifest三个浏览器装的是同一份声明Firefox 的差异被压缩到两个字段里{ manifest_version: 2, minimum_chrome_version: 64.0.3242, optional_permissions: [downloads, cookies], browser_specific_settings: { gecko: { update_url: https://pt-plugins.github.io/PT-Plugin-Plus/update/firefox.json } } }browser_specific_settings是 Firefox 独占字段Chrome 会忽略它所以自动更新地址可以安全地内嵌minimum_chrome_version则把下限锁在 Chrome 64老版本直接拒装省去了对旧 API 行为的兼容代码。另一个关键决策是optional_permissionsdownloads和cookies不放在permissions里因为这两个权限在 Firefox 中会触发强制弹窗安装时就声明会显著提高商店审核风险与用户拒绝率所以推迟到真正用到的时刻再申请——这就是下一节的主题。全库不写 browser.*用能力检测代替浏览器判断一个自然的疑问是Firefox 有browser.*命名空间和 Promise 化的 API为什么代码里几乎只出现chrome.*答案在 src/background/service.ts 的事件初始化里它不判断是不是 Firefox只判断API 在不在private initBrowserEvent() { if (window.chrome undefined) { return; } if (!chrome.runtime) { return; } chrome.runtime.onMessage.addListener( (message, sender, callback) { this.requestMessage(message, sender).then(result { callback callback({ resolve: result }); }); return true; // 不能去掉标记异步响应 } ); }Firefox 同时提供chrome.*兼容层所以只写 chrome.* 处处加空值防护是成本最低的公约数。同一种手法在 src/background/contextMenus.ts 的构造器里更明显chrome chrome.tabs this.initBrowserEvent()菜单的add()和clear()也全部套上chrome chrome.contextMenus 前缀。配合 src/service/public.ts 中用 UAParser 得到的browserName和isExtensionMode标志代码能区分运行在扩展环境与运行在本地调试环境而不依赖 UA 字符串猜浏览器。代价是 TypeScript 类型只能贴types/chromebrowser.*的新能力用不到换来的是业务代码零分叉。downloads 与 cookies 的可选权限怎么动态申请真正调用chrome.downloads备份导出或读cookies之前src/service/public.ts 的PPF.usePermissions走先查再申请的两段式public usePermissions(permissions: string[], needConfirm false, confirmMsg ) { return new Promise((resolve, reject) { this.checkPermissions(permissions) .then(result resolve(result)) .catch(() { let confirmed true; if (needConfirm) { confirmed confirm(confirmMsg); } if (!confirmed) { reject({ success: false }); return; } this.requestPermissions(permissions) .then(result resolve(result)) .catch(error reject(error)); }); }); }这里有两个针对浏览器差异的设计一是needConfirm参数——Chrome 的动态权限申请会自动弹系统确认框而 Firefox 的行为不完全一致所以关键路径上再加一层confirm兜底避免用户面对来源不明的浏览器弹窗二是 src/service/public.ts 的checkOptionalPermission会回读 manifest 的optional_permissions列表确认该权限确实被声明过才继续防止不同浏览器打包产物漂移。被拒时统一 reject{success:false}调用方降级而不是崩溃。站点上下文菜单与那句 Could not establish connection右键菜单是浏览器差异最容易被用户看到的地方。src/background/contextMenus.ts 的策略是菜单跟着标签页走监听chrome.tabs.onActivated和onUpdated标签页一切换就clearSiteMenus()重建再按站点 host 匹配生成按当前站点搜索发送到客户端等项匹配时把site.cdn域名一并纳入解决站点主域与下载域不一致的问题。菜单还通过documentUrlPatterns把自己限定在站点页面内避免在任意网页污染右键菜单。chrome.tabs.sendMessage(tabid, { action: EAction.showMessage, data: {...} }, (result) { if (chrome.runtime.lastError) { let message chrome.runtime.lastError.message || ; if (message.match(/Could not establish connection/)) { APP.showNotifications({ message: this.service.i18n.t(service.contextMenus.pluginStatusIsUnknown) }); } return; } notice result; });这段在sendTorrentToClient里把背景页→内容脚本的消息投递错误翻译成用户能懂的话当页面刚加载、内容脚本尚未注入时这在 Firefox 里比 Chrome 更常见因为其内容脚本注入时序不同lastError会报 Could not establish connection此时插件提示刷新页面再试而不是静默失败。类似的防御还出现在徽标更新上——src/service/public.ts 的updateBadge整段裹在 try/catch 里某个浏览器不支持browserAction的某个方法时只是丢徽标不影响主流程。不依赖浏览器的本地调试模式跨浏览器代码的回归成本高仓库用 debug/ 目录给了个解法yarn dev-s会在 Node 环境里跑一份插件主体App.ts、BuildPlugin.ts对应PTPlugin构造器的localMode参数——为真时跳过initBrowserEvent()消息分发、配置读写等纯逻辑照常可用src/background/service.ts 中大量if (!this.localMode)分支就是为此准备的。业务逻辑与浏览器 API 天然分层调试时不装插件也能跑通数据链路省掉了改一行代码、装三个浏览器的循环。可以搬到自己项目里的做法单一 manifest 浏览器专属字段隔离用browser_specific_settings收拢 Firefox 差异用minimum_chrome_version锁底线避免维护多份 manifest敏感权限进optional_permissions调用前先查再申请并给不同浏览器的弹窗行为加一层confirm兜底能力检测写防护浏览器判断只留一处chrome chrome.xxx 前缀保证缺失 API 时优雅跳过UA 解析仅用于展示与统计不进控制流为浏览器 API 的时序差异准备可理解错误把runtime.lastError里的典型错误如连接未建立映射成带操作建议的提示而不是裸报错。【免费下载链接】PT-Plugin-PlusPT 助手 Plus为 Microsoft Edge、Google Chrome、Firefox 浏览器插件Web Extensions主要用于辅助下载 PT 站的种子。项目地址: https://gitcode.com/GitHub_Trending/pt/PT-Plugin-Plus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考