
Chrome 109 老兵救火实录Zotero Connector 的 Cookies 分区兼容改造3 条退路全给齐【免费下载链接】zotero-connectorsChrome, Firefox, Edge, and Safari extensions for Zotero项目地址: https://gitcode.com/gh_mirrors/zo/zotero-connectorsZotero Connector 是 Zotero 官方出品的浏览器扩展它要解决的核心问题很简单让用户在 Chrome、Firefox、Edge 或 Safari 里浏览文献页面时点一下就能把网页内容、PDF 附件连同权限校验信息一起抓回 Zotero 桌面端。可当这套流程跑在 Windows 7 上、浏览器被死死卡在 Chrome 109 时附件下载会毫无征兆地失败——不是网络断了而是一条名叫partitionKey的 Cookie 参数在暗中作梗。这篇文章复盘了我们从能跑就行到分区兼容的完整迭代过程也把试过的三条退路一次性交代清楚。一、报错现场Chrome 109 上的静默罢工用户群里最早炸锅的是一条很具体的反馈Windows 7 笔记本 Chrome 109Win7/8 能装的最后一个版本点开一篇期刊文章正文能正常保存但点保存PDF 附件时扩展后台直接抛Uncaught TypeError: Cannot read properties of undefined (reading partitionKey)更迷惑的是同样的操作在 Chrome 120、Edge、Firefox 上全都正常。也就是说问题跟网络、账号、Zotero 桌面端都无关纯粹是浏览器版本断层。顺带一提Firefox 用户当时还多一层困惑cookies.getAll在某些版本里要求传firstPartyDomain: null才能拿到非分区 cookie这属于另一条战线后面避坑清单里会再提。二、先从能跑开始第一版代码是怎么埋雷的回头翻代码第一版_fetchAttachment写得很天真直接往cookies.getAll()里塞分区参数cookies await Zotero.Connector_Browser.getAllCookies({ url: attachment.url, partitionKey: {}, // 从分区和非分区存储里都取 cookie });partitionKey: {}的意思是把默认分区和非分区存储里的 cookie 都给我。Chrome 1182023 年 10 月发布开始支持这个字段Windows 7/8 用户永远停在 109等于永远摸不到它。当时我们的心态是新浏览器都支持老版本随缘。结果老版本用户不是功能降级而是整条链路直接崩——Chrome 在解析不认识的参数时返回的对象里没有partitionKey下游代码一读就undefined报错。这里有个坑API 不认识的参数浏览器未必会报参数非法更多时候是静默忽略或返回畸形结果错误往往发生在更远的地方排查成本反而更高。三、根因一条 cookie 的分区身世要理解为什么项目死磕partitionKey得先知道它从哪来。现代浏览器为了堵住跨站追踪搞出了分区 cookie机制CHIPScookie 不再只按域名存而是按域名 顶层站点双键分区。而 Cloudflare 这类反爬服务会故意在 iframe 里设置cf_clearancecookie让它天然带上分区键。对 Zotero Connector 来说这本来无所谓——但问题在于Chrome 的 Service Worker 发起 fetch 时即使带credentials: include也不会自动带上分区 cookie。于是我们只能手动把分区 cookie 捞出来、拼进请求头。而捞的动作恰好就要用partitionKey参数。这条链路里每一环都是必需的老浏览器一断整条链就瘫了。四、三条退路逐个试从异常兜底到提前体检我们围绕这个问题争论过三轮三条思路各有取舍。退路 Atry-catch 整段兜底最终采用的。先用带partitionKey的参数请求失败就删掉参数重试一次。代码改动最小老浏览器和新浏览器共用一套逻辑零运行时判断。退路 B功能检测提前判断 API 支不支持。比如检查browser.cookies.getAll.length 2带第二个参数说明支持分区。听着更优雅但我们试完就放弃了——Function.length在不同浏览器实现里并不可靠而且万一某天 Chrome 把参数改名叫别的这段检测代码又要跟着失效属于为未来埋雷。退路 C构建期条件编译打包时针对不同目标浏览器裁剪参数。性能最优但代价是要维护多套构建产物而我们同时要发 Chrome、Firefox、Edge、Safari 四家商店构建矩阵会直接爆炸否决。三条路对比一眼收口思路做法代价适用场景try-catch 回退带参数失败 → 去掉参数重试异常路径多一次调用参数是锦上添花丢了也不致命功能检测检测 API 特征再决定传参特征不可靠需长期维护有官方稳定的能力探测入口构建期裁剪每个目标版本单独打包构建矩阵爆炸版本少、分发渠道单一五、最终落地真实改动长什么样src/common/itemSaver_background.js里的_fetchAttachment最终长这样let cookies; try { cookies await Zotero.Connector_Browser.getAllCookies({ url: attachment.url, partitionKey: {}, }, tab?.id); } catch (e) { // Unavailable with Chrome 118 and below. // Last supported version on Win 7/8 is Chrome 109. Zotero.debug(Error getting cookies for ${attachment.url} with partitionKey.); cookies await Zotero.Connector_Browser.getAllCookies({ url: attachment.url, }, tab?.id); } // Chromium and Firefox will send cookies, but Chrome currently // ignores those with partitionKey. cookies cookies.filter(c c.partitionKey); options.headers { Cookie: cookies.map(cookie ${cookie.name}${cookie.value}).join(; ) };为什么这样写说三点回退前先打日志Zotero.debug那句不是废话它让降级发生这件事可观测用户把 debug 日志发回来我们一眼就能确认是老浏览器走了回退分支而不是别的环节出错。filter(c c.partitionKey)是第二个保险Chromium 和 Firefox 会原样返回 cookie但 Chrome 在请求时会忽略带分区键的 cookieChromium 的 bug 追踪列表里挂着一条对应的 issue。过滤不是洁癖是避免拼出看似有 Cookie 头、实际发不出去的假象。Zotero.Connector_Browser.getAllCookies是统一出口它负责在src/browserExt/background.js里做 Safari 特判——Safari 的 cookie store 跟标签页不对应得运行时查getAllCookieStores()再补storeId。分区兼容只是这条链路上的一环外层封装把平台差异全挡住了。另一处src/common/http.js的_augmentCfCookie处理 Cloudflare 的cf_clearance时策略更保守try失败直接return连重试都不做——因为拿不到清障 cookie 顶多是多走一步 bot 绕过逻辑不值得为老浏览器再搭一条异常路径。六、验证与上线真机、构建、加载一条龙改完代码光靠新浏览器自测没用我们按这套流程验证在 Windows 7 虚拟机里装 Chrome 109加载未打包扩展仓库根目录跑./build.sh -d产物在build/browserExt/打开chrome://extensions→ 开发者模式 → 加载已解压的扩展程序选这个目录。打开一个带 PDF 附件的期刊页点保存附件确认后台无TypeError、附件正常入库。打开 Cloudflare 保护的站点确认cf_clearance兜底分支不抛错、页面仍可保存。回到 Chrome 120 回归一遍确认partitionKey: {}分支正常分区 cookie 照常拼进请求头。跑一遍项目自带的测试套件npm test底层是 mocha确保没有连带回归。七、避坑清单与留给你的开放问题✅API 不认识的参数不一定会报错可能静默忽略、可能返回畸形对象所以兼容代码的断言要写在读取返回值这层。✅回退路径要留日志否则降级发生得无声无息线上问题只能靠猜。✅平台差异收口到统一封装getAllCookies一处特判 Safari、一处兼容分区别让平台 if 散落得到处都是。✅别用Function.length做能力探测浏览器实现不一致今天能用明天就塌。⚠️ Firefox 老版本要额外补firstPartyDomain: null分区 cookie 跟 first-party 隔离是两条独立的战线。⚠️ Chrome 目前会忽略请求中带分区键的 cookie过滤逻辑别省。最后留个开放问题partitionKey的引入意味着 Chrome 正在把分区变成默认行为而分区 cookie 的清理、迁移、跨站传递规则还在快速演化。如果你的扩展也依赖 cookies API 做登录态或反爬绕过你会选择 try-catch 回退还是提前押注功能检测欢迎在评论区聊聊你的取舍也建议你顺手打开项目的src/common/itemSaver_background.js看看这段注释里没写出来的第三个坑是什么。【免费下载链接】zotero-connectorsChrome, Firefox, Edge, and Safari extensions for Zotero项目地址: https://gitcode.com/gh_mirrors/zo/zotero-connectors创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考