import {TrustedRuntimeSession} from "./protocol.js"; import {collectVisiblePage} from "./page_extract.js"; import {NativePortTransport, OwnedTabLifecycle, SlotCoordinator, SlotStateStore} from "./runtime.js"; const HOST = "com.project_info.bili_dynamic_refresh"; const ALARM = "project-info-dynamic-refresh-half-hour"; const PERIOD_MINUTES = 30; async function hashSlot(value) { const material = new TextEncoder().encode(String(value)); const digest = await crypto.subtle.digest("SHA-256", material); return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join(""); } function nextBoundary(now = Date.now()) { const interval = PERIOD_MINUTES * 60 * 1000; return Math.floor(now / interval) * interval + interval; } function createSession(api) { return new TrustedRuntimeSession(api, { extension_id: chrome.runtime.id, version: chrome.runtime.getManifest().version, manifest_name: chrome.runtime.getManifest().name }); } const lifecycle = new OwnedTabLifecycle(chrome); const slotStore = new SlotStateStore(chrome); const coordinator = new SlotCoordinator({ lifecycle, slotStore, connect: () => new NativePortTransport(chrome.runtime.connectNative(HOST)), createSession, hashSlot, collectPage: collectVisiblePage }); function schedule() { chrome.alarms.create(ALARM, {when: nextBoundary(), periodInMinutes: PERIOD_MINUTES}); } function recoverAtStartup() { // Never leak a raw storage/runtime exception from a startup event. The next // scheduled run will surface the same strict fixed code without acting. void coordinator.recover().catch(() => console.error("E_SLOT_STATE")); } chrome.runtime.onInstalled.addListener(() => { schedule(); recoverAtStartup(); }); chrome.runtime.onStartup.addListener(() => { schedule(); recoverAtStartup(); }); chrome.alarms.onAlarm.addListener((alarm) => { if (alarm?.name !== ALARM) return; // The slot material is deterministic at the half-hour boundary and carries // no session, cookie, profile, URL query, or page payload data. const slot = Math.floor(Number(alarm.scheduledTime) / (PERIOD_MINUTES * 60 * 1000)); void coordinator.run(`dynamic-slot:${slot}`); });