// Vestibule unlock popup — production implementation. // // Opens as a browser.windows.create popup. Sends the password to the // background script, which forwards to usher for Argon2id verification. // On success: the popup closes and the background clears the lock // overlay + enters admin grace mode. On failure: shows error, clears // input, refocuses. const REASON_MESSAGES = { invalid: "Invalid unlock code.", "not-configured": "No unlock password configured. Run the admin wizard (Ctrl+Shift+V).", }; document.getElementById("unlock-form").addEventListener("submit", (e) => { e.preventDefault(); const password = document.getElementById("unlock-password").value; if (!password) return; const submitBtn = e.target.querySelector("button[type=submit]"); submitBtn.disabled = true; submitBtn.textContent = "Verifying..."; browser.runtime .sendMessage({ type: "unlock-attempt", password }) .then(() => { // Result arrives asynchronously via runtime.onMessage. // The button re-enables when the result lands. }) .catch(() => { resetForm("Communication error. Try again."); }); }); browser.runtime.onMessage.addListener((msg) => { if (msg.type !== "unlock-result") return; if (msg.granted) { window.close(); return; } const message = REASON_MESSAGES[msg.reason] || "Unlock failed."; resetForm(message); }); function resetForm(errorMessage) { const input = document.getElementById("unlock-password"); const submitBtn = document.querySelector("button[type=submit]"); const errorEl = document.getElementById("unlock-error"); input.value = ""; input.focus(); submitBtn.disabled = false; submitBtn.textContent = "Unlock"; if (errorMessage) { errorEl.textContent = errorMessage; errorEl.hidden = false; } else { errorEl.hidden = true; } } console.log("[vestibule-unlock] popup loaded");