import test from "node:test"; import assert from "node:assert/strict"; import { readSession, SESSION_PERMISSION } from "../extension/session.js"; const sampleCookie = value => ({ name: "SAPISID", value, domain: ".youtube.com", path: "/", secure: true, httpOnly: true, hostOnly: false }); test("session access needs both opt-in and permission and does not return secrets to the UI", async () => { let enabled = false, permission = false, reads = 0; globalThis.chrome = { storage: { local: { get: async () => ({ youtubeSession: enabled }) } }, permissions: { contains: async () => permission }, cookies: { getAllCookieStores: async () => [{ id: "current-profile", tabIds: [42] }], getAll: async options => { reads++; assert.equal(options.domain, "youtube.com"); assert.equal(options.storeId, "current-profile"); return [sampleCookie("synthetic-session"), { ...sampleCookie("other"), domain: ".google.com" }, { ...sampleCookie("evil"), domain: "youtube.com.evil.test" }, { ...sampleCookie("expired"), expirationDate: 1 }, { ...sampleCookie("partitioned"), partitionKey: { topLevelSite: "https://another.test" } }]; }, }, }; assert.equal((await readSession(42)).status, "disabled"); assert.equal(reads, 0); enabled = true; assert.equal((await readSession(42)).status, "permission_required"); assert.equal(reads, 0); permission = true; const status = await readSession(42); assert.equal(status.status, "connected"); assert.ok(!JSON.stringify(status).includes("synthetic-session")); const authenticated = await readSession(42, true); assert.equal(authenticated.cookies.length, 1); assert.equal(authenticated.cookies[0].value, "synthetic-session"); await assert.rejects(readSession(999, true), /профиль вкладки/); }); test("background passes fresh YouTube cookies to both worker actions and never persists them", async () => { const storage = {}, requests = [], listeners = {}, pendingUi = new Map(); let permission = false, cookieValue = "synthetic-original", cookieReads = 0, nativeListener; const noEvent = { addListener() {} }; const native = { onMessage: { addListener(listener) { nativeListener = listener; } }, onDisconnect: noEvent, disconnect() {}, postMessage(message) { requests.push(message); const result = message.action === "hello" ? { version: "1.3.2", ready: true, supportsBrowserCookies: true } : message.action === "ping" ? { alive: true } : message.action === "download" ? { jobId: "auth-test-job" } : { title: "Synthetic video", videos: [], audios: [] }; queueMicrotask(() => nativeListener({ id: message.id, ok: true, result })); }, }; globalThis.chrome = { runtime: { id: "test-id", getManifest: () => ({ version: "1.4.5" }), getURL: name => `chrome-extension://test-id/${name}`, connectNative: () => native, onConnect: { addListener(listener) { listeners.connect = listener; } }, onMessage: noEvent }, permissions: { contains: async () => permission, remove: async input => { assert.deepEqual(input, SESSION_PERMISSION); permission = false; return true; } }, cookies: { getAllCookieStores: async () => [{ id: "0", tabIds: [42] }], getAll: async () => { cookieReads++; return [sampleCookie(cookieValue)]; } }, storage: { local: { get: async key => Object.fromEntries((Array.isArray(key) ? key : [key]).map(name => [name, storage[name]])), set: async values => Object.assign(storage, structuredClone(values)) } }, notifications: { clear: async () => {}, create: async () => {}, onButtonClicked: noEvent }, tabs: { sendMessage: async () => {} }, action: { onClicked: noEvent, setBadgeText() {}, setBadgeBackgroundColor() {} }, }; await import("../extension/background.js?session-test"); let uiListener; listeners.connect({ name: "ytdl-ui", sender: { id: "test-id", url: "chrome-extension://test-id/downloader.html" }, onDisconnect: noEvent, onMessage: { addListener(listener) { uiListener = listener; } }, postMessage(message) { if (message.id) { const done = pendingUi.get(message.id); pendingUi.delete(message.id); done(message); } } }); const call = (action, payload = {}) => new Promise(resolve => { const id = crypto.randomUUID(); pendingUi.set(id, resolve); uiListener({ id, action, payload }); }); assert.equal((await call("hello")).ok, true); assert.equal((await call("session_enable", { enabled: true, tabId: 42 })).ok, false); const url = "https://www.youtube.com/watch?v=jNQXAC9IVRw"; await call("inspect", { url, tabId: 42, browserCookies: [sampleCookie("caller-injected")] }); assert.equal(cookieReads, 0); assert.ok(!requests.at(-1).payload.browserCookies); permission = true; const enabled = await call("session_enable", { enabled: true, tabId: 42 }); assert.equal(enabled.result.status, "connected"); assert.ok(!JSON.stringify(enabled).includes(cookieValue)); await call("inspect", { url, tabId: 42 }); assert.equal(requests.at(-1).payload.browserCookies[0].value, cookieValue); const inspectionRequests = requests.filter(request => request.action === "inspect").length; await call("inspect", { url, tabId: 42 }); assert.equal(requests.filter(request => request.action === "inspect").length, inspectionRequests, "Reuse a recently inspected video's quality without another YouTube request"); await call("inspect", { url, tabId: 42, refresh: true }); assert.equal(requests.filter(request => request.action === "inspect").length, inspectionRequests + 1, "Explicit refresh bypasses the summary cache"); cookieValue = "synthetic-rotated"; await call("download", { url, tabId: 42, title: "Test", folder: "D:/Videos" }); assert.equal(requests.at(-1).payload.browserCookies[0].value, cookieValue); nativeListener({ event: "job", job: { id: "auth-test-job", status: "complete", stage: "complete", result: { title: "Test", filename: "test.mp4", path: "D:/Videos/test.mp4" } } }); await new Promise(resolve => setTimeout(resolve, 20)); assert.ok(!JSON.stringify(storage).includes("synthetic-")); assert.ok(!JSON.stringify(storage).includes("browserCookies")); await call("session_enable", { enabled: false, tabId: 42 }); const readsBefore = cookieReads; await call("inspect", { url, tabId: 42 }); assert.equal(cookieReads, readsBefore); assert.ok(!requests.at(-1).payload.browserCookies); // An expired/removed permission must still allow ordinary public downloads. storage.youtubeSession = true; assert.equal((await call("inspect", { url, tabId: 42, refresh: true })).ok, true); assert.ok(!requests.at(-1).payload.browserCookies); });