Decide which name systems Theseus can resolve, and which certificate roots it will trust. BNS (.x, .bch, .sia, …) is always on; everything else is off by default.
+ +
+ Your choices are stored in %APPDATA%\Theseus\extra-resolvers.json. They land in the file now and will come alive as each resolver is wired — the plan is 0.3.96 ENS, 0.3.97 Namecoin + Handshake, 0.3.98 SNS + Unstoppable, 0.3.99 Russian CA.
+
Silent Mode components that live alongside Theseus — each with its own on/off, updates and settings page.
@@ -816,6 +950,10 @@enumerateDevices() — closes a WebRTC fingerprinting leak, like Firefox.getDisplayMedia() outright, so no site or extension can even ask. Off by default because screen capture always opens a picker first — nothing is shared until you choose a screen or window and confirm.For each: Show (real), Hide (neutral value), Spoof (a decoy), or Manual (set your own).
@@ -1272,7 +1410,7 @@ // Running counts change as extensions start; refresh when the page is shown. document.addEventListener("visibilitychange", () => { if (!document.hidden) refresh(); }); })(); - const TOGGLES = ["restoreSession", "backgroundThrottle", "freezeBackgroundTabs", "extensionsOnDemand", "walletAtLaunch", "preloadMenus", "blockCamera", "blockMicrophone", "hideMediaDevices", "gpc", + const TOGGLES = ["restoreSession", "backgroundThrottle", "freezeBackgroundTabs", "extensionsOnDemand", "walletAtLaunch", "preloadMenus", "blockCamera", "blockMicrophone", "hideMediaDevices", "blockScreenCapture", "gpc", "clearCookiesOnQuit", "keepSignInsOnQuit", "clearCacheOnQuit", "clearStorageOnQuit", "clearHistoryOnQuit", "pwOfferSave", "pwOfferFill", "quickLinksShow", "translateAutoOffer", @@ -2817,6 +2955,7 @@ "open-tab": "Can open its own pages as full tabs.", "page-inject": "Runs code inside the web pages it declares — it can read and change what those pages show.", "capture-tab": "Can take screenshots of the current tab.", + "screen-capture": "Can ask to record a screen or window — including other applications — and save it to Downloads. You pick the source each time.", "vault-derive": "Derives its own keys from your password vault. It never sees the vault itself.", "approval-modal": "Can ask you to approve an action in a dialog over the page.", "session-proxy": "Can route the browser's traffic through a proxy it controls.", @@ -3102,6 +3241,85 @@ }); // Populate on first paint so the tab is ready when the user clicks in. (async () => { await loadAddonUpdates(); loadAddons(); })(); + + // Names & Certificates (0.3.95 — UI shell only; adapters land in 0.3.96–0.3.99). + // The toggles + Advanced fields persist to %APPDATA%\Theseus\extra-resolvers.json + // via main's extra-resolvers-get/set IPC. Nothing resolves yet; this is the + // user's chance to pre-configure defaults before each adapter ships. + (function () { + if (!C || !C.resolversGet || !C.resolversSet) return; // older preload — skip + const el = (i) => document.getElementById(i); + const BINDS = [ + // id key type + ["rvEnsOn", "resolvers.ens.enabled", "bool"], + ["rvEnsRpc", "resolvers.ens.rpc", "text"], + ["rvEnsGateway", "resolvers.ens.gateway", "text"], + ["rvNmcOn", "resolvers.namecoin.enabled", "bool"], + ["rvNmcRpc", "resolvers.namecoin.rpc", "text"], + ["rvHnsOn", "resolvers.handshake.enabled", "bool"], + ["rvHnsEndpoint", "resolvers.handshake.endpoint", "text"], + ["rvHnsCollisionPolicy", "resolvers.handshake.collision_policy", "text"], + ["rvSnsOn", "resolvers.sns.enabled", "bool"], + ["rvSnsRpc", "resolvers.sns.rpc", "text"], + ["rvUdOn", "resolvers.unstoppable.enabled","bool"], + ["rvUdEndpoint", "resolvers.unstoppable.endpoint","text"], + ["caRuOn", "ca_bundles.ru_national.enabled","bool"], + ["caRuScope", "ca_bundles.ru_national.scope_tlds","csv"], + ]; + function dig(obj, path) { + return path.split(".").reduce((o, k) => (o == null ? o : o[k]), obj); + } + function hydrate(state) { + for (const [id, key, type] of BINDS) { + const node = el(id); if (!node) continue; + const v = dig(state, key); + if (type === "bool") node.checked = !!v; + else if (type === "csv") node.value = Array.isArray(v) ? v.join(", ") : (v || ""); + else node.value = v != null ? String(v) : ""; + } + } + function readValue(id, type) { + const node = el(id); if (!node) return null; + if (type === "bool") return !!node.checked; + if (type === "csv") return node.value.split(/\s*,\s*/).map((s) => s.trim()).filter(Boolean); + return node.value; + } + async function save(id, key, type) { + const value = readValue(id, type); + try { await C.resolversSet(key, value); } catch (e) { console.warn("resolversSet failed", key, e); } + } + // Fire-once wiring. Load current state when the section first shows, + // persist each change through resolversSet. + let wired = false; + async function ensureWired() { + if (wired) return; wired = true; + try { + const state = await C.resolversGet(); + hydrate(state || {}); + } catch (e) { console.warn("resolversGet failed", e); } + for (const [id, key, type] of BINDS) { + const node = el(id); if (!node) continue; + const evt = type === "bool" ? "change" : "change"; // input events fire too often for text fields + node.addEventListener(evt, () => save(id, key, type)); + } + const resetBtn = el("rvReset"); + if (resetBtn) { + resetBtn.addEventListener("click", async () => { + if (!confirm("Reset every Names & Certificates toggle to defaults? BNS stays on; everything else goes off and Advanced fields are cleared.")) return; + try { + if (C.resolversReset) await C.resolversReset(); + const state = await C.resolversGet(); + hydrate(state || {}); + } catch (e) { console.warn("resolversReset failed", e); } + }); + } + } + document.addEventListener("section", (e) => { if (e.detail === "names") ensureWired(); }); + // If the user lands on #names directly, the section event already fired + // during showSection() before this IIFE registered the listener, so we + // kick wiring manually when the page is already visible. + try { if (!document.getElementById("names").hidden) ensureWired(); } catch {} + })();