theseus/preload.js
Local Dev 3e784e299c Theseus 0.3.31 rewrite — UI improvements + defensive hash-verify, spawn flags unchanged
Same 0.3.31 version, new binary. Rebuilds the shipped 0.3.31 with the
salvageable content from the reverted 0.3.32-0.3.34 track:

  chrome.html
    - light-mode chrome strip: --bg #e6e8ec, inactive tab #f2f4f7,
      active tab #ffffff. Fixes the "tabs disappear into the light
      Windows title bar" report.
    - bookmark chips shrunk: 130px max-width, 11px text, 12px favicon,
      22px row (was 26). ~40% more chips fit in the same width.
    - bookmark chips draggable with the tab-strip's left/right-half
      drop convention; new .dropbefore/.dropafter accent.
    - light-mode .tor + .logo + .upchip chips: from illegible white-
      on-#253A49 (at 12-13px) to #eef1f5 with #253A49 ink. Both readable
      now. .tor.connecting/.on keep amber/purple hue in light fills.

  main.js
    - will-download update handler now streams the saved setup .exe
      through crypto.createHash("sha256"), compares to the manifest's
      updateAvailable.setupHash before marking ready. Rejects and
      deletes the file on mismatch or on empty manifest hash. Test C
      in the previous session proved this catches truncated payloads
      Electron reports as "completed" (a real class of failure the
      Ariadne addon updater has always guarded against here).
    - new bookmark-move IPC: splices the list, no-ops on self-drop
      or missing entry.

  preload.js
    - moveBookmark(fromUrl, targetUrl, place) exposed for chrome.

Deliberately NOT changed: install-update-now still spawns setup with
["/S"] alone. The 0.3.32 --updated /S --force-run change was proven
in the previous session's real-install E2E to not address the actual
"browser vanished on D:\Program Files install" symptom — every flag
combination (/S alone, --updated /S --force-run, /S /currentuser,
/S /D=<install>) exits 0 without upgrading anything on that specific
install path. That's a separate open bug; not touched here.

Version stays 0.3.31 — this is a binary rewrite of 0.3.31, not a new
release. Existing 0.3.31 installs won't see an update chip (version
compare returns false), which is intentional given the auto-update
path is still broken for non-default install locations.
2026-09-08 21:26:42 +02:00

92 lines
6.1 KiB
JavaScript

const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("theseus", {
navigate: (input) => ipcRenderer.invoke("navigate", input),
search: (q) => ipcRenderer.invoke("search", q),
newTab: () => ipcRenderer.invoke("new-tab"),
closeTab: (id) => ipcRenderer.invoke("close-tab", id),
switchTab: (id) => ipcRenderer.invoke("switch-tab", id),
moveTab: (id, targetId, place) => ipcRenderer.invoke("move-tab", id, targetId, place),
suggestAddress: (query, rect) => ipcRenderer.invoke("suggest-address", query, rect),
closeAddressPicker: () => ipcRenderer.invoke("close-address-picker"),
addressCursor: (dir) => ipcRenderer.invoke("address-cursor", dir),
togglePwFill: (rect) => ipcRenderer.invoke("toggle-pw-fill", rect),
onPwAvailability: (cb) => ipcRenderer.on("pw-availability", (_e, d) => cb(d)),
// Update chip: chrome subscribes to update-available; clicking the chip's
// download button opens the URL in the system browser; ✕ dismisses for
// the current session.
onUpdateAvailable: (cb) => ipcRenderer.on("update-available", (_e, d) => cb(d)),
openUpdateDownload: (url) => ipcRenderer.invoke("open-update-download", url),
installUpdateNow: () => ipcRenderer.invoke("install-update-now"),
dismissUpdate: () => ipcRenderer.invoke("dismiss-update"),
goHome: () => ipcRenderer.invoke("go-home"),
back: () => ipcRenderer.invoke("go-back"),
forward: () => ipcRenderer.invoke("go-forward"),
reload: (hard) => ipcRenderer.invoke("reload", !!hard),
stop: () => ipcRenderer.invoke("stop"),
toggleTor: () => ipcRenderer.invoke("toggle-tor"),
openSettings: () => ipcRenderer.invoke("open-settings"),
getSettings: () => ipcRenderer.invoke("settings-get"),
setSetting: (key, val) => ipcRenderer.invoke("settings-set", key, val),
onSettingsUpdate: (cb) => ipcRenderer.on("settings-update", (_e, d) => cb(d)),
// Find-in-page. main.js fires 'find-open' on Ctrl+F; chrome renderer
// owns the bar UI and drives findInPage / stopFindInPage via these
// wrappers. Match count / active ordinal comes back through onFindResult.
onFindOpen: (cb) => ipcRenderer.on("find-open", () => cb()),
findInPage: (query, opts) => ipcRenderer.invoke("find-in-page", query, opts || {}),
findStop: () => ipcRenderer.invoke("find-stop"),
onFindResult: (cb) => ipcRenderer.on("find-result", (_e, d) => cb(d)),
toggleSiteInfo: (rect) => ipcRenderer.invoke("toggle-site-info", rect),
switchToBcnr: () => ipcRenderer.invoke("switch-to-bcnr"),
setChromeHeight: (h) => ipcRenderer.invoke("set-chrome-height", h),
getSearchEngines: () => ipcRenderer.invoke("search-engines"),
setSearchEngine: (id) => ipcRenderer.invoke("set-search-engine", id),
addEngine: (eng) => ipcRenderer.invoke("add-engine", eng),
removeEngine: (id) => ipcRenderer.invoke("remove-engine", id),
toggleEnginePicker: (rect) => ipcRenderer.invoke("toggle-engine-picker", rect),
onEngines: (cb) => ipcRenderer.on("engines", (_e, d) => cb(d)),
getBookmarks: () => ipcRenderer.invoke("bookmarks-get"),
addBookmark: (bm) => ipcRenderer.invoke("bookmark-add", bm),
updateBookmark: (url, patch) => ipcRenderer.invoke("bookmark-update", url, patch),
removeBookmark: (url) => ipcRenderer.invoke("bookmark-remove", url),
moveBookmark: (fromUrl, targetUrl, place) => ipcRenderer.invoke("bookmark-move", fromUrl, targetUrl, place),
onBookmarks: (cb) => ipcRenderer.on("bookmarks", (_e, d) => cb(d)),
onNav: (cb) => ipcRenderer.on("nav", (_e, d) => cb(d)),
onTor: (cb) => ipcRenderer.on("tor", (_e, d) => cb(d)),
onTabs: (cb) => ipcRenderer.on("tabs", (_e, d) => cb(d)),
tabReload: (id) => ipcRenderer.invoke("tab-reload", id),
tabDuplicate: (id) => ipcRenderer.invoke("tab-duplicate", id),
tabMute: (id, on) => ipcRenderer.invoke("tab-mute", id, on),
tabGroup: (id, color) => ipcRenderer.invoke("tab-group", id, color),
tabGroupToggle: (color) => ipcRenderer.invoke("tab-group-toggle", color),
tabBookmark: (id) => ipcRenderer.invoke("tab-bookmark", id),
onAddressPicked: (cb) => ipcRenderer.on("address-picked", (_e, url) => cb(url)),
onBcnrOffer: (cb) => ipcRenderer.on("bcnr-offer", (_e, d) => cb(d)),
// Collision-mode (BCNR ↔ ICANN) live switcher for the active tab
collisionSwitch: (arg) => ipcRenderer.invoke("collision-switch", arg),
collisionState: () => ipcRenderer.invoke("collision-state"),
// Downloads — the toolbar button subscribes to `downloads` to update its
// badge, and toggleDownloads opens/closes the floating panel.
getDownloads: () => ipcRenderer.invoke("downloads-get"),
toggleDownloads: (rect) => ipcRenderer.invoke("toggle-downloads", rect),
onDownloads: (cb) => ipcRenderer.on("downloads", (_e, d) => cb(d)),
// Add-on sidebar: toggle, open on a specific panel, close, or subscribe
// to state (visibility + which panel is active + the panel list). The
// extension dock in chrome.html renders one button per panel and calls
// openSidebar / closeSidebar accordingly.
toggleSidebar: () => ipcRenderer.invoke("sidebar-toggle"),
openSidebar: (panelId) => ipcRenderer.invoke("sidebar-open", panelId),
closeSidebar: () => ipcRenderer.invoke("sidebar-close"),
sidebarState: () => ipcRenderer.invoke("sidebar-state"),
onSidebarState: (cb) => ipcRenderer.on("sidebar-state", (_e, d) => cb(d)),
// Toolbar-menu (dropdown from an add-on's dock icon): dispatch the picked
// item id to the add-on's "menu-select" handler.
addonMenuSelect: (addonId, itemId) => ipcRenderer.invoke("addon-menu-select", addonId, itemId),
// Pop the dock-icon dropdown as a NATIVE menu. Renderer-side DOM popovers
// get clipped by chrome.html's own WebContentsView height (CHROME_H) and
// then covered by the tab view below it — a native Menu.popup escapes that
// layering entirely. Pass the button's viewport-rect so main can anchor.
toolbarMenuPopup: (addonId, rect) => ipcRenderer.invoke("toolbar-menu-popup", addonId, rect),
// Chrome listens so it can drop the "active" tint when the native menu
// dismisses (Esc, outside click, item picked — main fires all three).
onToolbarMenuClosed: (cb) => ipcRenderer.on("toolbar-menu-closed", () => cb()),
});