// Vestibule content script — production implementation. // // Single responsibility: inject and manage the hidden menu overlay // and the lock overlay. The 3px-from-top gesture is the direct // descendant of the 2001 VB6 Form_MouseMove handler (Y <= 3). const EDGE_PX = 3; const HIDE_DELAY_MS = 1500; let menuEl = null; let hideTimer = null; // ─── Menu construction (data-driven) ────────────────────────────────── const MENU_ACTIONS = [ { action: "back", label: "Back", symbol: "\u25C0", handler: () => history.back() }, { action: "forward", label: "Forward", symbol: "\u25B6", handler: () => history.forward() }, { action: "refresh", label: "Refresh", symbol: "\u21BB", handler: () => location.reload() }, { action: "home", label: "Home", symbol: "\u2302", handler: () => browser.runtime.sendMessage({ type: "navigate-home" }).catch(() => {}) }, { divider: true }, { action: "unlock", label: "Unlock", symbol: "\uD83D\uDD12", handler: openUnlockPopup }, { action: "admin", label: "Admin", symbol: "\u2699", handler: () => browser.runtime.sendMessage({ type: "open-admin" }).catch(() => {}) }, ]; function buildMenu() { const menu = document.createElement("div"); menu.id = "vestibule-menu"; menu.setAttribute("role", "toolbar"); menu.setAttribute("aria-label", "Vestibule controls"); MENU_ACTIONS.forEach((item) => { if (item.divider) { const span = document.createElement("span"); span.className = "vestibule-divider"; menu.appendChild(span); return; } const btn = document.createElement("button"); btn.dataset.action = item.action; btn.title = item.label; btn.setAttribute("aria-label", item.label); btn.textContent = item.symbol; btn.addEventListener("click", () => { item.handler(); hideMenu(); }); menu.appendChild(btn); }); menu.addEventListener("mouseenter", () => clearTimeout(hideTimer)); menu.addEventListener("mouseleave", scheduleHide); return menu; } function ensureMenu() { if (menuEl && document.body.contains(menuEl)) return menuEl; menuEl = buildMenu(); document.documentElement.appendChild(menuEl); return menuEl; } // ─── Show / hide (step-down) ────────────────────────────────────────── function showMenu() { clearTimeout(hideTimer); ensureMenu().classList.add("vestibule-visible"); } function hideMenu() { if (menuEl) menuEl.classList.remove("vestibule-visible"); } function scheduleHide() { clearTimeout(hideTimer); hideTimer = setTimeout(hideMenu, HIDE_DELAY_MS); } // ─── Unlock popup ───────────────────────────────────────────────────── function openUnlockPopup() { browser.runtime.sendMessage({ type: "open-unlock-popup" }).catch(() => {}); } // ─── Lock overlay ───────────────────────────────────────────────────── function showLockOverlay() { if (document.getElementById("vestibule-lock-overlay")) return; const overlay = document.createElement("div"); overlay.id = "vestibule-lock-overlay"; overlay.innerHTML = `
This kiosk has been idle. Your browsing data has been cleared.
Click Unlock to start a new session.