'use strict'; const APT_URL = 'http://127.0.0.1:18247/cookie'; const PAIRING_STORAGE_KEY = 'aptPairingSecret'; const PAIRING_SECRET_PATTERN = /^[A-Za-z0-9_-]{43}$/; function isSupportedDeploymentUrl(value) { try { const url = new URL(value); const host = url.hostname.toLowerCase(); return url.protocol === 'https:' && (host.endsWith('.avasecurity.com') || host.endsWith('.avigilon.com')); } catch { return false; } } function createPopupController({ chromeApi, documentApi, navigatorApi, fetchImpl, confirmCopy }) { const tabInfo = documentApi.getElementById('tabInfo'); const pairingInfo = documentApi.getElementById('pairingInfo'); const sendBtn = documentApi.getElementById('sendBtn'); const copyBtn = documentApi.getElementById('copyBtn'); const copyWarning = documentApi.getElementById('copyWarning'); const statusMsg = documentApi.getElementById('statusMsg'); const openOptionsBtn = documentApi.getElementById('openOptionsBtn'); let detectedOrigin = null; let pairingSecret = null; let busy = false; function showStatus(message, type) { statusMsg.textContent = message; statusMsg.className = `status-msg ${type}`; } function updateActions() { const disabled = busy || !detectedOrigin || !pairingSecret; sendBtn.disabled = disabled; copyBtn.disabled = disabled; } function setBusy(value) { busy = value; updateActions(); } async function getVaCookieValue() { if (!detectedOrigin) throw new Error('NO_DEPLOYMENT'); const cookie = await chromeApi.cookies.get({ url: detectedOrigin, name: 'va' }); if (!cookie || !cookie.value) throw new Error('MISSING_COOKIE'); if (cookie.expirationDate && cookie.expirationDate < Date.now() / 1000) { throw new Error('EXPIRED_COOKIE'); } return cookie.value; } function showCookieError(error, copyOperation = false) { if (error && error.message === 'MISSING_COOKIE') { showStatus('No VA token found. Log in to Alta and try again.', 'error'); } else if (error && error.message === 'EXPIRED_COOKIE') { showStatus('The VA token has expired. Log in to Alta again.', 'error'); } else if (copyOperation) { showStatus('Could not copy the VA token. Check clipboard permission.', 'error'); } else { showStatus('Could not reach Alta Proxy Tool on this computer.', 'error'); } } async function sendToApt() { if (!detectedOrigin || !pairingSecret || busy) return; setBusy(true); let cookieValue = null; try { showStatus('Sending to Alta Proxy Tool...', 'info'); cookieValue = await getVaCookieValue(); const response = await fetchImpl(APT_URL, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-APT-Pairing-Secret': pairingSecret }, body: JSON.stringify({ deploymentUrl: detectedOrigin, cookieValue }) }); const data = await response.json(); if (!response.ok || !data || data.success !== true) throw new Error('BRIDGE_REJECTED'); showStatus('VA token sent successfully.', 'success'); } catch (error) { showCookieError(error); } finally { cookieValue = null; setBusy(false); } } async function copyToken() { if (!detectedOrigin || !pairingSecret || busy) return; const confirmed = confirmCopy( 'Copy the full VA bearer token? Clipboard history or sync may retain it. Continue only if you will paste it into a trusted destination.' ); if (!confirmed) { showStatus('Copy cancelled. The VA token was not read.', 'info'); return; } setBusy(true); let cookieValue = null; try { cookieValue = await getVaCookieValue(); await navigatorApi.clipboard.writeText(cookieValue); showStatus('VA token copied. Clear your clipboard after use.', 'success'); } catch (error) { showCookieError(error, true); } finally { cookieValue = null; setBusy(false); } } async function init() { copyWarning.textContent = 'Copying exposes the full bearer token. Clipboard history or sync may retain it. A confirmation is required.'; sendBtn.addEventListener('click', sendToApt); copyBtn.addEventListener('click', copyToken); openOptionsBtn.addEventListener('click', () => chromeApi.runtime.openOptionsPage()); const stored = await chromeApi.storage.local.get(PAIRING_STORAGE_KEY); const candidate = stored && stored[PAIRING_STORAGE_KEY]; if (PAIRING_SECRET_PATTERN.test(typeof candidate === 'string' ? candidate : '')) { pairingSecret = candidate; pairingInfo.textContent = 'Paired with Alta Proxy Tool'; pairingInfo.className = 'pairing-info paired'; openOptionsBtn.hidden = true; } else { pairingInfo.textContent = 'Not paired. Add the one-time secret from APT.'; pairingInfo.className = 'pairing-info unpaired'; openOptionsBtn.hidden = false; } const tabs = await chromeApi.tabs.query({ active: true, currentWindow: true }); const tab = tabs && tabs[0]; if (!tab || !isSupportedDeploymentUrl(tab.url)) { tabInfo.textContent = 'This tab is not an Alta deployment.'; tabInfo.className = 'tab-info not-detected'; updateActions(); return; } const url = new URL(tab.url); detectedOrigin = url.origin; tabInfo.textContent = `Detected: ${url.hostname}`; tabInfo.className = 'tab-info detected'; updateActions(); } return { copyToken, init, sendToApt }; } if (typeof module !== 'undefined' && module.exports) { module.exports = { APT_URL, PAIRING_STORAGE_KEY, createPopupController, isSupportedDeploymentUrl }; } else { createPopupController({ chromeApi: chrome, documentApi: document, navigatorApi: navigator, fetchImpl: fetch, confirmCopy: (message) => window.confirm(message) }).init().catch(() => { const status = document.getElementById('statusMsg'); status.textContent = 'Extension initialization failed. Open pairing settings and try again.'; status.className = 'status-msg error'; }); }