From de5bc7c5c5a057500bd65e7ed7b45787efa58cc4 Mon Sep 17 00:00:00 2001 From: Abe Jellinek <1770299+AbeJellinek@users.noreply.github.com> Date: Wed, 22 Apr 2026 10:33:45 -0400 Subject: [PATCH] cookieContextId -> userContextId --- .../zoteroWebTranslationEnvironment.mjs | 2 +- chrome/content/zotero/HiddenBrowser.mjs | 7 ++- .../import/mendeley/mendeleyAPIUtils.js | 2 +- .../content/zotero/standalone/basicViewer.js | 6 +-- chrome/content/zotero/xpcom/browserRequest.js | 44 +++++++++---------- chrome/content/zotero/xpcom/http.js | 13 +++--- chrome/content/zotero/xpcom/zotero.js | 4 +- test/tests/httpTest.js | 14 +++--- 8 files changed, 45 insertions(+), 47 deletions(-) diff --git a/chrome/content/scaffold/zoteroWebTranslationEnvironment.mjs b/chrome/content/scaffold/zoteroWebTranslationEnvironment.mjs index eed325ea2b..f6ad3fa643 100644 --- a/chrome/content/scaffold/zoteroWebTranslationEnvironment.mjs +++ b/chrome/content/scaffold/zoteroWebTranslationEnvironment.mjs @@ -11,7 +11,7 @@ export class ZoteroWebTranslationEnvironment extends AbstractWebTranslationEnvir const { HiddenBrowser } = ChromeUtils.importESModule('chrome://zotero/content/HiddenBrowser.mjs'); let browser = new HiddenBrowser({ docShell: { allowMetaRedirects: true }, - cookieContextId: tester.cookieSandbox, + userContextId: tester.cookieSandbox, }); await browser.load(url, { requireSuccessfulStatus: true }); diff --git a/chrome/content/zotero/HiddenBrowser.mjs b/chrome/content/zotero/HiddenBrowser.mjs index ac97707366..814d565cd9 100644 --- a/chrome/content/zotero/HiddenBrowser.mjs +++ b/chrome/content/zotero/HiddenBrowser.mjs @@ -48,8 +48,7 @@ export class HiddenBrowser { * @param {Boolean} [options.blockRemoteResources] Block all remote (non-file:) resources * @param {Boolean} [options.useHiddenFrame=true] Use a hidden frame to create the browser. * Must be set to false if intending to call print(). - * @param {Number} [options.cookieContextId] - userContextId from Zotero.HTTP.newCookieContext() - * for cookie isolation + * @param {Number} [options.userContextId] - From Zotero.HTTP.newCookieContext() for cookie isolation * @param {String} [options.customUserAgent] - Override User-Agent for all requests * from this browser's browsing context */ @@ -83,8 +82,8 @@ export class HiddenBrowser { browser.setAttribute("remote", "true"); browser.setAttribute('maychangeremoteness', 'true'); browser.setAttribute("disableglobalhistory", "true"); - if (options.cookieContextId) { - browser.setAttribute("usercontextid", String(options.cookieContextId)); + if (options.userContextId) { + browser.setAttribute("usercontextid", String(options.userContextId)); } browser.style.display = "none"; doc.documentElement.appendChild(browser); diff --git a/chrome/content/zotero/import/mendeley/mendeleyAPIUtils.js b/chrome/content/zotero/import/mendeley/mendeleyAPIUtils.js index ea683624dd..6e8ebd0a61 100644 --- a/chrome/content/zotero/import/mendeley/mendeleyAPIUtils.js +++ b/chrome/content/zotero/import/mendeley/mendeleyAPIUtils.js @@ -160,7 +160,7 @@ const obtainReferenceManagerToken = async (login, password) => { let { HiddenBrowser } = ChromeUtils.importESModule("chrome://zotero/content/HiddenBrowser.mjs"); let cookieContext = Zotero.HTTP.newCookieContext(); let browser = new HiddenBrowser({ - cookieContextId: cookieContext.id, + userContextId: cookieContext.id, docShell: { allowMetaRedirects: true, allowAuth: true, diff --git a/chrome/content/zotero/standalone/basicViewer.js b/chrome/content/zotero/standalone/basicViewer.js index 314915dfda..4544b60c36 100644 --- a/chrome/content/zotero/standalone/basicViewer.js +++ b/chrome/content/zotero/standalone/basicViewer.js @@ -35,13 +35,13 @@ window.addEventListener("load", /*async */function () { let { uri, options } = window.arguments[0].wrappedJSObject; browser = document.querySelector('browser'); - if (options?.cookieContextId) { + if (options?.userContextId) { // Set usercontextid on new so it takes effect let newBrowser = document.createXULElement('browser'); for (let { name, value } of browser.attributes) { newBrowser.setAttribute(name, value); } - newBrowser.setAttribute('usercontextid', String(options.cookieContextId)); + newBrowser.setAttribute('usercontextid', String(options.userContextId)); browser.replaceWith(newBrowser); browser = newBrowser; } @@ -56,7 +56,7 @@ window.addEventListener("load", /*async */function () { } window.viewerOriginalURI = uri; - window.viewerCookieContextId = options?.cookieContextId; + window.viewerUserContextId = options?.userContextId; loadURI(Services.io.newURI(uri), options); }, false); diff --git a/chrome/content/zotero/xpcom/browserRequest.js b/chrome/content/zotero/xpcom/browserRequest.js index d25e7e462c..be8f726902 100644 --- a/chrome/content/zotero/xpcom/browserRequest.js +++ b/chrome/content/zotero/xpcom/browserRequest.js @@ -78,7 +78,7 @@ Zotero.BrowserRequest = { * client-side redirects or cookie-setting challenges to settle. * * Cookies acquired by the browser remain in the shared jar keyed on - * cookieContextId; a subsequent Zotero.HTTP.request using the same ID will + * userContextId; a subsequent Zotero.HTTP.request using the same ID will * see them. * * On timeout, if the page contains the entry's captchaLocator and @@ -86,7 +86,7 @@ Zotero.BrowserRequest = { * * @param {string} url * @param {object} [options] - * @param {number} [options.cookieContextId] + * @param {number} [options.userContextId] * @param {object} [options.entry] - registry entry controlling escalation * @param {boolean} [options.allowViewer=false] * @returns {Promise} @@ -94,13 +94,13 @@ Zotero.BrowserRequest = { async clearChallenge(url, options = {}) { Zotero.debug(`BrowserRequest: Clearing challenge at ${url}`); - let { cookieContextId, entry, allowViewer = false } = options; + let { userContextId, entry, allowViewer = false } = options; let successCookie = entry?.successCookie; // Capture the cookie's current value (if any) before the attempt so // we can tell a freshly-issued cookie from a stale one left over from // a previous session. let initialCookieValue = successCookie - ? this._readCookieValue({ ...successCookie, cookieContextId }) + ? this._readCookieValue({ ...successCookie, userContextId }) : null; // Cloudflare Turnstile rejects the "Zotero/[version]" suffix. // A plain Firefox UA on just this browsing context lets the widget run. @@ -111,11 +111,11 @@ Zotero.BrowserRequest = { // before the page fully settles (or redirects somewhere else). let hiddenBrowser; try { - hiddenBrowser = new HiddenBrowser({ cookieContextId, customUserAgent }); + hiddenBrowser = new HiddenBrowser({ userContextId, customUserAgent }); await hiddenBrowser._createdPromise; await this._loadAndSettle(hiddenBrowser, url, { successCookie, - cookieContextId + userContextId }); } catch (e) { @@ -129,7 +129,7 @@ Zotero.BrowserRequest = { } if (successCookie) { - let currentValue = this._readCookieValue({ ...successCookie, cookieContextId }); + let currentValue = this._readCookieValue({ ...successCookie, userContextId }); if (currentValue && currentValue !== initialCookieValue) { return; } @@ -144,14 +144,14 @@ Zotero.BrowserRequest = { Zotero.debug(`BrowserRequest: Escalating to viewer for ${url}`); if (successCookie) { await this._loadAndWaitForCookieInViewer(url, { - cookieContextId, + userContextId, customUserAgent, successCookie }); return; } await this.clearChallengeInViewer(url, { - cookieContextId, + userContextId, captchaLocator: entry.captchaLocator }); }, @@ -165,7 +165,7 @@ Zotero.BrowserRequest = { async _loadAndWaitForCookieInViewer(url, options) { Zotero.debug(`BrowserRequest: Awaiting user challenge clearance (cookie ${options.successCookie.name}) at ${url}`); const timeout = Zotero.Prefs.get('browserRequest.timeout'); - const { successCookie, cookieContextId, customUserAgent } = options; + const { successCookie, userContextId, customUserAgent } = options; let win, wmListener, pollInterval; let done = false; @@ -178,14 +178,14 @@ Zotero.BrowserRequest = { }); Services.wm.addListener(wmListener); await new Promise((resolve) => { - win = Zotero.openInViewer(url, { cookieContextId, customUserAgent }); + win = Zotero.openInViewer(url, { userContextId, customUserAgent }); win.addEventListener('load', resolve); }); Zotero.Utilities.Internal.activate(win); pollInterval = this._pollForCookie({ successCookie, - cookieContextId, + userContextId, onFound: () => { done = true; cookieDeferred.resolve(); @@ -213,11 +213,11 @@ Zotero.BrowserRequest = { * Read the value of a named cookie on a given host under an optional * userContextId. Returns null if the cookie is absent. */ - _readCookieValue({ host, name, cookieContextId }) { + _readCookieValue({ host, name, userContextId }) { try { let cookies = Services.cookies.getCookiesFromHost( host, - cookieContextId ? { userContextId: cookieContextId } : {} + userContextId ? { userContextId } : {} ); for (let cookie of cookies) { if (cookie.name === name) { @@ -262,16 +262,16 @@ Zotero.BrowserRequest = { * * @param {object} opts * @param {{host: string, name: string}} opts.successCookie - * @param {number} [opts.cookieContextId] + * @param {number} [opts.userContextId] * @param {Function} opts.onFound * @param {number} [opts.intervalMs=250] * @returns {number} interval handle */ - _pollForCookie({ successCookie, cookieContextId, onFound, intervalMs = 250 }) { + _pollForCookie({ successCookie, userContextId, onFound, intervalMs = 250 }) { let { host, name } = successCookie; - let initialValue = this._readCookieValue({ host, name, cookieContextId }); + let initialValue = this._readCookieValue({ host, name, userContextId }); return setInterval(() => { - let currentValue = this._readCookieValue({ host, name, cookieContextId }); + let currentValue = this._readCookieValue({ host, name, userContextId }); if (currentValue && currentValue !== initialValue) { onFound(); } @@ -285,7 +285,7 @@ Zotero.BrowserRequest = { * * @param {string} url * @param {object} options - * @param {number} [options.cookieContextId] + * @param {number} [options.userContextId] * @param {string} options.captchaLocator * @returns {Promise} */ @@ -306,7 +306,7 @@ Zotero.BrowserRequest = { Services.wm.addListener(wmListener); await new Promise((resolve) => { win = Zotero.openInViewer(url, { - cookieContextId: options.cookieContextId + userContextId: options.userContextId }); win.addEventListener('load', resolve); }); @@ -407,7 +407,7 @@ Zotero.BrowserRequest = { * @param {object} [opts] * @param {(blob: Blob) => void} [opts.onPDF] * @param {{ host: string, name: string }} [opts.successCookie] - * @param {number} [opts.cookieContextId] + * @param {number} [opts.userContextId] * @returns {Promise} */ async _loadAndSettle(hiddenBrowser, url, opts = {}) { @@ -455,7 +455,7 @@ Zotero.BrowserRequest = { if (opts.successCookie) { cookiePollInterval = this._pollForCookie({ successCookie: opts.successCookie, - cookieContextId: opts.cookieContextId, + userContextId: opts.userContextId, onFound: () => { Zotero.debug(`BrowserRequest: successCookie ${opts.successCookie.name} appeared`); cookieDeferred.resolve(); diff --git a/chrome/content/zotero/xpcom/http.js b/chrome/content/zotero/xpcom/http.js index a99eba3d2c..03a8ba5f7b 100644 --- a/chrome/content/zotero/xpcom/http.js +++ b/chrome/content/zotero/xpcom/http.js @@ -116,7 +116,7 @@ Zotero.HTTP = new function () { // Base for generated userContextIds -- high to avoid collision with Firefox containers - var _nextCookieContextId = 100000 + Math.floor(Math.random() * 100000); + var _nextUserContextId = 100000 + Math.floor(Math.random() * 100000); /** * Create an isolated cookie context backed by a unique Mozilla userContextId. @@ -128,7 +128,7 @@ Zotero.HTTP = new function () { * @return {{ id: number, getCookies: (host: string) => nsICookie[], dispose: () => void }} */ this.newCookieContext = function () { - let id = _nextCookieContextId++; + let id = _nextUserContextId++; return { id, /** @@ -174,8 +174,7 @@ Zotero.HTTP = new function () { * @param {Number[]|false} [options.successCodes] - HTTP status codes that are considered * successful, or FALSE to allow all * @param {Boolean} [options.anon] - Make the request anonymously, without global cookies - * @param {Number} [options.cookieContextId] - userContextId from newCookieContext() for - * cookie isolation + * @param {Number} [options.userContextId] - From newCookieContext() for cookie isolation * @param {Number} [options.timeout = 30000] - Request timeout specified in milliseconds, or 0 * for no timeout * @param {Number[]} [options.errorDelayIntervals] - Array of milliseconds to wait before @@ -300,7 +299,7 @@ Zotero.HTTP = new function () { // Translation framework uses cookieSandbox to hold userContextId number if (typeof options.cookieSandbox === 'number') { - options.cookieContextId = options.cookieSandbox; + options.userContextId = options.cookieSandbox; delete options.cookieSandbox; } @@ -335,8 +334,8 @@ Zotero.HTTP = new function () { xmlhttp.open(method, url, true, options.username, options.password); // Isolate cookies into a separate jar via userContextId - if (options.cookieContextId && xmlhttp.setOriginAttributes) { - xmlhttp.setOriginAttributes({ userContextId: options.cookieContextId }); + if (options.userContextId && xmlhttp.setOriginAttributes) { + xmlhttp.setOriginAttributes({ userContextId: options.userContextId }); } // Pass the request to a callback diff --git a/chrome/content/zotero/xpcom/zotero.js b/chrome/content/zotero/xpcom/zotero.js index d463d782ff..bfa53f5de4 100644 --- a/chrome/content/zotero/xpcom/zotero.js +++ b/chrome/content/zotero/xpcom/zotero.js @@ -1238,7 +1238,7 @@ const { CommandLineOptions } = ChromeUtils.importESModule("chrome://zotero/conte * @param {Object} [options] * @param {Function} [options.onLoad] - Function to run once URI is loaded; passed the loaded document * @param {Boolean} [options.allowJavaScript] - Set to false to disable JavaScript - * @param {Number} [options.cookieContextId] - userContextId to isolate the viewer's cookies + * @param {Number} [options.userContextId] - To isolate the viewer's cookies * into the same jar as a Zotero.HTTP.request or HiddenBrowser using the same ID * @param {String} [options.customUserAgent] - Override the User-Agent for all requests * from this viewer's browsing context @@ -1251,7 +1251,7 @@ const { CommandLineOptions } = ChromeUtils.importESModule("chrome://zotero/conte var viewerWins = Services.wm.getEnumerator("zotero:basicViewer"); for (let existingWin of viewerWins) { - if (existingWin.viewerOriginalURI === uri && existingWin.viewerCookieContextId === options?.cookieContextId) { + if (existingWin.viewerOriginalURI === uri && existingWin.viewerUserContextId === options?.userContextId) { existingWin.focus(); return existingWin; } diff --git a/test/tests/httpTest.js b/test/tests/httpTest.js index b2251526f0..f0e3c63421 100644 --- a/test/tests/httpTest.js +++ b/test/tests/httpTest.js @@ -426,7 +426,7 @@ describe("Zotero.HTTP", function () { // Request in the isolated context should not see the default cookie let req = await Zotero.HTTP.request('GET', cookieURL, { - cookieContextId: ctx.id, + userContextId: ctx.id, successCodes: false }); assert.equal(req.status, 403); @@ -441,14 +441,14 @@ describe("Zotero.HTTP", function () { try { // First request in context -- gets 403, sets cookie let req = await Zotero.HTTP.request('GET', cookieURL, { - cookieContextId: ctx.id, + userContextId: ctx.id, successCodes: false }); assert.equal(req.status, 403); // Second request in same context -- should have the cookie req = await Zotero.HTTP.request('GET', cookieURL, { - cookieContextId: ctx.id, + userContextId: ctx.id, successCodes: false }); assert.equal(req.status, 200); @@ -464,13 +464,13 @@ describe("Zotero.HTTP", function () { try { // Set cookie in ctx1 await Zotero.HTTP.request('GET', cookieURL, { - cookieContextId: ctx1.id, + userContextId: ctx1.id, successCodes: false }); // ctx2 should not see ctx1's cookie let req = await Zotero.HTTP.request('GET', cookieURL, { - cookieContextId: ctx2.id, + userContextId: ctx2.id, successCodes: false }); assert.equal(req.status, 403); @@ -486,7 +486,7 @@ describe("Zotero.HTTP", function () { // Set cookie in context await Zotero.HTTP.request('GET', cookieURL, { - cookieContextId: ctx.id, + userContextId: ctx.id, successCodes: false }); @@ -499,7 +499,7 @@ describe("Zotero.HTTP", function () { let ctx2 = Zotero.HTTP.newCookieContext(); try { let req = await Zotero.HTTP.request('GET', cookieURL, { - cookieContextId: ctx.id, + userContextId: ctx.id, successCodes: false }); assert.equal(req.status, 403);