94 lines
6.5 KiB
JavaScript
94 lines
6.5 KiB
JavaScript
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);
|
|
});
|