Ship Theseus 0.0.8: window.bcnr dApp API + eTLD+1 permission origins
Merges a parallel session's work with the multi-source BNS story from 0.0.7.
The dApp side (parallel session)
--------------------------------
* bcnr-preload.js — installs `window.bcnr` on every page via contextBridge.
Read-only surface: resolveName(name), isRegistered(name), getBcnrTlds(),
getRecordVersion(name), plus getPermissionOrigin() for diagnostics. All
Promises; a missing name returns null (not throw). No signing, no wallet
unlock — that surface is designed but deliberately out of scope for 0.0.8
(see TheseusNavigator/DESIGN-integrated-wallet.md).
* bcnr-origin.js — pure function that computes the eTLD+1 permission origin
for a URL. ICANN suffixes via `psl` (same PSL Chromium uses, handles
.co.uk / .github.io / etc); BNS names key off the on-chain TLD list so
foo.wallet becomes a public suffix as soon as `wallet` appears there.
Match browser cookie / MetaMask semantics: a grant on pay.merchant.com
covers account.merchant.com but not evil.com.
* dev/bcnr-selftest.js, dev/origin-selftest.mjs — self-tests, no I/O.
* main.js wires bcnr-preload.js into session.defaultSession.setPreloads() so
it runs BEFORE per-WebContentsView preloads; adds bcnr:* IPC handlers.
* preload.js + chrome.html — small hooks so the shell picks up window.bcnr
the same way regular content does.
* package.json — psl dep, bcnr-preload.js/bcnr-origin.js in `files`.
Also included
-------------
* AriadneResolver/mobile/.../UpdateCheck.java — in-app update-check for the
Android app; already active in the shipped 0.11 APK (build.ps1 -Recurse
picked it up), formalising the source now.
* TheseusNavigator/snapshots/bns-name-snapshot.json — refreshed bundled
starter (73 beacon txs, root c37b8596…c54e414ba).
* Site pages + manifest updated to point at 0.0.8.
TheseusNavigator-Setup-0.0.8.exe 95.4 MB
21939743eafdfe8742a6b7c4b987bd2782384d7bc41289cb80a7e08019dc9f02
TheseusNavigator-0.0.8-portable.exe 92.7 MB
2aa429fe39dc0fa4ac040fc6d6eb31b0f890c8a83175c49fcb50f052c480d39d
2026-08-31 01:38:55 +02:00
|
|
|
// bcnr-preload.js — session-wide preload that installs `window.bcnr` on every
|
|
|
|
|
// page (regular tabs, popups, chrome/settings/etc). Reads only — no signing,
|
|
|
|
|
// no wallet unlock, no permission prompts. These four methods query the same
|
|
|
|
|
// resolver Theseus already runs for its address bar; nothing about the local
|
|
|
|
|
// user leaks, so no origin gate is needed for this surface.
|
|
|
|
|
//
|
|
|
|
|
// Sequencing: registered via `session.defaultSession.setPreloads([...])` in
|
|
|
|
|
// main.js at whenReady, which runs BEFORE per-WebContentsView preloads (home,
|
|
|
|
|
// settings, popover, etc.), so those preloads still install their own bridges
|
|
|
|
|
// on top of `window.bcnr`. See DESIGN-integrated-wallet.md §3 for the full
|
|
|
|
|
// API surface.
|
|
|
|
|
const { contextBridge, ipcRenderer } = require("electron");
|
|
|
|
|
|
|
|
|
|
// Every method returns a Promise; a name that fails to resolve or isn't
|
|
|
|
|
// registered comes back as `null` (not an error) so page code can treat
|
|
|
|
|
// "no such name" as data, not an exception. `getBcnrTlds` always returns
|
|
|
|
|
// an array — even the seed ["bch"] before the on-chain list has landed.
|
|
|
|
|
contextBridge.exposeInMainWorld("bcnr", {
|
|
|
|
|
resolveName: (name) => ipcRenderer.invoke("bcnr:resolveName", name),
|
|
|
|
|
isRegistered: (name) => ipcRenderer.invoke("bcnr:isRegistered", name),
|
|
|
|
|
getBcnrTlds: () => ipcRenderer.invoke("bcnr:getBcnrTlds"),
|
|
|
|
|
getRecordVersion: (name) => ipcRenderer.invoke("bcnr:getRecordVersion", name),
|
2026-09-16 00:53:13 +02:00
|
|
|
// Owner-signed DNS records (A/AAAA/MX/TXT/CNAME/NS) published beside the
|
|
|
|
|
// name's Sia content and verified by the gateway against the current NFT
|
|
|
|
|
// holder. `{ name, dns, seq, updatedAt, owner }`, or null when the name is
|
|
|
|
|
// unregistered or has published no manifest. Waits ≤ 3 s for a fetch.
|
|
|
|
|
dnsRecords: (name) => ipcRenderer.invoke("bcnr:dnsRecords", name),
|
Ship Theseus 0.0.8: window.bcnr dApp API + eTLD+1 permission origins
Merges a parallel session's work with the multi-source BNS story from 0.0.7.
The dApp side (parallel session)
--------------------------------
* bcnr-preload.js — installs `window.bcnr` on every page via contextBridge.
Read-only surface: resolveName(name), isRegistered(name), getBcnrTlds(),
getRecordVersion(name), plus getPermissionOrigin() for diagnostics. All
Promises; a missing name returns null (not throw). No signing, no wallet
unlock — that surface is designed but deliberately out of scope for 0.0.8
(see TheseusNavigator/DESIGN-integrated-wallet.md).
* bcnr-origin.js — pure function that computes the eTLD+1 permission origin
for a URL. ICANN suffixes via `psl` (same PSL Chromium uses, handles
.co.uk / .github.io / etc); BNS names key off the on-chain TLD list so
foo.wallet becomes a public suffix as soon as `wallet` appears there.
Match browser cookie / MetaMask semantics: a grant on pay.merchant.com
covers account.merchant.com but not evil.com.
* dev/bcnr-selftest.js, dev/origin-selftest.mjs — self-tests, no I/O.
* main.js wires bcnr-preload.js into session.defaultSession.setPreloads() so
it runs BEFORE per-WebContentsView preloads; adds bcnr:* IPC handlers.
* preload.js + chrome.html — small hooks so the shell picks up window.bcnr
the same way regular content does.
* package.json — psl dep, bcnr-preload.js/bcnr-origin.js in `files`.
Also included
-------------
* AriadneResolver/mobile/.../UpdateCheck.java — in-app update-check for the
Android app; already active in the shipped 0.11 APK (build.ps1 -Recurse
picked it up), formalising the source now.
* TheseusNavigator/snapshots/bns-name-snapshot.json — refreshed bundled
starter (73 beacon txs, root c37b8596…c54e414ba).
* Site pages + manifest updated to point at 0.0.8.
TheseusNavigator-Setup-0.0.8.exe 95.4 MB
21939743eafdfe8742a6b7c4b987bd2782384d7bc41289cb80a7e08019dc9f02
TheseusNavigator-0.0.8-portable.exe 92.7 MB
2aa429fe39dc0fa4ac040fc6d6eb31b0f890c8a83175c49fcb50f052c480d39d
2026-08-31 01:38:55 +02:00
|
|
|
// Diagnostic — the eTLD+1 permission origin Theseus computes for THIS page.
|
|
|
|
|
// dApp devs use this to see how their subdomains bucket under one grant.
|
|
|
|
|
// Returns null for opaque origins (data:, blob:) which never hold grants.
|
|
|
|
|
getOrigin: () => ipcRenderer.invoke("bcnr:getOrigin"),
|
2026-09-21 02:40:05 +02:00
|
|
|
// One-click install of a community extension by catalog id (what
|
|
|
|
|
// theseus.x/extensions' Install button calls). The page names an id only;
|
|
|
|
|
// Theseus fetches the catalog itself, asks the user in a native dialog,
|
|
|
|
|
// verifies the publisher signature against the name's owner and installs.
|
|
|
|
|
// Resolves `{ ok, version, publisher }` or `{ ok:false, error }` (also
|
|
|
|
|
// "cancelled"). Pages can feature-detect it: absent on older builds.
|
|
|
|
|
installExtension: (id) => ipcRenderer.invoke("bcnr:installExtension", String(id || "")),
|
Ship Theseus 0.0.8: window.bcnr dApp API + eTLD+1 permission origins
Merges a parallel session's work with the multi-source BNS story from 0.0.7.
The dApp side (parallel session)
--------------------------------
* bcnr-preload.js — installs `window.bcnr` on every page via contextBridge.
Read-only surface: resolveName(name), isRegistered(name), getBcnrTlds(),
getRecordVersion(name), plus getPermissionOrigin() for diagnostics. All
Promises; a missing name returns null (not throw). No signing, no wallet
unlock — that surface is designed but deliberately out of scope for 0.0.8
(see TheseusNavigator/DESIGN-integrated-wallet.md).
* bcnr-origin.js — pure function that computes the eTLD+1 permission origin
for a URL. ICANN suffixes via `psl` (same PSL Chromium uses, handles
.co.uk / .github.io / etc); BNS names key off the on-chain TLD list so
foo.wallet becomes a public suffix as soon as `wallet` appears there.
Match browser cookie / MetaMask semantics: a grant on pay.merchant.com
covers account.merchant.com but not evil.com.
* dev/bcnr-selftest.js, dev/origin-selftest.mjs — self-tests, no I/O.
* main.js wires bcnr-preload.js into session.defaultSession.setPreloads() so
it runs BEFORE per-WebContentsView preloads; adds bcnr:* IPC handlers.
* preload.js + chrome.html — small hooks so the shell picks up window.bcnr
the same way regular content does.
* package.json — psl dep, bcnr-preload.js/bcnr-origin.js in `files`.
Also included
-------------
* AriadneResolver/mobile/.../UpdateCheck.java — in-app update-check for the
Android app; already active in the shipped 0.11 APK (build.ps1 -Recurse
picked it up), formalising the source now.
* TheseusNavigator/snapshots/bns-name-snapshot.json — refreshed bundled
starter (73 beacon txs, root c37b8596…c54e414ba).
* Site pages + manifest updated to point at 0.0.8.
TheseusNavigator-Setup-0.0.8.exe 95.4 MB
21939743eafdfe8742a6b7c4b987bd2782384d7bc41289cb80a7e08019dc9f02
TheseusNavigator-0.0.8-portable.exe 92.7 MB
2aa429fe39dc0fa4ac040fc6d6eb31b0f890c8a83175c49fcb50f052c480d39d
2026-08-31 01:38:55 +02:00
|
|
|
});
|
feat(theseus): install a site as an app, the way Chrome and Edge offer it
Electron ships Chromium's renderer without the browser-side web-app
install machinery, so beforeinstallprompt never fires and every site's
own "Install our app" chip (coin-spectrum.com's, for one) stays hidden
in Theseus. The browser side now exists:
- webapps.js reads a page's <link rel="manifest">, accepts it when it
names an app with a standalone-style display mode and a start_url on
the page's origin, and records the descriptor on the tab.
- The address bar shows an install chip for such pages (filled once the
app is installed: click then opens or removes it); the page context
menu carries the same entry.
- Pages get a synthetic beforeinstallprompt whose prompt() routes to the
Theseus install dialog and resolves userChoice like Chrome, and an
appinstalled event afterwards, so sites' own chips appear and work.
- Installing stores the app under <userData>/webapps/, wraps the
manifest icon into an .ico, writes a Start Menu (optionally desktop)
shortcut that launches Theseus with --app=<start_url>, and opens the
app in a chromeless window with its own taskbar identity. The window
shares the session, BCNR resolution, fingerprint and add-on bridges
with tabs; popups and "open in Theseus" go to the browser window,
Alt+arrows / F5 / Ctrl+R cover navigation without a toolbar.
- Theseus takes the single-instance lock so a shortcut launch lands in
the running browser (second-instance) instead of a second profile
owner; launched cold, --app= opens only the app window and a later
plain launch brings the browser window back.
2026-09-27 01:23:36 +02:00
|
|
|
|
|
|
|
|
// Install-as-app relay. Theseus fires a synthetic `beforeinstallprompt` in
|
|
|
|
|
// pages whose manifest is installable (webapps.js); the page's prompt()
|
|
|
|
|
// dispatches a DOM event that this isolated world hears, asks main for the
|
|
|
|
|
// install dialog, and answers with another DOM event. Nothing is exposed
|
|
|
|
|
// on window; the page only ever sees Chrome's event shape. Top frame only.
|
|
|
|
|
try {
|
|
|
|
|
if (window.top === window) {
|
|
|
|
|
document.addEventListener("theseus:webapp-prompt", () => {
|
|
|
|
|
ipcRenderer.invoke("webapp-prompt").then((r) => {
|
|
|
|
|
document.dispatchEvent(new Event(r === "accepted" ? "theseus:webapp-accepted" : "theseus:webapp-dismissed"));
|
|
|
|
|
}).catch(() => { try { document.dispatchEvent(new Event("theseus:webapp-dismissed")); } catch {} });
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
} catch {}
|