/** * Authrix Extension — Content Script v3 * * Responsibilities: * - Render the overlay UI (loading, result, error states) * - Relay messages from background to the overlay * - Recording is handled by offscreen.js (MV3 requirement) */ // ── Message listener ────────────────────────────────────────────────────────── chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { if (msg.type === 'SHOW_CAPTURE_OVERLAY') { showOverlay('capture'); sendResponse({ ok: true }); } if (msg.type === 'SHOW_URL_ANALYSIS_OVERLAY') { showOverlay('url', msg.url); sendResponse({ ok: true }); } if (msg.type === 'CAPTURE_PROGRESS') { const pct = Math.min(95, Math.round((msg.elapsed / msg.total) * 65)); updateLoadingText(`Recording: ${msg.elapsed}s / ${msg.total}s`); if (msg.elapsed === 1) activateStep(0); if (msg.elapsed >= msg.total) { activateStep(1); updateLoadingText('Processing frames — running AI analysis…'); } } if (msg.type === 'ANALYSIS_RESULT') { activateStep(3); renderResult(msg.result); } if (msg.type === 'ANALYSIS_ERROR') { showError(msg.error); } }); // ── Show overlay ────────────────────────────────────────────────────────────── function showOverlay(mode = 'capture', url = '') { document.getElementById('authrix-overlay')?.remove(); const overlay = document.createElement('div'); overlay.id = 'authrix-overlay'; overlay.innerHTML = `
${mode === 'url' ? 'Downloading & analyzing video…' : 'Initializing capture…'}
${mode === 'url' ? '⬇️ Downloading video' : '🎬 Recording tab stream'}
🖼️ Extracting frames
🧠 Running AI models
📊 Generating report
${mode === 'url' ? `
${escHtml(url.slice(0, 80))}${url.length > 80 ? '…' : ''}
` : `
Recording ~8 seconds of video for analysis
` }
`; document.body.appendChild(overlay); // Wire up buttons document.getElementById('authrix-close').onclick = () => overlay.remove(); overlay.addEventListener('click', e => { if (e.target === overlay) overlay.remove(); }); document.getElementById('authrix-open-app').onclick = () => window.open('https://aarav13-authrix.hf.space', '_blank'); document.getElementById('authrix-reanalyze').onclick = () => chrome.runtime.sendMessage({ type: 'START_CAPTURE' }); document.getElementById('authrix-retry').onclick = () => chrome.runtime.sendMessage({ type: 'START_CAPTURE' }); // Auto-activate first step for URL mode (no recording phase) if (mode === 'url') activateStep(1); } // ── Loading helpers ─────────────────────────────────────────────────────────── function updateLoadingText(text) { const el = document.getElementById('authrix-loading-text'); if (el) el.textContent = text; } function activateStep(idx) { document.querySelectorAll('.authrix-step').forEach((el, i) => { el.classList.toggle('active', i === idx); el.classList.toggle('done', i < idx); }); } function showState(state) { const loading = document.getElementById('authrix-loading'); const result = document.getElementById('authrix-result'); const error = document.getElementById('authrix-error'); if (loading) loading.style.display = state === 'loading' ? 'flex' : 'none'; if (result) result.style.display = state === 'result' ? 'block' : 'none'; if (error) error.style.display = state === 'error' ? 'flex' : 'none'; } // ── Render result ───────────────────────────────────────────────────────────── function renderResult(data) { const isFake = data.result === 'FAKE'; const conf = data.confidence ?? 0; const color = isFake ? '#ff4466' : '#00ff9c'; // Badge const badge = document.getElementById('authrix-badge'); if (badge) { badge.textContent = isFake ? '⚠' : '✓'; badge.style.color = color; badge.style.borderColor = color; badge.style.boxShadow = `0 0 16px ${color}44`; } // Verdict text const vt = document.getElementById('authrix-verdict-text'); if (vt) { vt.textContent = isFake ? 'DEEPFAKE DETECTED' : 'AUTHENTIC VIDEO'; vt.style.color = color; } // Confidence number const cv = document.getElementById('authrix-conf'); if (cv) { cv.textContent = conf + '%'; cv.style.color = color; } // Confidence bar const bar = document.getElementById('authrix-conf-bar'); if (bar) { bar.style.background = isFake ? 'linear-gradient(90deg,#880022,#ff4466)' : 'linear-gradient(90deg,#006633,#00ff9c)'; bar.style.boxShadow = `0 0 8px ${color}66`; setTimeout(() => { bar.style.width = conf + '%'; }, 80); } // Detail bullets (max 3) const dl = document.getElementById('authrix-details'); if (dl) { dl.innerHTML = (data.details || []).slice(0, 3).map(d => `
${escHtml(d)}
` ).join(''); } // Audio row const audioRow = document.getElementById('authrix-audio-row'); if (audioRow && data.audio?.available) { const isAI = data.audio.result === 'AI_VOICE'; const isMismatch = data.audio.result === 'AV_MISMATCH'; const aColor = (isAI || isMismatch) ? '#ff4466' : '#00ff9c'; const audioIcon = document.getElementById('authrix-audio-icon'); const audioLabel = document.getElementById('authrix-audio-label'); if (audioIcon) audioIcon.textContent = (isAI || isMismatch) ? '🤖' : '🎙️'; if (audioLabel) { audioLabel.textContent = isMismatch ? 'AV Mismatch — face-swap detected' : isAI ? `AI Voice (${data.audio.confidence}%)` : `Human Voice (${data.audio.confidence}%)`; audioLabel.style.color = aColor; } audioRow.style.display = 'flex'; } // Metadata row const meta = document.getElementById('authrix-meta'); if (meta && data.metadata) { const m = data.metadata; const parts = []; if (m.video_duration_sec) parts.push(`${m.video_duration_sec}s`); if (m.resolution && m.resolution !== '0x0') parts.push(m.resolution); if (m.frames_with_faces != null) parts.push(`${m.frames_with_faces} faces`); if (data.processing_time_sec) parts.push(`${data.processing_time_sec}s analysis`); if (parts.length) { meta.textContent = parts.join(' · '); meta.style.cssText = 'font-size:10px;color:rgba(255,255,255,0.25);margin-bottom:12px;font-family:monospace;'; } } showState('result'); } // ── Show error ──────────────────────────────────────────────────────────────── function showError(message) { const isOffline = !message || message.includes('fetch') || message.includes('Failed to fetch') || message.includes('ERR_CONNECTION'); const errMsg = document.getElementById('authrix-error-msg'); const errHint = document.getElementById('authrix-error-hint'); if (errMsg) { errMsg.textContent = isOffline ? 'Authrix server is not running' : (message || 'Unknown error'); } if (errHint) { errHint.textContent = isOffline ? 'Visit https://aarav13-authrix.hf.space to check server status' : 'Make sure a video is playing before capturing.'; } showState('error'); } // ── Utility ─────────────────────────────────────────────────────────────────── function escHtml(s) { return String(s) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); }