(function () { const browser = typeof chrome !== 'undefined' && chrome.storage ? chrome : typeof browser !== 'undefined' ? browser : chrome; const KEY = 'holesailSettings'; const DEFAULTS = { proxyPort: 8443, defaultServerPort: 3000, defaultServerHost: '127.0.0.1', defaultSecure: true, requestTimeoutMs: 0, readyTimeoutMs: 0, disableOnFileUrls: false, notifyOnDisconnect: false, debug: false }; const proxyPortEl = document.getElementById('proxyPort'); const defaultServerPortEl = document.getElementById('defaultServerPort'); const defaultServerHostEl = document.getElementById('defaultServerHost'); const defaultSecureEl = document.getElementById('defaultSecure'); const requestTimeoutMsEl = document.getElementById('requestTimeoutMs'); const readyTimeoutMsEl = document.getElementById('readyTimeoutMs'); const disableOnFileUrlsEl = document.getElementById('disableOnFileUrls'); const notifyOnDisconnectEl = document.getElementById('notifyOnDisconnect'); const debugEl = document.getElementById('debug'); const btnSave = document.getElementById('btnSave'); const btnReset = document.getElementById('btnReset'); const toastEl = document.getElementById('toast'); function showToast(msg, isError) { toastEl.textContent = msg; toastEl.className = 'toast show' + (isError ? ' err' : ''); clearTimeout(showToast._t); showToast._t = setTimeout(function () { toastEl.classList.remove('show'); }, 2500); } function load() { browser.storage.local.get(KEY, function (result) { const s = result[KEY] || {}; if (proxyPortEl) proxyPortEl.value = s.proxyPort != null ? s.proxyPort : DEFAULTS.proxyPort; if (defaultServerPortEl) defaultServerPortEl.value = s.defaultServerPort != null ? s.defaultServerPort : DEFAULTS.defaultServerPort; if (defaultServerHostEl) defaultServerHostEl.value = s.defaultServerHost != null ? s.defaultServerHost : DEFAULTS.defaultServerHost; if (defaultSecureEl) defaultSecureEl.checked = s.defaultSecure !== false; if (requestTimeoutMsEl) requestTimeoutMsEl.value = s.requestTimeoutMs != null ? s.requestTimeoutMs : DEFAULTS.requestTimeoutMs; if (readyTimeoutMsEl) readyTimeoutMsEl.value = s.readyTimeoutMs != null ? s.readyTimeoutMs : DEFAULTS.readyTimeoutMs; if (disableOnFileUrlsEl) disableOnFileUrlsEl.checked = s.disableOnFileUrls === true; if (notifyOnDisconnectEl) notifyOnDisconnectEl.checked = s.notifyOnDisconnect === true; if (debugEl) debugEl.checked = s.debug === true; }); } function validate() { const proxyPort = proxyPortEl ? parseInt(proxyPortEl.value, 10) : DEFAULTS.proxyPort; if (isNaN(proxyPort) || proxyPort < 1 || proxyPort > 65535) { showToast('Proxy port must be 1–65535.', true); return null; } const defaultServerPort = defaultServerPortEl ? parseInt(defaultServerPortEl.value, 10) : DEFAULTS.defaultServerPort; if (isNaN(defaultServerPort) || defaultServerPort < 1 || defaultServerPort > 65535) { showToast('Default server port must be 1–65535.', true); return null; } const requestTimeout = requestTimeoutMsEl ? parseInt(requestTimeoutMsEl.value, 10) : DEFAULTS.requestTimeoutMs; if (isNaN(requestTimeout) || requestTimeout < 0) { showToast('Request timeout must be 0 or positive.', true); return null; } const readyTimeout = readyTimeoutMsEl ? parseInt(readyTimeoutMsEl.value, 10) : DEFAULTS.readyTimeoutMs; if (isNaN(readyTimeout) || readyTimeout < 0) { showToast('Ready timeout must be 0 or positive.', true); return null; } return { proxyPort, defaultServerPort, defaultServerHost: (defaultServerHostEl && defaultServerHostEl.value.trim()) || DEFAULTS.defaultServerHost, defaultSecure: defaultSecureEl ? defaultSecureEl.checked : DEFAULTS.defaultSecure, requestTimeoutMs: requestTimeout, readyTimeoutMs: readyTimeout, disableOnFileUrls: disableOnFileUrlsEl ? disableOnFileUrlsEl.checked : DEFAULTS.disableOnFileUrls, notifyOnDisconnect: notifyOnDisconnectEl ? notifyOnDisconnectEl.checked : DEFAULTS.notifyOnDisconnect, debug: debugEl ? debugEl.checked : DEFAULTS.debug }; } if (btnSave) { btnSave.addEventListener('click', function () { const s = validate(); if (!s) return; browser.storage.local.set({ [KEY]: s }, function () { if (browser.runtime.lastError) { showToast('Save failed: ' + browser.runtime.lastError.message, true); return; } showToast('Saved.'); }); }); } if (btnReset) { btnReset.addEventListener('click', function () { if (proxyPortEl) proxyPortEl.value = DEFAULTS.proxyPort; if (defaultServerPortEl) defaultServerPortEl.value = DEFAULTS.defaultServerPort; if (defaultServerHostEl) defaultServerHostEl.value = DEFAULTS.defaultServerHost; if (defaultSecureEl) defaultSecureEl.checked = DEFAULTS.defaultSecure; if (requestTimeoutMsEl) requestTimeoutMsEl.value = DEFAULTS.requestTimeoutMs; if (readyTimeoutMsEl) readyTimeoutMsEl.value = DEFAULTS.readyTimeoutMs; if (disableOnFileUrlsEl) disableOnFileUrlsEl.checked = DEFAULTS.disableOnFileUrls; if (notifyOnDisconnectEl) notifyOnDisconnectEl.checked = DEFAULTS.notifyOnDisconnect; if (debugEl) debugEl.checked = DEFAULTS.debug; browser.storage.local.set({ [KEY]: DEFAULTS }, function () { if (browser.runtime.lastError) { showToast('Reset failed: ' + browser.runtime.lastError.message, true); return; } showToast('Reset to defaults.'); }); }); } const installCaBtn = document.getElementById('installCaBtn'); if (installCaBtn) { installCaBtn.addEventListener('click', function () { showToast('Installing...'); browser.runtime.sendMessage( { target: 'holesail-native', action: 'send', payload: { type: 'installRootCA', payload: {} } }, function (response) { if (browser.runtime.lastError) { showToast('Error: ' + browser.runtime.lastError.message, true); return; } showToast(response && response.ok ? 'Root CA installed (or already installed).' : (response && response.error ? response.error : 'Failed'), !!(response && !response.ok)); } ); }); } load(); })();