const HOST_NAME = "com.project_info.bili_auth_ingress"; const SCHEMA = 3; const EXTENSION_BUILD = "project-info-bili-auth-ingress/1.2.25+20260829.generic.v027"; const OWNED_TAB_STORAGE_KEY = "bili_auth_job_owned_tab_v1"; const OWNED_TAB_SCHEMA = 1; const BVID_RE = /^BV1[1-9A-HJ-NP-Za-km-z]{9}$/; const CREATOR_RE = /^[1-9][0-9]{0,19}$/; const HEX32_RE = /^[0-9a-f]{32}$/; const HEX64_RE = /^[0-9a-f]{64}$/; const UPPER_HEX64_RE = /^[0-9A-F]{64}$/; const MESSAGE_ID_RE = /^msg_[0-9]{17}_[0-9a-f]{8}$/; const HANDOFF_ID_RE = /^HANDOFF-[A-Z0-9-]{8,240}$/; const AUDIT_ID_RE = /^DEV-AUDIT-[A-Z0-9-]{8,240}$/; const ERROR_CODE_RE = /^E_[A-Z0-9_]{1,48}$/; const SAFE_PHASES = new Set([ "IDLE", "READY", "CHECKING", "DOWNLOADING", "MERGING", "VALIDATING", "PUBLISHING", "MEDIA_COMPLETE", "POSTPROCESS_PENDING", "POSTPROCESS_FAILED", "COMPLETE", "FAILED", "CANCELED", "RELOAD_REQUIRED" ]); const RESPONSE_KEYS = [ "error_code", "formal_filename", "host_build", "job", "lease_id", "maintenance", "mapping_filename", "phase", "prepare_id", "progress", "schema", "type" ]; const JOB_KEYS = ["bvid", "canonical_url", "creator_uid", "expected_duration_ms", "job_id", "published_at", "title"]; const LINEAGE_KEYS = [ "authorization_handoff_id", "authorization_message_id", "authorization_sha256", "predecessor_job_id", "predecessor_terminal_error_code", "repair_audit_bytes", "repair_audit_id", "repair_audit_sha256", "repair_review_result_message_id", "retry_generation" ]; const PREPARELESS_TERMINAL_DIAGNOSTIC_CONTRACT = new Map([ ["E_DRM", ["PAGE_REJECTED", new Set(["PAGE_DRM_REJECTED"])]], ["E_DURATION", ["PAGE_REJECTED", new Set(["PAGE_DURATION_REJECTED"])]], ["E_MULTI_PART", ["PAGE_REJECTED", new Set(["PAGE_MULTIPART_REJECTED"])]], ["E_OWNER", ["PAGE_REJECTED", new Set(["PAGE_IDENTITY_REJECTED", "PAGE_OWNER_REJECTED"])]], ["E_PAGE_ACCESS_CONTROL", ["PAGE_REJECTED", new Set(["PAGE_ACCESS_REJECTED"])]], ["E_PAGE_DUPLICATE_TAB", ["TAB_IDENTITY", new Set(["TAB_IDENTITY_DRIFT"])]], ["E_PAGE_DIMENSIONS_UNAVAILABLE", ["DIMENSIONS_PENDING", new Set(["VIDEO_DIMENSIONS_PENDING"])]], ["E_PAGE_IDENTITY_UNAVAILABLE", ["IDENTITY_PENDING", new Set([ "PAGE_DOM_IDENTITY_PENDING", "PAGE_NAVIGATION_PENDING", "PAGE_SCRIPTING_PENDING", "PAGE_TAB_ACTIVATION_PENDING", "PAGE_URL_PENDING", "PAGE_VISIBILITY_PENDING", "PAGE_WINDOW_FOCUS_PENDING", "PAGE_WINDOW_MINIMIZED_PENDING", "PAGE_WINDOW_STATE_PENDING" ])]], ["E_PAGE_METADATA_UNAVAILABLE", ["METADATA_NOT_READY", new Set([ "INITIAL_STATE_ASSIGNMENT_ABSENT", "INITIAL_STATE_JSON_INVALID", "INITIAL_STATE_VIDEO_DATA_ABSENT" ])]], ["E_PAGE_OWNER_ANCHOR_UNAVAILABLE", ["OWNER_PENDING", new Set([ "OWNER_ANCHOR_ABSENT", "OWNER_ANCHOR_AMBIGUOUS", "OWNER_ANCHOR_MISMATCH" ])]], ["E_PAGE_PROOF", ["PAGE_REJECTED", new Set([ "PAGE_BVID_REJECTED", "PAGE_IDENTITY_REJECTED", "PAGE_ORIGIN_REJECTED", "PAGE_URL_REJECTED" ])]], ["E_PAGE_SCRIPT_TIMEOUT", ["SCRIPT_TIMEOUT", new Set(["SCRIPT_INVOCATION_FAILED"])]], ["E_PAGE_STABILITY_TIMEOUT", ["READY_UNSTABLE", new Set(["STABLE_SNAPSHOTS_PENDING"])]], ["E_PAGE_TAB_DRIFT", ["TAB_IDENTITY", new Set(["TAB_IDENTITY_DRIFT"])]], ["E_PAGE_VIDEO_ABSENT", ["VIDEO_ABSENT", new Set(["VIDEO_ELEMENT_ABSENT"])]], ]); const PREPARELESS_REJECT_CODES = new Set(PREPARELESS_TERMINAL_DIAGNOSTIC_CONTRACT.keys()); const PAGE_PROOF_DEADLINE_MS = 60000; const PAGE_EXTENSION_ACTIVATION_GRACE_MS = 5000; const PAGE_PROOF_INVOCATION_TIMEOUT_MS = 5000; const PAGE_PROOF_POLL_MS = 500; const PAGE_PROOF_STABLE_SNAPSHOTS = 3; const PAGE_PROOF_KEYS = [ "bvid", "canonical_url", "creator_uid", "eme_present", "job_id", "observed_at_unix_ms", "metadata_source", "observed_duration_ms", "ready_state", "task_nonce", "video_height", "video_width" ]; const PAGE_PENDING_STATES = new Set([ "DIMENSIONS_PENDING", "IDENTITY_PENDING", "METADATA_NOT_READY", "OWNER_PENDING", "VIDEO_ABSENT" ]); const PAGE_DIAGNOSTIC_STATES = new Set([ ...PAGE_PENDING_STATES, "PAGE_REJECTED", "READY_UNSTABLE", "SCRIPT_TIMEOUT", "TAB_IDENTITY" ]); const PAGE_DIAGNOSTIC_REASONS = new Set([ "DEADLINE_EXHAUSTED", "METADATA_FIELDS_PENDING", "OWNER_ANCHOR_ABSENT", "OWNER_ANCHOR_AMBIGUOUS", "OWNER_ANCHOR_MISMATCH", "INITIAL_STATE_ASSIGNMENT_ABSENT", "INITIAL_STATE_JSON_INVALID", "INITIAL_STATE_VIDEO_DATA_ABSENT", "PAGE_ACCESS_REJECTED", "PAGE_BVID_REJECTED", "PAGE_DOM_IDENTITY_PENDING", "PAGE_DRM_REJECTED", "PAGE_DURATION_REJECTED", "PAGE_IDENTITY_REJECTED", "PAGE_MULTIPART_REJECTED", "PAGE_NAVIGATION_PENDING", "PAGE_ORIGIN_REJECTED", "PAGE_OWNER_REJECTED", "PAGE_SCRIPTING_PENDING", "PAGE_TAB_ACTIVATION_PENDING", "PAGE_URL_PENDING", "PAGE_URL_REJECTED", "PAGE_VISIBILITY_PENDING", "PAGE_WINDOW_FOCUS_PENDING", "PAGE_WINDOW_MINIMIZED_PENDING", "PAGE_WINDOW_STATE_PENDING", "SCRIPT_INVOCATION_FAILED", "STABLE_SNAPSHOTS_PENDING", "TAB_IDENTITY_DRIFT", "VIDEO_DIMENSIONS_PENDING", "VIDEO_ELEMENT_ABSENT" ]); const PAGE_METADATA_UNAVAILABLE_REASONS = new Set([ "INITIAL_STATE_ASSIGNMENT_ABSENT", "INITIAL_STATE_JSON_INVALID", "INITIAL_STATE_VIDEO_DATA_ABSENT" ]); const PAGE_PENDING_TERMINAL_CONTRACT = new Map([ ["E_PAGE_DIMENSIONS_UNAVAILABLE", ["DIMENSIONS_PENDING", new Set(["VIDEO_DIMENSIONS_PENDING"])]], ["E_PAGE_IDENTITY_UNAVAILABLE", ["IDENTITY_PENDING", new Set([ "PAGE_DOM_IDENTITY_PENDING", "PAGE_NAVIGATION_PENDING", "PAGE_SCRIPTING_PENDING", "PAGE_TAB_ACTIVATION_PENDING", "PAGE_URL_PENDING", "PAGE_VISIBILITY_PENDING", "PAGE_WINDOW_FOCUS_PENDING", "PAGE_WINDOW_MINIMIZED_PENDING", "PAGE_WINDOW_STATE_PENDING" ])]], ["E_PAGE_METADATA_NOT_READY", ["METADATA_NOT_READY", PAGE_METADATA_UNAVAILABLE_REASONS]], ["E_PAGE_OWNER_ANCHOR_UNAVAILABLE", ["OWNER_PENDING", new Set([ "OWNER_ANCHOR_ABSENT", "OWNER_ANCHOR_AMBIGUOUS", "OWNER_ANCHOR_MISMATCH" ])]], ["E_PAGE_VIDEO_ABSENT", ["VIDEO_ABSENT", new Set(["VIDEO_ELEMENT_ABSENT"])]], ]); const MAX_COOKIE_COUNT = 128; const COOKIE_KEYS = [ "domain", "expiration_unix", "host_only", "http_only", "name", "partition_key", "path", "same_site", "secure", "session", "store_id", "value" ]; const COOKIE_SAME_SITE = new Set(["no_restriction", "lax", "strict", "unspecified"]); const COOKIE_CONTROL_RE = /\p{C}/u; const STORE_ID_RE = /^[0-9]{1,8}$/; const AUTH_COOKIE_NAME = "SESSDATA"; const REQUIRED_AUTH_COOKIE_NAMES = new Set([AUTH_COOKIE_NAME]); const TRANSFER_COOKIE_NAMES = new Set([AUTH_COOKIE_NAME]); const COOKIE_ACCESS_REASONS = new Set([ "COOKIE_API_ERROR", "COOKIE_API_SHAPE", "COOKIE_AUTH_SET_EMPTY", "COOKIE_EQUAL_PRECEDENCE_CONFLICT", "COOKIE_RELEVANCE_AMBIGUOUS", "COOKIE_SELECTED_INVALID", "COOKIE_SELECTION_EXCEPTION", "COOKIE_TRANSFER_INVALID", "COOKIE_TRANSFER_OVERFLOW" ]); let drainLease = false; let lastDrainErrorCode = null; let lastCookieAccessReason = null; let lastTabDriftReason = null; let lastPageReadinessDiagnostic = null; let lastExtensionDiagnostic = null; let lastBrowserLifecycleDiagnostic = null; const BROWSER_LIFECYCLE_DIAGNOSTIC_CONTRACT = new Map([ ["OWNED_TAB_RECORDED", "BROWSER_OWNERSHIP"], ["OWNED_TAB_ADOPTED", "BROWSER_OWNERSHIP"], ["OWNED_TAB_RECORD_INVALID", "BROWSER_OWNERSHIP"], ["OWNED_TAB_STORAGE_FAILED", "BROWSER_OWNERSHIP"], ["OWNED_TAB_CLOSED", "BROWSER_CLEANUP"], ["OWNED_TAB_ALREADY_CLOSED", "BROWSER_CLEANUP"], ["OWNED_TAB_IDENTITY_DRIFT", "BROWSER_CLEANUP"], ["OWNED_TAB_CLOSE_FAILED", "BROWSER_CLEANUP"], ["OWNED_TAB_AUTOPLAY_STOPPED", "BROWSER_CLEANUP"] ]); const EXTENSION_DIAGNOSTIC_CONTRACT = new Map([ ["DOCUMENT_FOCUS_FALSE", "SCRIPTING"], ["DOCUMENT_FOCUS_TRUE", "SCRIPTING"], ["DOCUMENT_FOCUS_UNAVAILABLE", "SCRIPTING"], ["NATIVE_CONNECT_FAILED", "NATIVE_MESSAGING"], ["NATIVE_DISCONNECT_FAILED", "NATIVE_MESSAGING"], ["SCRIPTING_EXECUTE_FAILED", "SCRIPTING"], ["SERVICE_WORKER_ERROR", "SERVICE_WORKER"], ["SERVICE_WORKER_UNHANDLED_REJECTION", "SERVICE_WORKER"], ["TABS_CREATE_FAILED", "TABS"], ["TABS_GET_FAILED", "TABS"], ["TABS_QUERY_FAILED", "TABS"], ["TABS_UPDATE_FAILED", "TABS"], ["WINDOWS_GET_FAILED", "WINDOWS"], ["WINDOWS_UPDATE_FAILED", "WINDOWS"], ["WINDOW_FOCUS_FALSE", "WINDOWS"], ["WINDOW_FOCUS_TRUE", "WINDOWS"], ["DOCUMENT_VISIBILITY_HIDDEN", "SCRIPTING"], ["DOCUMENT_VISIBILITY_VISIBLE", "SCRIPTING"], ["OS_FOREGROUND_LAUNCH_FAILED", "NATIVE_FOREGROUND"], ["OS_FOREGROUND_LOCKED", "NATIVE_FOREGROUND"], ["OS_FOREGROUND_PLATFORM_UNSUPPORTED", "NATIVE_FOREGROUND"], ["OS_FOREGROUND_READY", "NATIVE_FOREGROUND"], ["OS_FOREGROUND_REPLAY", "NATIVE_FOREGROUND"], ["OS_FOREGROUND_WINDOW_ABSENT", "NATIVE_FOREGROUND"], ["OS_FOREGROUND_WINDOW_AMBIGUOUS", "NATIVE_FOREGROUND"] ]); const DOCUMENT_FOCUS_DIAGNOSTICS = new Set([ "DOCUMENT_FOCUS_FALSE", "DOCUMENT_FOCUS_TRUE", "DOCUMENT_FOCUS_UNAVAILABLE" ]); const DOCUMENT_VISIBILITY_DIAGNOSTICS = new Set([ "DOCUMENT_VISIBILITY_HIDDEN", "DOCUMENT_VISIBILITY_VISIBLE" ]); const FOREGROUND_ERROR_DIAGNOSTICS = new Map([ ["E_FOREGROUND_LAUNCH_FAILED", "OS_FOREGROUND_LAUNCH_FAILED"], ["E_FOREGROUND_LOCKED", "OS_FOREGROUND_LOCKED"], ["E_FOREGROUND_PLATFORM_UNSUPPORTED", "OS_FOREGROUND_PLATFORM_UNSUPPORTED"], ["E_FOREGROUND_REPLAY", "OS_FOREGROUND_REPLAY"], ["E_FOREGROUND_WINDOW_ABSENT", "OS_FOREGROUND_WINDOW_ABSENT"], ["E_FOREGROUND_WINDOW_AMBIGUOUS", "OS_FOREGROUND_WINDOW_AMBIGUOUS"] ]); const FOREGROUND_ELIGIBLE_CODES = new Set([ "E_PAGE_DIMENSIONS_UNAVAILABLE", "E_PAGE_IDENTITY_UNAVAILABLE", "E_PAGE_METADATA_UNAVAILABLE", "E_PAGE_OWNER_ANCHOR_UNAVAILABLE", "E_PAGE_SCRIPT_TIMEOUT", "E_PAGE_STABILITY_TIMEOUT", "E_PAGE_VIDEO_ABSENT" ]); function recordExtensionDiagnostic(reason) { const phase = EXTENSION_DIAGNOSTIC_CONTRACT.get(reason); if (typeof phase !== "string") return; lastExtensionDiagnostic = Object.freeze({phase, reason}); } function recordBrowserLifecycleDiagnostic(reason) { const phase = BROWSER_LIFECYCLE_DIAGNOSTIC_CONTRACT.get(reason); if (typeof phase !== "string") return; lastBrowserLifecycleDiagnostic = Object.freeze({phase, reason}); } function exactOwnedTabRecord(value) { const keys = [ "schema", "job_id", "lease_id", "bvid", "tab_id", "window_id", "cookie_store_id" ]; if (!isPlainObject(value) || !exactKeys(value, keys) || value.schema !== OWNED_TAB_SCHEMA || !HEX64_RE.test(value.job_id || "") || !HEX32_RE.test(value.lease_id || "") || !BVID_RE.test(value.bvid || "") || !Number.isInteger(value.tab_id) || value.tab_id < 0 || !Number.isInteger(value.window_id) || value.window_id < 0 || !STORE_ID_RE.test(value.cookie_store_id || "")) return null; return Object.freeze({...value}); } async function storageSessionCall(methodName, args) { if (!chrome.storage?.session) throw new Error("E_OWNED_TAB_STORAGE"); return chromeApiCall( chrome.storage.session, methodName, args, "E_OWNED_TAB_STORAGE", "OWNED_TAB_STORAGE_FAILED" ); } async function loadOwnedTabRecord() { try { const value = await storageSessionCall("get", [OWNED_TAB_STORAGE_KEY]); const raw = isPlainObject(value) ? value[OWNED_TAB_STORAGE_KEY] : null; if (raw === undefined || raw === null) return null; const record = exactOwnedTabRecord(raw); if (record !== null) return record; recordBrowserLifecycleDiagnostic("OWNED_TAB_RECORD_INVALID"); await storageSessionCall("remove", [OWNED_TAB_STORAGE_KEY]); } catch { recordBrowserLifecycleDiagnostic("OWNED_TAB_STORAGE_FAILED"); } return null; } async function persistOwnedTabRecord(job, leaseId, binding) { const record = exactOwnedTabRecord({ schema: OWNED_TAB_SCHEMA, job_id: job.job_id, lease_id: leaseId, bvid: job.bvid, tab_id: binding.tabId, window_id: binding.windowId, cookie_store_id: binding.cookieStoreId }); if (record === null || binding.managed !== true) throw new Error("E_OWNED_TAB_STORAGE"); try { await storageSessionCall("set", [{[OWNED_TAB_STORAGE_KEY]: record}]); } catch { recordBrowserLifecycleDiagnostic("OWNED_TAB_STORAGE_FAILED"); throw new Error("E_OWNED_TAB_STORAGE"); } recordBrowserLifecycleDiagnostic("OWNED_TAB_RECORDED"); return record; } async function clearOwnedTabRecord() { try { await storageSessionCall("remove", [OWNED_TAB_STORAGE_KEY]); return true; } catch { recordBrowserLifecycleDiagnostic("OWNED_TAB_STORAGE_FAILED"); return false; } } async function cleanupOwnedTab(recordValue = null) { const record = exactOwnedTabRecord(recordValue) || await loadOwnedTabRecord(); if (record === null) return true; let tab; try { tab = await chromeApiCall( chrome.tabs, "get", [record.tab_id], "E_OWNED_TAB_CLOSE", "TABS_GET_FAILED" ); } catch { await clearOwnedTabRecord(); recordBrowserLifecycleDiagnostic("OWNED_TAB_ALREADY_CLOSED"); return true; } if (!isPlainObject(tab) || tab.id !== record.tab_id || tab.windowId !== record.window_id || String(tab.cookieStoreId ?? "0") !== record.cookie_store_id || (!locationMatches(tab.url, record.bvid) && !locationMatches(tab.pendingUrl, record.bvid) && !isManagedIdentityPendingUrl(tab.url, record.bvid))) { await clearOwnedTabRecord(); recordBrowserLifecycleDiagnostic("OWNED_TAB_IDENTITY_DRIFT"); return false; } // Retire the durable ownership capability before the non-atomic remove. A // failed remove must never leave a record that a restarted service worker // could apply to a same-id/same-BVID user replacement. if (!await clearOwnedTabRecord()) { recordBrowserLifecycleDiagnostic("OWNED_TAB_CLOSE_FAILED"); return false; } try { await chromeApiCall( chrome.tabs, "remove", [record.tab_id], "E_OWNED_TAB_CLOSE", "TABS_REMOVE_FAILED" ); recordBrowserLifecycleDiagnostic("OWNED_TAB_CLOSED"); return true; } catch { // tabs.remove is not an atomic compare-and-close operation. Once it fails, // the numeric tab id may already name a replacement user tab, including a // replacement on the same BVID. No subsequent tabs.update/remove mutation // can prove object ownership. The durable capability was already retired, // so surface only a fixed, sanitized lifecycle result and never retry it. recordBrowserLifecycleDiagnostic("OWNED_TAB_CLOSE_FAILED"); return false; } } function extensionApiError(code, reason) { recordExtensionDiagnostic(reason); return new Error(code); } function chromeApiCall(receiver, methodName, args, code, reason) { return new Promise((resolve, reject) => { let settled = false; const settle = (error, value) => { if (settled) return; settled = true; if (error) reject(extensionApiError(code, reason)); else resolve(value); }; const callback = value => { let failed = false; try { failed = chrome.runtime.lastError != null; } catch { failed = true; } settle(failed, value); }; let returned; try { returned = receiver[methodName](...args, callback); } catch { settle(true); return; } if (returned && typeof returned.then === "function") { returned.then(value => settle(false, value), () => settle(true)); } }); } if (typeof globalThis.addEventListener === "function") { globalThis.addEventListener("error", () => recordExtensionDiagnostic("SERVICE_WORKER_ERROR")); globalThis.addEventListener("unhandledrejection", () => recordExtensionDiagnostic("SERVICE_WORKER_UNHANDLED_REJECTION")); } function isPlainObject(value) { if (value === null || typeof value !== "object" || Array.isArray(value)) return false; const prototype = Object.getPrototypeOf(value); return prototype === Object.prototype || prototype === null; } function exactKeys(value, keys) { return isPlainObject(value) && Object.keys(value).sort().join("\0") === [...keys].sort().join("\0"); } function safeErrorCode(error, fallback = "E_EXTENSION") { const candidate = typeof error?.message === "string" ? error.message : ""; return ERROR_CODE_RE.test(candidate) ? candidate : fallback; } function canonicalUrl(bvid) { return `https://www.bilibili.com/video/${bvid}`; } function locationMatches(rawUrl, bvid) { if (!BVID_RE.test(bvid) || typeof rawUrl !== "string") return false; let parsed; try { parsed = new URL(rawUrl); } catch { return false; } const path = `/video/${bvid}`; return parsed.origin === "https://www.bilibili.com" && (parsed.pathname === path || parsed.pathname === `${path}/`) && (parsed.search === "" || /^\?vd_source=[0-9a-f]{32}$/.test(parsed.search)) && parsed.hash === ""; } function isManagedIdentityPendingUrl(rawUrl, bvid) { if (rawUrl === "about:blank") return true; if (typeof rawUrl !== "string" || !BVID_RE.test(bvid)) return false; let parsed; try { parsed = new URL(rawUrl); } catch { return true; } if (parsed.origin !== "https://www.bilibili.com") return false; const videoMatch = /^\/video\/(BV1[1-9A-HJ-NP-Za-km-z]{9})\/?$/.exec(parsed.pathname); return videoMatch === null || videoMatch[1] === bvid; } function durationToleranceMs(expected) { return Math.max(1500, Math.min(10000, Math.ceil(expected / 1000))); } async function sha256Hex(text) { const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(text)); return Array.from(new Uint8Array(digest), value => value.toString(16).padStart(2, "0")).join(""); } async function validateJob(job) { const successor = isPlainObject(job) && Object.prototype.hasOwnProperty.call(job, "lineage"); if (!exactKeys(job, successor ? [...JOB_KEYS, "lineage"] : JOB_KEYS) || !HEX64_RE.test(job.job_id) || !BVID_RE.test(job.bvid) || !CREATOR_RE.test(job.creator_uid) || job.canonical_url !== canonicalUrl(job.bvid) || !Number.isSafeInteger(job.expected_duration_ms) || job.expected_duration_ms < 1000 || job.expected_duration_ms > 86400000 || typeof job.title !== "string" || !job.title.trim() || new TextEncoder().encode(job.title).length > 600 || typeof job.published_at !== "string" || job.published_at.length > 64 || !Number.isFinite(Date.parse(job.published_at))) return false; let stable; if (successor) { const lineage = job.lineage; if (!exactKeys(lineage, LINEAGE_KEYS) || !HEX64_RE.test(lineage.predecessor_job_id) || !Number.isSafeInteger(lineage.retry_generation) || lineage.retry_generation < 1 || lineage.retry_generation > 1000000 || !ERROR_CODE_RE.test(lineage.predecessor_terminal_error_code) || !MESSAGE_ID_RE.test(lineage.authorization_message_id) || !HANDOFF_ID_RE.test(lineage.authorization_handoff_id) || !UPPER_HEX64_RE.test(lineage.authorization_sha256) || !MESSAGE_ID_RE.test(lineage.repair_review_result_message_id) || !AUDIT_ID_RE.test(lineage.repair_audit_id) || !Number.isSafeInteger(lineage.repair_audit_bytes) || lineage.repair_audit_bytes < 1 || !UPPER_HEX64_RE.test(lineage.repair_audit_sha256)) return false; stable = await sha256Hex([ "bili-auth-job-v2", job.creator_uid, job.bvid, lineage.predecessor_job_id, String(lineage.retry_generation), lineage.predecessor_terminal_error_code, lineage.authorization_message_id, lineage.authorization_handoff_id, lineage.authorization_sha256, lineage.repair_review_result_message_id, lineage.repair_audit_id, String(lineage.repair_audit_bytes), lineage.repair_audit_sha256 ].join("\0")); } else { stable = await sha256Hex(`bili-auth-job-v1\0${job.creator_uid}\0${job.bvid}`); } return stable === job.job_id; } function validateMaintenance(value) { return exactKeys(value, ["reload_required", "reload_token", "required_extension_build", "retry_after_unix_ms"]) && typeof value.required_extension_build === "string" && value.required_extension_build.length <= 128 && typeof value.reload_required === "boolean" && (value.reload_token === null || HEX32_RE.test(value.reload_token)) && Number.isSafeInteger(value.retry_after_unix_ms) && value.retry_after_unix_ms >= 0; } async function validateResponse(value, expectedType) { if (!exactKeys(value, RESPONSE_KEYS) || value.schema !== SCHEMA || value.type !== expectedType || typeof value.host_build !== "string" || !SAFE_PHASES.has(value.phase) || !Number.isInteger(value.progress) || value.progress < 0 || value.progress > 100 || (value.error_code !== null && !/^E_[A-Z0-9_]{1,48}$/.test(value.error_code)) || !validateMaintenance(value.maintenance)) return false; if (value.job !== null && !(await validateJob(value.job))) return false; if (value.lease_id !== null && !HEX32_RE.test(value.lease_id)) return false; for (const name of ["formal_filename", "mapping_filename", "prepare_id"]) { if (value[name] !== null && typeof value[name] !== "string") return false; } return true; } function nativeSession() { let port; try { port = chrome.runtime.connectNative(HOST_NAME); } catch { throw extensionApiError("E_HOST_CONNECT", "NATIVE_CONNECT_FAILED"); } if (!isPlainObject(port) && (port === null || typeof port !== "object")) { throw extensionApiError("E_HOST_CONNECT", "NATIVE_CONNECT_FAILED"); } const messages = []; const waiters = []; let disconnected = false; let closeRequested = false; let lastDeterministicError = null; const rejectWaiters = code => { while (waiters.length) { const waiter = waiters.shift(); clearTimeout(waiter.timer); waiter.reject(new Error(code)); } }; port.onMessage.addListener(message => { if (isPlainObject(message) && ERROR_CODE_RE.test(message.error_code || "")) { lastDeterministicError = message.error_code; } const waiter = waiters.shift(); if (waiter) { clearTimeout(waiter.timer); waiter.resolve(message); } else messages.push(message); }); port.onDisconnect.addListener(() => { if (disconnected) return; disconnected = true; let runtimeFailure = false; try { runtimeFailure = chrome.runtime.lastError != null; } catch { runtimeFailure = true; } if (runtimeFailure) recordExtensionDiagnostic("NATIVE_DISCONNECT_FAILED"); rejectWaiters(lastDeterministicError || "E_HOST_DISCONNECT"); }); const next = timeoutMs => new Promise((resolve, reject) => { if (messages.length) { resolve(messages.shift()); return; } if (disconnected) { reject(new Error(lastDeterministicError || "E_HOST_DISCONNECT")); return; } const waiter = {resolve, reject, timer: null}; waiters.push(waiter); waiter.timer = setTimeout(() => { const index = waiters.indexOf(waiter); if (index >= 0) { waiters.splice(index, 1); reject(new Error("E_HOST_TIMEOUT")); } }, timeoutMs); }); return { async send(message, timeoutMs = 20000) { if (disconnected) throw new Error(lastDeterministicError || "E_HOST_DISCONNECT"); const response = next(timeoutMs); try { port.postMessage(message); } catch (error) { rejectWaiters(safeErrorCode(error, "E_HOST_SEND")); } return response; }, disconnect() { if (closeRequested) return; closeRequested = true; if (!disconnected) { try { port.disconnect(); } catch {} } } }; } function randomHex(bytes) { const data = new Uint8Array(bytes); crypto.getRandomValues(data); return Array.from(data, value => value.toString(16).padStart(2, "0")).join(""); } function isPageReadinessDiagnostic(value) { return exactKeys(value, ["attempts", "elapsed_ms", "reason", "state"]) && Number.isInteger(value.attempts) && value.attempts >= 0 && value.attempts <= 10000 && Number.isInteger(value.elapsed_ms) && value.elapsed_ms >= 0 && value.elapsed_ms <= 7200000 && PAGE_DIAGNOSTIC_STATES.has(value.state) && PAGE_DIAGNOSTIC_REASONS.has(value.reason); } function isCanonicalPreparelessTerminal(code, diagnostic) { if (!isPageReadinessDiagnostic(diagnostic)) return false; const contract = PREPARELESS_TERMINAL_DIAGNOSTIC_CONTRACT.get(code); return Array.isArray(contract) && contract.length === 2 && diagnostic.state === contract[0] && contract[1] instanceof Set && contract[1].has(diagnostic.reason); } function pageReadinessError(code, attempts, startedAtUnixMs, state, reason) { const diagnostic = { attempts, elapsed_ms: Math.max(0, Math.min(7200000, Date.now() - startedAtUnixMs)), state, reason }; if (!isCanonicalPreparelessTerminal(code, diagnostic)) return new Error("E_REJECT"); lastPageReadinessDiagnostic = diagnostic; const error = new Error(code); error.page_readiness_diagnostic = diagnostic; return error; } function fallbackPageReadinessDiagnostic(code) { const contract = PREPARELESS_TERMINAL_DIAGNOSTIC_CONTRACT.get(code); if (!Array.isArray(contract) || contract.length !== 2 || !(contract[1] instanceof Set) || contract[1].size !== 1) return null; const value = {attempts: 0, elapsed_ms: 0, state: contract[0], reason: [...contract[1]][0]}; lastPageReadinessDiagnostic = value; return value; } function tabDriftError(reason) { lastTabDriftReason = reason; const error = new Error("E_PAGE_TAB_DRIFT"); error.reason_code = reason; return error; } function tabIdentityReason(tab, binding) { if (!isPlainObject(tab) || !Number.isInteger(tab.id)) return "TAB_ID_INVALID"; if (tab.id !== binding.tabId) return "TAB_ID_CHANGED"; if (!Number.isInteger(tab.windowId) || tab.windowId !== binding.windowId) return "TAB_WINDOW_CHANGED"; if (String(tab.cookieStoreId ?? "0") !== binding.cookieStoreId) return "TAB_STORE_CHANGED"; return null; } function bindTab(tab, bvid, managed) { if (!isPlainObject(tab) || !Number.isInteger(tab.id) || !Number.isInteger(tab.windowId)) { throw tabDriftError("TAB_IDENTITY_INVALID"); } const exactUrl = locationMatches(tab.url, bvid); const exactPendingUrl = managed === true && locationMatches(tab.pendingUrl, bvid); if (!exactUrl && !exactPendingUrl) throw tabDriftError("TAB_URL_UNBOUND"); return Object.freeze({ tabId: tab.id, windowId: tab.windowId, cookieStoreId: String(tab.cookieStoreId ?? "0"), managed: managed === true }); } async function revalidateBoundTab(binding, bvid) { let current; try { current = await chromeApiCall( chrome.tabs, "get", [binding.tabId], "E_PAGE_TAB_DRIFT", "TABS_GET_FAILED" ); } catch { throw tabDriftError("TAB_REMOVED_OR_UNAVAILABLE"); } const identityReason = tabIdentityReason(current, binding); if (identityReason !== null) throw tabDriftError(identityReason); if (!locationMatches(current.url, bvid)) throw tabDriftError("TAB_URL_CHANGED"); return current; } async function activateBoundTab(binding, tab, bvid, startedAtUnixMs) { const identityReason = tabIdentityReason(tab, binding); if (identityReason !== null) throw tabDriftError(identityReason); let focusedWindow; try { focusedWindow = await chromeApiCall( chrome.windows, "update", [binding.windowId, {state: "normal", focused: true}], "E_PAGE_IDENTITY_UNAVAILABLE", "WINDOWS_UPDATE_FAILED" ); } catch { throw pageReadinessError( "E_PAGE_IDENTITY_UNAVAILABLE", 0, startedAtUnixMs, "IDENTITY_PENDING", "PAGE_WINDOW_FOCUS_PENDING" ); } if (!isPlainObject(focusedWindow) || focusedWindow.id !== binding.windowId) { throw tabDriftError("TAB_WINDOW_CHANGED"); } let updated; try { updated = await chromeApiCall( chrome.tabs, "update", [binding.tabId, {active: true}], "E_PAGE_IDENTITY_UNAVAILABLE", "TABS_UPDATE_FAILED" ); } catch { throw pageReadinessError( "E_PAGE_IDENTITY_UNAVAILABLE", 0, startedAtUnixMs, "IDENTITY_PENDING", "PAGE_TAB_ACTIVATION_PENDING" ); } const updatedIdentityReason = tabIdentityReason(updated, binding); if (updatedIdentityReason !== null) throw tabDriftError(updatedIdentityReason); if (!locationMatches(updated.url, bvid) && !(binding.managed && (locationMatches(updated.pendingUrl, bvid) || isManagedIdentityPendingUrl(updated.url, bvid)))) { throw tabDriftError("TAB_MANAGED_URL_DRIFT"); } return updated; } async function waitForComplete(binding, tab, bvid, startedAtUnixMs, deadlineUnixMs) { const identityReason = tabIdentityReason(tab, binding); if (identityReason !== null) throw tabDriftError(identityReason); if (tab.status === "complete" && locationMatches(tab.url, bvid)) { return revalidateBoundTab(binding, bvid); } if (!locationMatches(tab.url, bvid) && !(binding.managed && (locationMatches(tab.pendingUrl, bvid) || isManagedIdentityPendingUrl(tab.url, bvid)))) { throw tabDriftError("TAB_URL_UNBOUND"); } return new Promise((resolve, reject) => { let done = false; let timer = null; const finish = (error, value) => { if (done) return; done = true; chrome.tabs.onUpdated.removeListener(onUpdated); chrome.tabs.onRemoved.removeListener(onRemoved); if (timer !== null) clearTimeout(timer); if (error) reject(error); else resolve(value); }; const onUpdated = (tabId, change, current) => { if (tabId !== binding.tabId) return; const currentIdentityReason = tabIdentityReason(current, binding); if (currentIdentityReason !== null) { finish(tabDriftError(currentIdentityReason)); return; } if (typeof change?.url === "string" && !locationMatches(change.url, bvid) && !(binding.managed && isManagedIdentityPendingUrl(change.url, bvid))) { finish(tabDriftError("TAB_MANAGED_URL_DRIFT")); return; } if (locationMatches(current.url, bvid) && current.status === "complete") { finish(null, current); return; } if (!locationMatches(current.url, bvid) && !(binding.managed && (locationMatches(current.pendingUrl, bvid) || isManagedIdentityPendingUrl(current.url, bvid)))) { finish(tabDriftError("TAB_URL_CHANGED")); } }; const onRemoved = tabId => { if (tabId === binding.tabId) finish(tabDriftError("TAB_REMOVED_OR_UNAVAILABLE")); }; chrome.tabs.onUpdated.addListener(onUpdated); chrome.tabs.onRemoved.addListener(onRemoved); timer = setTimeout(() => finish(pageReadinessError( "E_PAGE_IDENTITY_UNAVAILABLE", 0, startedAtUnixMs, "IDENTITY_PENDING", "PAGE_URL_PENDING" )), Math.max(1, deadlineUnixMs - Date.now())); }); } async function waitForActiveNonMinimizedBoundTab(binding, bvid, startedAtUnixMs, deadlineUnixMs) { let pendingReason = "PAGE_WINDOW_STATE_PENDING"; while (Date.now() < deadlineUnixMs) { const current = await revalidateBoundTab(binding, bvid); let currentWindow; try { currentWindow = await chromeApiCall( chrome.windows, "get", [binding.windowId], "E_PAGE_IDENTITY_UNAVAILABLE", "WINDOWS_GET_FAILED" ); } catch { currentWindow = null; } if (!isPlainObject(currentWindow) || currentWindow.id !== binding.windowId) { pendingReason = "PAGE_WINDOW_STATE_PENDING"; } else if (typeof currentWindow.state !== "string") { pendingReason = "PAGE_WINDOW_STATE_PENDING"; } else if (currentWindow.state === "minimized") { pendingReason = "PAGE_WINDOW_MINIMIZED_PENDING"; } else if (!["normal", "maximized", "fullscreen", "locked-fullscreen"].includes(currentWindow.state)) { pendingReason = "PAGE_WINDOW_STATE_PENDING"; } else if (current.active !== true) { pendingReason = "PAGE_TAB_ACTIVATION_PENDING"; } else { recordExtensionDiagnostic(currentWindow.focused === true ? "WINDOW_FOCUS_TRUE" : "WINDOW_FOCUS_FALSE"); return current; } const remainingMs = deadlineUnixMs - Date.now(); if (remainingMs <= 0) break; await new Promise(resolve => setTimeout(resolve, Math.min(PAGE_PROOF_POLL_MS, remainingMs))); } throw pageReadinessError( "E_PAGE_IDENTITY_UNAVAILABLE", 0, startedAtUnixMs, "IDENTITY_PENDING", pendingReason ); } function foregroundFallbackEligible(error) { return FOREGROUND_ELIGIBLE_CODES.has(error?.message) && isPageReadinessDiagnostic(error?.page_readiness_diagnostic); } function exactWindowBounds(value) { if (!isPlainObject(value)) return null; const bounds = {}; for (const key of ["left", "top", "width", "height"]) { if (!Number.isSafeInteger(value[key])) return null; bounds[key] = value[key]; } if (bounds.width < 1 || bounds.height < 1) return null; return bounds; } async function foregroundAndRebind(session, job, leaseId, selected, flow, sourceError) { if (flow.foregroundUsed) throw sourceError; flow.foregroundUsed = true; let windowValue; try { windowValue = await chromeApiCall( chrome.windows, "get", [selected.binding.windowId], "E_PAGE_IDENTITY_UNAVAILABLE", "WINDOWS_GET_FAILED" ); } catch { throw sourceError; } const windowBounds = exactWindowBounds(windowValue); if (windowBounds === null) throw sourceError; const response = await session.send({ schema: SCHEMA, type: "foreground", job_id: job.job_id, lease_id: leaseId, tab_id: selected.binding.tabId, window_id: selected.binding.windowId, window_bounds: windowBounds }, 20000); if (!(await validateResponse(response, "foreground")) || response.job?.job_id !== job.job_id || response.lease_id !== leaseId) { throw sourceError; } if (response.phase !== "READY" || response.error_code !== null) { const diagnosticReason = FOREGROUND_ERROR_DIAGNOSTICS.get(response.error_code); if (typeof diagnosticReason === "string") recordExtensionDiagnostic(diagnosticReason); throw sourceError; } recordExtensionDiagnostic("OS_FOREGROUND_READY"); let pendingError = sourceError; while (Date.now() < flow.deadlineUnixMs) { let tabs; try { tabs = await chromeApiCall( chrome.tabs, "query", [{url: ["https://www.bilibili.com/video/*"], windowType: "normal"}], "E_PAGE_IDENTITY_UNAVAILABLE", "TABS_QUERY_FAILED" ); } catch { tabs = null; } if (Array.isArray(tabs)) { const exactCandidates = tabs.filter(item => item?.incognito !== true && locationMatches(item?.url, job.bvid)); if (exactCandidates.length > 1) throw new Error("E_PAGE_DUPLICATE_TAB"); if (exactCandidates.length === 1) { const preservesOwnership = selected.binding.managed === true && exactCandidates[0].id === selected.binding.tabId && exactCandidates[0].windowId === selected.binding.windowId; const rebound = { binding: bindTab(exactCandidates[0], job.bvid, preservesOwnership), tab: exactCandidates[0] }; const active = await waitForActiveNonMinimizedBoundTab( rebound.binding, job.bvid, flow.startedAtUnixMs, flow.deadlineUnixMs ); return {binding: rebound.binding, tab: active, activeNonMinimized: active}; } pendingError = pageReadinessError( "E_PAGE_IDENTITY_UNAVAILABLE", 0, flow.startedAtUnixMs, "IDENTITY_PENDING", "PAGE_URL_PENDING" ); } const remainingMs = flow.deadlineUnixMs - Date.now(); if (remainingMs <= 0) break; await new Promise(resolve => setTimeout(resolve, Math.min(PAGE_PROOF_POLL_MS, remainingMs))); } throw pendingError; } async function targetTab(session, job, leaseId, flow) { const startedAtUnixMs = Date.now(); let tabs; try { tabs = await chromeApiCall( chrome.tabs, "query", [{ url: ["https://www.bilibili.com/video/*"], windowType: "normal" }], "E_PAGE_IDENTITY_UNAVAILABLE", "TABS_QUERY_FAILED" ); } catch { throw pageReadinessError( "E_PAGE_IDENTITY_UNAVAILABLE", 0, startedAtUnixMs, "IDENTITY_PENDING", "PAGE_DOM_IDENTITY_PENDING" ); } if (!Array.isArray(tabs)) throw new Error("E_PAGE_PROOF"); const storedOwnership = await loadOwnedTabRecord(); const exactCandidates = []; for (const candidate of tabs.filter(item => item?.incognito !== true && locationMatches(item?.url, job.bvid))) { const adopted = storedOwnership !== null && storedOwnership.job_id === job.job_id && storedOwnership.lease_id === leaseId && storedOwnership.bvid === job.bvid && storedOwnership.tab_id === candidate.id && storedOwnership.window_id === candidate.windowId && storedOwnership.cookie_store_id === String(candidate.cookieStoreId ?? "0"); const provisional = bindTab(candidate, job.bvid, adopted); const current = await revalidateBoundTab(provisional, job.bvid); exactCandidates.push({binding: bindTab(current, job.bvid, adopted), tab: current}); if (adopted) recordBrowserLifecycleDiagnostic("OWNED_TAB_ADOPTED"); } if (exactCandidates.length > 1) throw new Error("E_PAGE_DUPLICATE_TAB"); let selected; if (exactCandidates.length === 1) { selected = exactCandidates[0]; } else { let created; try { created = await chromeApiCall( chrome.tabs, "create", [{url: canonicalUrl(job.bvid), active: false}], "E_PAGE_IDENTITY_UNAVAILABLE", "TABS_CREATE_FAILED" ); } catch { throw pageReadinessError( "E_PAGE_IDENTITY_UNAVAILABLE", 0, startedAtUnixMs, "IDENTITY_PENDING", "PAGE_NAVIGATION_PENDING" ); } selected = {binding: bindTab(created, job.bvid, true), tab: created}; await persistOwnedTabRecord(job, leaseId, selected.binding); } try { const activated = await activateBoundTab( selected.binding, selected.tab, job.bvid, startedAtUnixMs ); const activationDeadline = Math.min( flow.deadlineUnixMs, Date.now() + PAGE_EXTENSION_ACTIVATION_GRACE_MS ); const ready = await waitForComplete( selected.binding, activated, job.bvid, startedAtUnixMs, activationDeadline ); const activeNonMinimized = await waitForActiveNonMinimizedBoundTab( selected.binding, job.bvid, startedAtUnixMs, activationDeadline ); return {binding: selected.binding, tab: ready, activeNonMinimized}; } catch (error) { if (!foregroundFallbackEligible(error)) throw error; return foregroundAndRebind(session, job, leaseId, selected, flow, error); } } async function acquirePageProof(session, job, leaseId, selected, flow) { const remainingMs = flow.deadlineUnixMs - Date.now(); if (remainingMs <= 0) { throw pageReadinessError( "E_PAGE_IDENTITY_UNAVAILABLE", 0, flow.startedAtUnixMs, "IDENTITY_PENDING", "PAGE_URL_PENDING" ); } const initialBudgetMs = flow.foregroundUsed ? remainingMs : Math.min(PAGE_EXTENSION_ACTIVATION_GRACE_MS, remainingMs); try { return await observe(job, selected.binding, initialBudgetMs); } catch (error) { if (flow.foregroundUsed || !foregroundFallbackEligible(error)) throw error; const rebound = await foregroundAndRebind(session, job, leaseId, selected, flow, error); const finalBudgetMs = flow.deadlineUnixMs - Date.now(); if (finalBudgetMs <= 0) throw error; return observe(job, rebound.binding, finalBudgetMs); } } function injectedObservation(job, taskNonce) { const path = `/video/${job.bvid}`; if (location.href === "about:blank" || (typeof document.readyState === "string" && document.readyState !== "complete")) { return {status: "PENDING", terminal_error_code: "E_PAGE_IDENTITY_UNAVAILABLE", state: "IDENTITY_PENDING", reason: "PAGE_URL_PENDING"}; } const documentVisibilityDiagnostic = document.visibilityState === "visible" ? "DOCUMENT_VISIBILITY_VISIBLE" : "DOCUMENT_VISIBILITY_HIDDEN"; const documentFocusDiagnostic = typeof document.hasFocus !== "function" ? "DOCUMENT_FOCUS_UNAVAILABLE" : (document.hasFocus() === true ? "DOCUMENT_FOCUS_TRUE" : "DOCUMENT_FOCUS_FALSE"); if (location.origin !== "https://www.bilibili.com") { return {status: "REJECT", error_code: "E_PAGE_PROOF", state: "PAGE_REJECTED", reason: "PAGE_ORIGIN_REJECTED"}; } const observedBvid = /^\/video\/(BV1[1-9A-HJ-NP-Za-km-z]{9})\/?$/.exec(location.pathname)?.[1] ?? null; if (observedBvid !== null && observedBvid !== job.bvid) { return {status: "REJECT", error_code: "E_PAGE_PROOF", state: "PAGE_REJECTED", reason: "PAGE_BVID_REJECTED"}; } if ((location.pathname !== path && location.pathname !== `${path}/`) || (location.search !== "" && !/^\?vd_source=[0-9a-f]{32}$/.test(location.search)) || location.hash !== "") { return {status: "REJECT", error_code: "E_PAGE_PROOF", state: "PAGE_REJECTED", reason: "PAGE_URL_REJECTED"}; } if (document.querySelectorAll( ".error-container,.error-body,[data-bili-access-state='denied']" ).length > 0) { return {status: "REJECT", error_code: "E_PAGE_ACCESS_CONTROL", state: "PAGE_REJECTED", reason: "PAGE_ACCESS_REJECTED"}; } const videos = Array.from(document.querySelectorAll("video")); if (videos.length === 0) return {status: "PENDING", terminal_error_code: "E_PAGE_VIDEO_ABSENT", state: "VIDEO_ABSENT", reason: "VIDEO_ELEMENT_ABSENT"}; if (videos.length > 1) return {status: "REJECT", error_code: "E_MULTI_PART", state: "PAGE_REJECTED", reason: "PAGE_MULTIPART_REJECTED"}; const video = videos[0]; if (video.mediaKeys !== null) return {status: "REJECT", error_code: "E_DRM", state: "PAGE_REJECTED", reason: "PAGE_DRM_REJECTED"}; let initialVideo = null; let initialStateReason = "INITIAL_STATE_ASSIGNMENT_ABSENT"; for (const script of Array.from(document.querySelectorAll("script"))) { const raw = script?.textContent; if (typeof raw !== "string" || raw.length < 30 || raw.length > 2_000_000) continue; const trimmed = raw.trim(); const assignment = /^window\.__INITIAL_STATE__\s*=\s*/.exec(trimmed); if (assignment === null) continue; initialStateReason = "INITIAL_STATE_JSON_INVALID"; let encoded = trimmed.slice(assignment[0].length); const runtimeMarker = encoded.lastIndexOf(";(function(){"); if (runtimeMarker >= 0) encoded = encoded.slice(0, runtimeMarker); else if (encoded.endsWith(";")) encoded = encoded.slice(0, -1); try { const parsed = JSON.parse(encoded); const candidate = parsed?.videoData; initialStateReason = "INITIAL_STATE_VIDEO_DATA_ABSENT"; if (candidate && typeof candidate === "object" && !Array.isArray(candidate)) { if (initialVideo !== null) return {status: "REJECT", error_code: "E_PAGE_PROOF", state: "PAGE_REJECTED", reason: "PAGE_URL_REJECTED"}; initialVideo = candidate; initialStateReason = "METADATA_FIELDS_PENDING"; } } catch {} } const ownerAnchorIdentities = new Set(); const ownerProofRoots = document.querySelectorAll( "#v_upinfo,.up-info-container,.up-panel-container,.video-owner" ); for (const root of ownerProofRoots) { if (root === null || typeof root.querySelectorAll !== "function") continue; for (const anchor of root.querySelectorAll("a[href]")) { try { const href = new URL(anchor.href, location.href); if (href.origin !== "https://space.bilibili.com" || !/^\/[1-9][0-9]{0,19}\/?$/.test(href.pathname)) { continue; } const ownerUid = href.pathname.replace(/^\//, "").replace(/\/$/, ""); ownerAnchorIdentities.add(`https://space.bilibili.com/${ownerUid}`); } catch {} } } const canonicalOwnerUrl = `https://space.bilibili.com/${job.creator_uid}`; const ownerAnchorExact = ownerAnchorIdentities.size === 1 && ownerAnchorIdentities.has(canonicalOwnerUrl); const ownerAnchorReason = ownerAnchorExact ? null : (ownerAnchorIdentities.size === 0 ? "OWNER_ANCHOR_ABSENT" : (ownerAnchorIdentities.size === 1 ? "OWNER_ANCHOR_MISMATCH" : "OWNER_ANCHOR_AMBIGUOUS")); let initialMetadata = null; if (initialVideo !== null) { if (initialVideo.bvid !== job.bvid) return {status: "REJECT", error_code: "E_PAGE_PROOF", state: "PAGE_REJECTED", reason: "PAGE_BVID_REJECTED"}; if (!Array.isArray(initialVideo.pages) || initialVideo.pages.length === 0) { return {status: "REJECT", error_code: "E_PAGE_PROOF", state: "PAGE_REJECTED", reason: "PAGE_URL_REJECTED"}; } if (initialVideo.pages.length > 1) { return {status: "REJECT", error_code: "E_MULTI_PART", state: "PAGE_REJECTED", reason: "PAGE_MULTIPART_REJECTED"}; } const initialPage = initialVideo.pages[0]; const initialDimension = initialVideo.dimension; const pageDimension = initialPage?.dimension; const positiveSafeInteger = value => typeof value === "number" && Number.isSafeInteger(value) && value > 0; const positiveFiniteNumber = value => typeof value === "number" && Number.isFinite(value) && value > 0; if (!initialPage || typeof initialPage !== "object" || Array.isArray(initialPage) || !Object.prototype.hasOwnProperty.call(initialPage, "cid") || !Object.prototype.hasOwnProperty.call(initialPage, "page") || !Object.prototype.hasOwnProperty.call(initialPage, "duration") || !Object.prototype.hasOwnProperty.call(initialPage, "dimension") || !initialDimension || typeof initialDimension !== "object" || Array.isArray(initialDimension) || !pageDimension || typeof pageDimension !== "object" || Array.isArray(pageDimension) || !positiveSafeInteger(initialVideo.cid) || !positiveSafeInteger(initialPage.cid) || initialPage.cid !== initialVideo.cid || !positiveSafeInteger(initialPage.page) || initialPage.page !== 1 || !positiveFiniteNumber(initialVideo.duration) || !positiveFiniteNumber(initialPage.duration) || initialPage.duration !== initialVideo.duration || !positiveSafeInteger(initialDimension.width) || !positiveSafeInteger(initialDimension.height) || !positiveSafeInteger(pageDimension.width) || !positiveSafeInteger(pageDimension.height) || pageDimension.width !== initialDimension.width || pageDimension.height !== initialDimension.height) { return {status: "REJECT", error_code: "E_PAGE_PROOF", state: "PAGE_REJECTED", reason: "PAGE_URL_REJECTED"}; } const initialOwner = String(initialVideo.owner?.mid ?? ""); if (initialOwner !== "" && initialOwner !== job.creator_uid) { return {status: "REJECT", error_code: "E_OWNER", state: "PAGE_REJECTED", reason: "PAGE_OWNER_REJECTED"}; } initialMetadata = { duration: initialVideo.duration, width: initialDimension.width, height: initialDimension.height, owner: initialOwner }; } let metadataSource = "HTML_MEDIA_ELEMENT"; let durationSeconds = video.duration; let videoWidth = video.videoWidth; let videoHeight = video.videoHeight; let readyState = video.readyState; if (initialMetadata?.owner === "" && !ownerAnchorExact) { return {status: "PENDING", terminal_error_code: "E_PAGE_OWNER_ANCHOR_UNAVAILABLE", state: "OWNER_PENDING", reason: ownerAnchorReason}; } if (!Number.isFinite(durationSeconds) || durationSeconds <= 0 || readyState < 1 || videoWidth <= 0 || videoHeight <= 0) { if (initialMetadata !== null && (initialMetadata.owner === job.creator_uid || (initialMetadata.owner === "" && ownerAnchorExact))) { metadataSource = "BILIBILI_INITIAL_STATE"; durationSeconds = initialMetadata.duration; videoWidth = initialMetadata.width; videoHeight = initialMetadata.height; readyState = 1; } else if (!Number.isFinite(durationSeconds) || durationSeconds <= 0 || readyState < 1) { if (!PAGE_METADATA_UNAVAILABLE_REASONS.has(initialStateReason)) { return {status: "REJECT", error_code: "E_PAGE_PROOF", state: "PAGE_REJECTED", reason: "PAGE_URL_REJECTED"}; } return {status: "PENDING", terminal_error_code: "E_PAGE_METADATA_NOT_READY", state: "METADATA_NOT_READY", reason: initialStateReason}; } else { return {status: "PENDING", terminal_error_code: "E_PAGE_DIMENSIONS_UNAVAILABLE", state: "DIMENSIONS_PENDING", reason: "VIDEO_DIMENSIONS_PENDING"}; } } if (!ownerAnchorExact && String(initialVideo?.owner?.mid ?? "") !== job.creator_uid) { return {status: "PENDING", terminal_error_code: "E_PAGE_OWNER_ANCHOR_UNAVAILABLE", state: "OWNER_PENDING", reason: ownerAnchorReason}; } const durationMs = Math.round(durationSeconds * 1000); const tolerance = Math.max(1500, Math.min(10000, Math.ceil(job.expected_duration_ms / 1000))); if (Math.abs(durationMs - job.expected_duration_ms) > tolerance) { return {status: "REJECT", error_code: "E_DURATION", state: "PAGE_REJECTED", reason: "PAGE_DURATION_REJECTED"}; } return { status: "READY", document_focus_diagnostic: documentFocusDiagnostic, document_visibility_diagnostic: documentVisibilityDiagnostic, proof: { job_id: job.job_id, bvid: job.bvid, creator_uid: job.creator_uid, canonical_url: job.canonical_url, task_nonce: taskNonce, observed_at_unix_ms: Date.now(), metadata_source: metadataSource, observed_duration_ms: durationMs, video_width: videoWidth, video_height: videoHeight, ready_state: readyState, eme_present: video.mediaKeys !== null } }; } async function observe(job, binding, deadlineMs = PAGE_PROOF_DEADLINE_MS) { const taskNonce = randomHex(16); const startedAtUnixMs = Date.now(); const deadlineUnixMs = startedAtUnixMs + deadlineMs; let pendingTerminalCode = "E_PAGE_PROOF"; let pendingState = "PAGE_REJECTED"; let pendingReason = "PAGE_IDENTITY_REJECTED"; let attempts = 0; let stableSnapshots = 0; let stableSignature = null; let stableRejectSnapshots = 0; let stableRejectSignature = null; const deadlineCode = () => pendingTerminalCode === "E_PAGE_METADATA_NOT_READY" ? "E_PAGE_METADATA_UNAVAILABLE" : pendingTerminalCode; while (true) { await revalidateBoundTab(binding, job.bvid); const remainingBeforeInvocationMs = deadlineUnixMs - Date.now(); if (remainingBeforeInvocationMs <= 0) { throw pageReadinessError( deadlineCode(), attempts, startedAtUnixMs, pendingState, pendingReason ); } const invocationBudgetMs = Math.min(PAGE_PROOF_INVOCATION_TIMEOUT_MS, remainingBeforeInvocationMs); let deadlineTimer = null; let results; attempts += 1; try { results = await Promise.race([ chromeApiCall(chrome.scripting, "executeScript", [{ target: {tabId: binding.tabId, frameIds: [0]}, world: "ISOLATED", func: injectedObservation, args: [job, taskNonce] }], "E_PAGE_IDENTITY_UNAVAILABLE", "SCRIPTING_EXECUTE_FAILED"), new Promise((resolve, reject) => { deadlineTimer = setTimeout(() => reject(new Error("E_PAGE_SCRIPT_TIMEOUT")), invocationBudgetMs); }) ]); } catch (error) { if (error?.message === "E_PAGE_SCRIPT_TIMEOUT") { pendingTerminalCode = "E_PAGE_SCRIPT_TIMEOUT"; pendingState = "SCRIPT_TIMEOUT"; pendingReason = "SCRIPT_INVOCATION_FAILED"; } else { pendingTerminalCode = "E_PAGE_IDENTITY_UNAVAILABLE"; pendingState = "IDENTITY_PENDING"; pendingReason = "PAGE_SCRIPTING_PENDING"; } stableSnapshots = 0; stableSignature = null; stableRejectSnapshots = 0; stableRejectSignature = null; continue; } finally { if (deadlineTimer !== null) clearTimeout(deadlineTimer); } if (Date.now() >= deadlineUnixMs) { throw pageReadinessError( deadlineCode(), attempts, startedAtUnixMs, pendingState, pendingReason ); } if (!Array.isArray(results) || results.length !== 1 || !isPlainObject(results[0]) || !isPlainObject(results[0].result)) { pendingTerminalCode = "E_PAGE_IDENTITY_UNAVAILABLE"; pendingState = "IDENTITY_PENDING"; pendingReason = "PAGE_DOM_IDENTITY_PENDING"; stableSnapshots = 0; stableSignature = null; stableRejectSnapshots = 0; stableRejectSignature = null; continue; } const result = results[0].result; if (result.status === "READY" && exactKeys(result, ["document_focus_diagnostic", "document_visibility_diagnostic", "proof", "status"]) && DOCUMENT_FOCUS_DIAGNOSTICS.has(result.document_focus_diagnostic) && DOCUMENT_VISIBILITY_DIAGNOSTICS.has(result.document_visibility_diagnostic) && exactKeys(result.proof, PAGE_PROOF_KEYS)) { if (result.document_focus_diagnostic !== "DOCUMENT_FOCUS_TRUE") { recordExtensionDiagnostic(result.document_focus_diagnostic); } if (result.document_visibility_diagnostic !== "DOCUMENT_VISIBILITY_VISIBLE") { recordExtensionDiagnostic(result.document_visibility_diagnostic); } const signature = JSON.stringify(PAGE_PROOF_KEYS.filter( key => key !== "observed_at_unix_ms" && key !== "task_nonce" ).map(key => result.proof[key])); stableSnapshots = signature === stableSignature ? stableSnapshots + 1 : 1; stableSignature = signature; stableRejectSnapshots = 0; stableRejectSignature = null; if (stableSnapshots >= PAGE_PROOF_STABLE_SNAPSHOTS) return result.proof; pendingTerminalCode = "E_PAGE_STABILITY_TIMEOUT"; pendingState = "READY_UNSTABLE"; pendingReason = "STABLE_SNAPSHOTS_PENDING"; } else if (result.status === "REJECT" && exactKeys(result, ["error_code", "reason", "state", "status"]) && PREPARELESS_REJECT_CODES.has(result.error_code) && isCanonicalPreparelessTerminal(result.error_code, { attempts, elapsed_ms: Math.max(0, Math.min(7200000, Date.now() - startedAtUnixMs)), state: result.state, reason: result.reason })) { const stableIdentityReject = new Set([ "E_OWNER", "E_PAGE_ACCESS_CONTROL", "E_PAGE_PROOF" ]).has(result.error_code); if (!stableIdentityReject) { throw pageReadinessError( result.error_code, attempts, startedAtUnixMs, result.state, result.reason ); } pendingTerminalCode = result.error_code; pendingState = result.state; pendingReason = result.reason; stableSnapshots = 0; stableSignature = null; const rejectSignature = `${result.error_code}\0${result.state}\0${result.reason}`; stableRejectSnapshots = rejectSignature === stableRejectSignature ? stableRejectSnapshots + 1 : 1; stableRejectSignature = rejectSignature; if (stableRejectSnapshots >= PAGE_PROOF_STABLE_SNAPSHOTS) { throw pageReadinessError( result.error_code, attempts, startedAtUnixMs, result.state, result.reason ); } } else if (result.status !== "PENDING" || !exactKeys(result, ["reason", "state", "status", "terminal_error_code"]) || !PAGE_PENDING_TERMINAL_CONTRACT.has(result.terminal_error_code)) { throw new Error("E_PAGE_PROOF"); } else { const [expectedState, allowedReasons] = PAGE_PENDING_TERMINAL_CONTRACT.get(result.terminal_error_code); if (!PAGE_PENDING_STATES.has(result.state) || result.state !== expectedState || !PAGE_DIAGNOSTIC_REASONS.has(result.reason) || !allowedReasons.has(result.reason)) { throw new Error("E_PAGE_PROOF"); } pendingTerminalCode = result.terminal_error_code; pendingState = result.state; pendingReason = result.reason; stableSnapshots = 0; stableSignature = null; stableRejectSnapshots = 0; stableRejectSignature = null; } const remainingMs = deadlineUnixMs - Date.now(); if (remainingMs <= 0) { throw pageReadinessError( deadlineCode(), attempts, startedAtUnixMs, pendingState, pendingReason ); } await new Promise(resolve => setTimeout(resolve, Math.min(PAGE_PROOF_POLL_MS, remainingMs))); } } function normalizeCookie(cookie, storeId) { return { name: cookie.name, value: cookie.value, domain: cookie.domain, host_only: cookie.hostOnly, path: cookie.path, secure: cookie.secure, http_only: cookie.httpOnly, same_site: cookie.sameSite, session: cookie.session, expiration_unix: cookie.session === true ? null : Math.floor(cookie.expirationDate), store_id: cookie.storeId, partition_key: cookie.partitionKey === undefined ? null : cookie.partitionKey }; } function cookiePathMatches(path, bvid) { const wanted = `/video/${bvid}`; return path === "/" || (wanted.startsWith(path) && (path.endsWith("/") || path.length === wanted.length || wanted[path.length] === "/")); } function safeCookieString(value, minimum, maximumUtf8) { if (typeof value !== "string" || COOKIE_CONTROL_RE.test(value)) return false; const bytes = new TextEncoder().encode(value).length; return bytes >= minimum && bytes <= maximumUtf8; } function validBrowserCookie(cookie, storeId, proof, bvid, partitioned) { return exactKeys(cookie, COOKIE_KEYS) && safeCookieString(cookie.name, 1, 256) && safeCookieString(cookie.value, 1, 4096) && typeof cookie.host_only === "boolean" && cookie.domain === (cookie.host_only ? "www.bilibili.com" : ".bilibili.com") && safeCookieString(cookie.path, 1, 1024) && cookie.path.startsWith("/") && cookiePathMatches(cookie.path, bvid) && typeof cookie.secure === "boolean" && typeof cookie.http_only === "boolean" && typeof cookie.session === "boolean" && COOKIE_SAME_SITE.has(cookie.same_site) && STORE_ID_RE.test(cookie.store_id) && cookie.store_id === storeId && (partitioned ? validPartitionKeyDescriptor(cookie.partition_key) : cookie.partition_key === null) && (cookie.session ? cookie.expiration_unix === null : Number.isSafeInteger(cookie.expiration_unix) && cookie.expiration_unix >= 1 && cookie.expiration_unix > Math.floor(proof.observed_at_unix_ms / 1000)); } function validCookie(cookie, storeId, proof, bvid) { return validBrowserCookie(cookie, storeId, proof, bvid, false); } function validCookieSet(cookies, storeId, proof, bvid) { return Array.isArray(cookies) && cookies.length >= 1 && cookies.length <= MAX_COOKIE_COUNT && cookies.every(cookie => validCookie(cookie, storeId, proof, bvid)); } function validPartitionKeyDescriptor(value) { if (value === null || typeof value !== "object" || Array.isArray(value)) return false; const keys = Object.keys(value).sort().join("\0"); if (!["", "hasCrossSiteAncestor", "topLevelSite", "hasCrossSiteAncestor\0topLevelSite"].includes(keys)) { return false; } if (Object.prototype.hasOwnProperty.call(value, "hasCrossSiteAncestor") && typeof value.hasCrossSiteAncestor !== "boolean") return false; if (!Object.prototype.hasOwnProperty.call(value, "topLevelSite")) return true; if (!safeCookieString(value.topLevelSite, 1, 2048)) return false; try { const site = new URL(value.topLevelSite); return (site.protocol === "https:" || site.protocol === "http:") && site.origin === value.topLevelSite && site.username === "" && site.password === "" && site.pathname === "/" && site.search === "" && site.hash === ""; } catch { return false; } } function validRawSessionExpiration(cookie, proof) { if (typeof cookie.session !== "boolean") return false; if (cookie.session) return cookie.expirationDate === undefined; if (typeof cookie.expirationDate !== "number" || !Number.isFinite(cookie.expirationDate)) return false; const expirationUnix = Math.floor(cookie.expirationDate); return Number.isSafeInteger(expirationUnix) && expirationUnix >= 1 && expirationUnix > Math.floor(proof.observed_at_unix_ms / 1000); } function selectedCookieRelevance(cookie, storeId, bvid, proof) { if (cookie === null || typeof cookie !== "object" || Array.isArray(cookie) || !safeCookieString(cookie.name, 1, 256)) return "AMBIGUOUS"; if (!TRANSFER_COOKIE_NAMES.has(cookie.name)) return "IRRELEVANT_NAME"; if (cookie.partitionKey !== undefined) { if (!validRawSessionExpiration(cookie, proof)) return "AMBIGUOUS"; let normalized = null; try { normalized = normalizeCookie(cookie, storeId); return validBrowserCookie(normalized, storeId, proof, bvid, true) ? "IRRELEVANT_PARTITIONED" : "AMBIGUOUS"; } catch { return "AMBIGUOUS"; } finally { if (normalized !== null) { normalized.name = ""; normalized.value = ""; } } } return "SELECTED"; } function selectTransferCookies(rawCookies, storeId, proof, bvid) { const selected = []; const requiredNames = new Set(); if (!Array.isArray(rawCookies)) return {ok: false, reason: "COOKIE_API_SHAPE", cookies: selected}; if (rawCookies.length > MAX_COOKIE_COUNT) { return {ok: false, reason: "COOKIE_TRANSFER_OVERFLOW", cookies: selected}; } for (const rawCookie of rawCookies) { const relevance = selectedCookieRelevance(rawCookie, storeId, bvid, proof); if (relevance === "IRRELEVANT_NAME" || relevance === "IRRELEVANT_PARTITIONED") continue; if (relevance !== "SELECTED") { return {ok: false, reason: "COOKIE_RELEVANCE_AMBIGUOUS", cookies: selected}; } const cookie = normalizeCookie(rawCookie, storeId); selected.push(cookie); if (!validCookie(cookie, storeId, proof, bvid)) { return {ok: false, reason: "COOKIE_SELECTED_INVALID", cookies: selected}; } if (REQUIRED_AUTH_COOKIE_NAMES.has(cookie.name)) requiredNames.add(cookie.name); } if (selected.length === 0) return {ok: false, reason: "COOKIE_AUTH_SET_EMPTY", cookies: selected}; for (const requiredName of REQUIRED_AUTH_COOKIE_NAMES) { if (!requiredNames.has(requiredName)) { return {ok: false, reason: "COOKIE_AUTH_SET_EMPTY", cookies: selected}; } } const pathSpecificity = cookie => new TextEncoder().encode(cookie.path).length; const bestSpecificity = Math.max(...selected.map(pathSpecificity)); const highestPrecedence = selected.filter(cookie => pathSpecificity(cookie) === bestSpecificity); const firstValue = highestPrecedence[0].value; if (highestPrecedence.some(cookie => cookie.value !== firstValue)) { return {ok: false, reason: "COOKIE_EQUAL_PRECEDENCE_CONFLICT", cookies: selected}; } highestPrecedence.sort((left, right) => Number(right.host_only) - Number(left.host_only) || left.domain.localeCompare(right.domain) || left.path.localeCompare(right.path) || left.same_site.localeCompare(right.same_site) || Number(right.secure) - Number(left.secure) || Number(right.http_only) - Number(left.http_only) || Number(right.session) - Number(left.session) ); const chosen = highestPrecedence[0]; for (const cookie of selected) { if (cookie !== chosen) { cookie.name = ""; cookie.value = ""; } } const transfer = [chosen]; selected.length = 0; const valid = validCookieSet(transfer, storeId, proof, bvid); return {ok: valid, reason: valid ? "COOKIE_TRANSFER_READY" : "COOKIE_TRANSFER_INVALID", cookies: transfer}; } function zeroizeCookies(rawCookies, cookies) { for (const cookie of Array.isArray(cookies) ? cookies : []) { cookie.name = ""; cookie.value = ""; } for (const cookie of Array.isArray(rawCookies) ? rawCookies : []) { if (cookie !== null && typeof cookie === "object") { try { cookie.name = ""; } catch {} try { cookie.value = ""; } catch {} } } if (Array.isArray(cookies)) cookies.length = 0; if (Array.isArray(rawCookies)) rawCookies.length = 0; } async function abortPreparedForCookieAccess(session, job, leaseId, prepareId, rawCookies, cookies, reason) { lastCookieAccessReason = COOKIE_ACCESS_REASONS.has(reason) ? reason : "COOKIE_SELECTION_EXCEPTION"; zeroizeCookies(rawCookies, cookies); const aborted = await session.send({ schema: SCHEMA, type: "abort_prepare", job_id: job.job_id, lease_id: leaseId, prepare_id: prepareId, error_code: "E_COOKIE_ACCESS", error_reason: lastCookieAccessReason }); if (!(await validateResponse(aborted, "abort_prepare")) || aborted.phase !== "FAILED" || aborted.error_code !== "E_COOKIE_ACCESS" || aborted.prepare_id !== prepareId || aborted.job?.job_id !== job.job_id || aborted.lease_id !== leaseId) { throw new Error("E_PREPARE"); } return aborted; } async function runJobCore(session, job, leaseId, lifecycle) { lastTabDriftReason = null; lastCookieAccessReason = null; lastPageReadinessDiagnostic = null; let selectedTab; let proof; const flowStartedAtUnixMs = Date.now(); const foregroundFlow = { startedAtUnixMs: flowStartedAtUnixMs, deadlineUnixMs: flowStartedAtUnixMs + PAGE_PROOF_DEADLINE_MS, foregroundUsed: false }; try { selectedTab = await targetTab(session, job, leaseId, foregroundFlow); lifecycle.binding = selectedTab.binding; proof = await acquirePageProof(session, job, leaseId, selectedTab, foregroundFlow); await revalidateBoundTab(selectedTab.binding, job.bvid); } catch (error) { const code = typeof error?.message === "string" && PREPARELESS_REJECT_CODES.has(error.message) ? error.message : null; if (code === null) throw error; const candidate = isPageReadinessDiagnostic(error?.page_readiness_diagnostic) ? error.page_readiness_diagnostic : isPageReadinessDiagnostic(lastPageReadinessDiagnostic) ? lastPageReadinessDiagnostic : fallbackPageReadinessDiagnostic(code); const diagnostic = isCanonicalPreparelessTerminal(code, candidate) ? candidate : fallbackPageReadinessDiagnostic(code); if (!isCanonicalPreparelessTerminal(code, diagnostic)) throw new Error("E_REJECT"); const rejected = await session.send({ schema: SCHEMA, type: "reject", job_id: job.job_id, lease_id: leaseId, error_code: code, diagnostic }); if (!(await validateResponse(rejected, "reject")) || rejected.phase !== "FAILED" || rejected.error_code !== code || rejected.job?.job_id !== job.job_id || rejected.lease_id !== leaseId) { throw new Error("E_REJECT"); } return rejected; } const prepareId = randomHex(16); const prepared = await session.send({ schema: SCHEMA, type: "prepare", extension_build: EXTENSION_BUILD, lease_id: leaseId, prepare_id: prepareId, job, page_proof: proof }, 150000); const preparedValid = await validateResponse(prepared, "prepare"); if (preparedValid && prepared.phase === "COMPLETE" && prepared.prepare_id === prepareId && prepared.job?.job_id === job.job_id && prepared.lease_id === leaseId && prepared.progress === 100 && prepared.error_code === null && prepared.formal_filename === `${job.bvid}.mkv` && prepared.mapping_filename === `${job.bvid}.download.json`) { return prepared; } if (!preparedValid || prepared.phase !== "READY" || prepared.prepare_id !== prepareId) { const code = preparedValid && prepared.phase === "FAILED" && ERROR_CODE_RE.test(prepared.error_code || "") ? prepared.error_code : "E_PREPARE"; throw new Error(code); } const storeId = selectedTab.binding.cookieStoreId; let rawCookies = []; let cookies = []; try { rawCookies = await chrome.cookies.getAll({ url: canonicalUrl(job.bvid), name: AUTH_COOKIE_NAME, storeId }); } catch { return abortPreparedForCookieAccess(session, job, leaseId, prepareId, rawCookies, cookies, "COOKIE_API_ERROR"); } let selection; try { selection = selectTransferCookies(rawCookies, storeId, proof, job.bvid); } catch { return abortPreparedForCookieAccess( session, job, leaseId, prepareId, rawCookies, cookies, "COOKIE_SELECTION_EXCEPTION" ); } cookies = selection.cookies; if (!selection.ok) { return abortPreparedForCookieAccess( session, job, leaseId, prepareId, rawCookies, cookies, selection.reason ); } let started; try { started = await session.send({ schema: SCHEMA, type: "start", extension_build: EXTENSION_BUILD, lease_id: leaseId, prepare_id: prepareId, job, cookie_store_id: storeId, page_proof: proof, cookies }, 30000); } finally { zeroizeCookies(rawCookies, cookies); } if (!(await validateResponse(started, "status")) || started.job?.job_id !== job.job_id) { throw new Error("E_START"); } let state = started; while (!["COMPLETE", "FAILED", "POSTPROCESS_FAILED", "CANCELED"].includes(state.phase)) { await new Promise(resolve => setTimeout(resolve, 1000)); state = await session.send({schema: SCHEMA, type: "status", job_id: job.job_id, lease_id: leaseId}); if (!(await validateResponse(state, "status")) || state.job?.job_id !== job.job_id) throw new Error("E_STATUS"); } return state; } async function runJob(session, job, leaseId) { const lifecycle = {binding: null}; try { return await runJobCore(session, job, leaseId, lifecycle); } finally { // The durable session record is the authority. This also closes a tab when // a restart/rebind path lost its in-memory binding after Host start. await cleanupOwnedTab(); } } async function drainQueue() { if (drainLease) return; drainLease = true; lastDrainErrorCode = null; let session; try { session = nativeSession(); const hello = await session.send({schema: SCHEMA, type: "hello", extension_build: EXTENSION_BUILD}); const helloValid = await validateResponse(hello, "hello"); if (!helloValid) throw new Error("E_HELLO"); if (hello.phase === "FAILED") throw new Error(hello.error_code || "E_HOST"); if (hello.maintenance.reload_required) { const token = hello.maintenance.reload_token; if (!HEX32_RE.test(token || "")) return; const response = await session.send({schema: SCHEMA, type: "reload_begin", extension_build: EXTENSION_BUILD, reload_token: token}); if (!(await validateResponse(response, "reload_begin")) || response.phase !== "RELOAD_REQUIRED") return; session.disconnect(); session = null; chrome.runtime.reload(); return; } const polled = await session.send({schema: SCHEMA, type: "poll"}); const pollValid = await validateResponse(polled, "poll"); if (!pollValid) throw new Error("E_POLL"); const owned = await loadOwnedTabRecord(); const continuesOwnedJob = polled.phase === "READY" && polled.job && polled.lease_id && owned !== null && owned.job_id === polled.job.job_id && owned.lease_id === polled.lease_id; if (owned !== null && !continuesOwnedJob) await cleanupOwnedTab(owned); if (["FAILED", "POSTPROCESS_FAILED"].includes(polled.phase)) { throw new Error(polled.error_code || "E_HOST"); } if (polled.phase === "COMPLETE") { if (!polled.job || !polled.lease_id || polled.progress !== 100 || polled.error_code !== null || polled.formal_filename !== `${polled.job.bvid}.mkv` || polled.mapping_filename !== `${polled.job.bvid}.download.json`) { throw new Error("E_POLL"); } return; } if (polled.phase !== "READY" || !polled.job || !polled.lease_id) return; await runJob(session, polled.job, polled.lease_id); } catch (error) { // Memory-only safe code: never persist secrets, URLs, protocol payloads, or Host diagnostics here. lastDrainErrorCode = safeErrorCode(error); } finally { if (session) session.disconnect(); drainLease = false; } } function schedule() { chrome.alarms.create("bili-auth-queue", {periodInMinutes: 1}); void drainQueue(); } chrome.runtime.onInstalled.addListener(schedule); chrome.runtime.onStartup.addListener(schedule); chrome.alarms.onAlarm.addListener(alarm => { if (alarm?.name === "bili-auth-queue") void drainQueue(); });