The blocklist consumer existed in the resolver library and the gateway, but the browser opened a flagged name without comment. Now the indexer process reads the subscribed lists from the chain every ten minutes and hands the flags to main. A flagged name loads a warning page naming the reason, the list and the report; the user may continue, and that is remembered per name. Two gates, because content is reached two ways. loadBns shows the real interstitial. serveBns refuses with an inline page on every path that skips it: reload, back and forward, bns:// links, web app windows. The inline page has no button, since a page at the site's own origin must not be able to approve itself; only blocked.html may ask to continue, checked by file URL. Settings › Naming has the policy: warn (default), never open, or ignore the lists. The csam reason is never offered a way through. A list that cannot be read keeps the last known flags and never stops a name from resolving. The gateway put its own warning in front of flagged sites, which this browser could not get past: it fetches files itself, with no cookie jar. It now sends x-bns-policy: client and the gateway stays out of the way for a client that says it decides for itself. dev/blocklist-selftest.js runs the real protocol handler and decision functions against a scratch profile.
97 lines
6.8 KiB
JavaScript
97 lines
6.8 KiB
JavaScript
const { contextBridge, ipcRenderer } = require("electron");
|
||
contextBridge.exposeInMainWorld("cfg", {
|
||
get: () => ipcRenderer.invoke("settings-get"),
|
||
set: (key, value) => ipcRenderer.invoke("settings-set", key, value),
|
||
engines: () => ipcRenderer.invoke("search-engines"),
|
||
addEngine: (eng) => ipcRenderer.invoke("add-engine", eng),
|
||
removeEngine: (id) => ipcRenderer.invoke("remove-engine", id),
|
||
setEngineEnabled: (id, on) => ipcRenderer.invoke("set-engine-enabled", id, on),
|
||
setEngineOrder: (ids) => ipcRenderer.invoke("set-engine-order", ids),
|
||
removeFromList: (id) => ipcRenderer.invoke("remove-from-list", id),
|
||
// Storage: wipe browsing data on demand. Pass any subset of
|
||
// { cookies, cache, storage, history }.
|
||
clearBrowsingData: (opts) => ipcRenderer.invoke("clear-browsing-data", opts),
|
||
// Password vault. All calls return { ok, ... } | { ok: false, err }.
|
||
// Renderers never see the seed / vault key / master password past setup/
|
||
// unlock; get() returns plaintext only in explicit response to a user click.
|
||
pwStatus: () => ipcRenderer.invoke("password-status"),
|
||
pwSetup: (masterPassword, seedSource) => ipcRenderer.invoke("password-setup", { masterPassword, seedSource }),
|
||
pwUnlock: (masterPassword) => ipcRenderer.invoke("password-unlock", masterPassword),
|
||
pwLock: () => ipcRenderer.invoke("password-lock"),
|
||
pwList: () => ipcRenderer.invoke("password-list"),
|
||
pwGet: (id) => ipcRenderer.invoke("password-get", id),
|
||
pwAdd: (entry) => ipcRenderer.invoke("password-add", entry),
|
||
pwUpdate: (id, patch) => ipcRenderer.invoke("password-update", id, patch),
|
||
pwRemove: (id) => ipcRenderer.invoke("password-remove", id),
|
||
pwGenerate: (spec) => ipcRenderer.invoke("password-generate", spec),
|
||
// Quick-unlock PIN. pinSet proves the master password in main before
|
||
// wrapping it; pinUnlock opens Theseus's own PIN / password prompt.
|
||
pinStatus: () => ipcRenderer.invoke("vault-pin-status"),
|
||
pinSet: (pin, masterPassword) => ipcRenderer.invoke("vault-pin-set", { pin, masterPassword }),
|
||
pinClear: () => ipcRenderer.invoke("vault-pin-clear"),
|
||
pinUnlock: () => ipcRenderer.invoke("vault-pin-unlock"),
|
||
// Main asks settings to jump to a specific sidebar section (e.g. from the
|
||
// engine picker's "Search settings…" click). Emits the section id string.
|
||
onFocusSection: (cb) => ipcRenderer.on("focus-section", (_e, section) => cb(section)),
|
||
// Collision-mode: BCNR/ICANN policy + per-name/per-TLD overrides
|
||
collisionState: () => ipcRenderer.invoke("collision-state"),
|
||
setCollisionPolicy: (p) => ipcRenderer.invoke("collision-set-policy", p),
|
||
resetCollisions: () => ipcRenderer.invoke("collision-reset"),
|
||
// Blocklists: flagged names, the policy, and the "continue anyway" choices
|
||
blocklistState: () => ipcRenderer.invoke("blocklist-state"),
|
||
setBlocklistPolicy: (p) => ipcRenderer.invoke("blocklist-set-policy", p),
|
||
resetBlocklist: () => ipcRenderer.invoke("blocklist-reset"),
|
||
// Add-ons management (Settings > Add-ons tab).
|
||
listAddons: () => ipcRenderer.invoke("addons-list"),
|
||
setAddonEnabled: (id, enabled) => ipcRenderer.invoke("addons-set-enabled", id, !!enabled),
|
||
revealAddon: (folder) => ipcRenderer.invoke("addons-reveal", folder),
|
||
// Delete a non-bundled extension's folder (Settings › Extensions › ⋯ › Remove).
|
||
removeAddon: (id) => ipcRenderer.invoke("addons-remove", id),
|
||
openAddonsDir: () => ipcRenderer.invoke("addons-open-dir"),
|
||
reloadAddons: () => ipcRenderer.invoke("addons-reload"),
|
||
// Add-on update flow. checkAddonUpdates hits the release manifest and
|
||
// stages any newer signed version; listStagedAddonUpdates reports what's
|
||
// waiting; applyStagedAddons promotes staged → active and reactivates the
|
||
// addon host so the new bytes load without a full Theseus restart.
|
||
// Community extensions from theseus.x/extensions: the catalog (with what
|
||
// is installed already) and a verified install/update of one entry.
|
||
communityCatalog: () => ipcRenderer.invoke("addons-community-catalog"),
|
||
installCommunity: (id) => ipcRenderer.invoke("addons-install-community", id),
|
||
checkAddonUpdates: () => ipcRenderer.invoke("addons-check-updates"),
|
||
listStagedAddonUpdates: () => ipcRenderer.invoke("addons-list-staged"),
|
||
applyStagedAddons: (id) => ipcRenderer.invoke("addons-apply-staged", typeof id === "string" ? id : undefined),
|
||
// Settings › Performance › Protections: talk to an add-on's own message
|
||
// handlers (Shield, Cookie Pop-ups) and open its panel for the details.
|
||
addonInvoke: (id, msg, payload) => ipcRenderer.invoke("addon-invoke", String(id || ""), String(msg || ""), payload),
|
||
openPanel: (panelId) => ipcRenderer.invoke("settings-open-panel", String(panelId || "")),
|
||
// Which page is showing (the address bar follows), Tor state + toggle for Privacy › Network.
|
||
reportSection: (slug) => ipcRenderer.invoke("settings-section", String(slug || "")),
|
||
torState: () => ipcRenderer.invoke("tor-state"),
|
||
toggleTor: () => ipcRenderer.invoke("toggle-tor"),
|
||
// OS locale — used by the Website-language row to label "Automatic (OS: …)".
|
||
systemLocale: () => ipcRenderer.invoke("system-locale"),
|
||
// Live settings updates — the toolbar chip, this page's Website-language
|
||
// row, and the Anti-fingerprinting Language row all edit the same setting;
|
||
// any of them writing pushes a "settings-update" the others react to.
|
||
onSettingsUpdate: (cb) => ipcRenderer.on("settings-update", (_e, d) => cb(d)),
|
||
// Ariadne's Thread plug-in (system-wide resolver). The state getter returns
|
||
// { state:"running"|"stopped"|"not-installed", installedVersion, bundledVersion,
|
||
// canUpdate, hasUninstaller }; the mutators prompt UAC for admin.
|
||
ariadneState: () => ipcRenderer.invoke("ariadne-state"),
|
||
ariadneToggle: (on) => ipcRenderer.invoke("ariadne-toggle", !!on),
|
||
ariadneInstall: () => ipcRenderer.invoke("ariadne-install"),
|
||
ariadneUpdate: () => ipcRenderer.invoke("ariadne-update"),
|
||
ariadneUninstall: () => ipcRenderer.invoke("ariadne-uninstall"),
|
||
// Local BNS daemon settings + status (0.1.13+). All read/write against
|
||
// C:\ProgramData\Ariadne\policy.json (user-writable ACL) and the daemon's
|
||
// own /api/status endpoint on 127.0.0.1. No UAC required for any of these.
|
||
ariadneGetStatus: () => ipcRenderer.invoke("ariadne-get-status"),
|
||
ariadneGetPolicy: () => ipcRenderer.invoke("ariadne-get-policy"),
|
||
ariadneSetPolicy: (policy) => ipcRenderer.invoke("ariadne-set-policy", String(policy || "")),
|
||
ariadneSetSource: (name, enabled) => ipcRenderer.invoke("ariadne-set-source", String(name || ""), !!enabled),
|
||
// Manual "Check for updates" — un-dismisses any existing chip and re-
|
||
// fetches the release manifest. Returns { updateAvailable, currentVersion }.
|
||
recheckUpdate: () => ipcRenderer.invoke("recheck-update"),
|
||
appVersion: () => ipcRenderer.invoke("app-version"),
|
||
restartApp: () => ipcRenderer.invoke("app-restart"),
|
||
});
|