radai-api / extension /background.js
RageCoder2006's picture
Clean deployment for Hugging Face
879d39c
Raw
History Blame Contribute Delete
4.68 kB
// ── AI Detector Β· background.js (service worker) ─────────────────────────
//
// Responsibilities:
// 1. Keep a canonical scan-result cache (in-memory + storage)
// 2. Handle OPEN_SIDE_PANEL messages from popup
// 3. Relay GET_SCAN_RESULT / CLEAR_SCAN_RESULT messages to side panel
// ── Init side panel on action click ───────────────────────────────────────
chrome.runtime.onInstalled.addListener(() => {
chrome.sidePanel.setPanelBehavior({ openPanelOnActionClick: true }).catch((error) => console.error(error));
});
// ── In-memory result cache ────────────────────────────────────────────────
// Survives for the lifetime of the service worker (typically a few minutes
// of inactivity). chrome.storage.local is the durable fallback.
let cachedResult = null;
const activeScans = new Set();
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
// Orchestrate scan logic globally to avoid duplication and sync state
if (msg.type === "START_SCAN") {
const tabId = msg.tabId;
if (activeScans.has(tabId)) {
sendResponse({ ok: false });
return false;
}
activeScans.add(tabId);
console.log("SCAN_STARTED");
cachedResult = { status: "scanning", tabId, timestamp: Date.now() };
chrome.storage.local.set({ scanResult: cachedResult, lastScreenshot: msg.screenshot }).catch(()=>{});
chrome.scripting.executeScript({
target: { tabId },
files: ["content.js"]
}).then(() => {
const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("Scan timed out after 90 seconds")), 90000));
const scanPromise = new Promise((resolve, reject) => {
chrome.tabs.sendMessage(tabId, { type: "SCAN_IMAGES", screenshot: msg.screenshot }, (resp) => {
if (chrome.runtime.lastError) reject(new Error(chrome.runtime.lastError.message));
else resolve(resp);
});
});
return Promise.race([scanPromise, timeoutPromise]);
}).then((response) => {
if (!response) throw new Error("No response from content script");
let finalResult;
if (response.stopped) {
finalResult = { status: "stopped", risk: 0, count: 0, explanation: null, tabId, timestamp: Date.now() };
} else if (response.done) {
const risk = typeof response.risk === "number" ? response.risk : 0;
const count = typeof response.count === "number" ? response.count : 0;
const explanation = response.explanation || null;
const rawConfidence = typeof response.rawConfidence === "number" ? response.rawConfidence : risk / 100;
finalResult = { status: "done", risk, count, explanation, rawConfidence, tabId, timestamp: Date.now() };
} else {
throw new Error(response.error || "Unexpected response");
}
console.log("SCAN_COMPLETED");
cachedResult = finalResult;
chrome.storage.local.set({ scanResult: finalResult }).catch(()=>{});
}).catch(err => {
console.warn("SCAN_ERROR:", err.message);
const errResult = { status: "error", error: err.message, tabId, timestamp: Date.now() };
cachedResult = errResult;
chrome.storage.local.set({ scanResult: errResult }).catch(()=>{});
}).finally(() => {
activeScans.delete(tabId);
});
sendResponse({ ok: true });
return false;
}
if (msg.type === "STOP_SCAN") {
console.log("SCAN_STOPPED");
chrome.tabs.sendMessage(msg.tabId, { type: "STOP_SCAN" }, () => {
void chrome.runtime.lastError;
});
sendResponse({ ok: true });
return false;
}
// Side panel β†’ background: retrieve latest scan result
if (msg.type === "GET_SCAN_RESULT") {
if (cachedResult) {
sendResponse({ result: cachedResult });
return false;
}
// Fall back to storage (service worker may have been restarted)
chrome.storage.local.get("scanResult", (data) => {
if (chrome.runtime.lastError) {
console.warn("[BG] storage read error:", chrome.runtime.lastError.message);
sendResponse({ result: null });
return;
}
cachedResult = data.scanResult || null;
sendResponse({ result: cachedResult });
});
return true; // async response
}
// Popup or side panel: clear stored result
if (msg.type === "CLEAR_SCAN_RESULT") {
cachedResult = null;
chrome.storage.local.remove("scanResult");
sendResponse({ ok: true });
return false;
}
});