feat(remote-control): viewer can control a desktop sharer's screen, with consent (0.1.13/batch70)
Fixes the core "viewer can't control the sharer even on desktop" gap. Three root
causes addressed:
- share.html DISCARDED every input-channel message (onmessage=()=>{}). It now
parses the viewer's mouse/keyboard events and forwards them to the desktop shell.
- The main desktop app had NO OS injector (it lived only in the separate agent).
Ported the nut-js injector (agent/input/inject.js) into desktop/input, wired an
inject IPC + injectInput bridge, HARD-gated behind a consent flag (rcArmed).
- /share runs in an iframe (no direct bridge access) → it postMessages input to
the top frame (home.html), which relays to the native bridge.
Consent + safety: the sharer sees an Allow/Deny prompt the first time the agent
interacts; while active a persistent "your screen is being controlled — Stop"
banner; instant revoke; auto-release on session end/teardown. Browser sharers stay
view-only (no OS injection possible). nut-js is an optionalDependency (N-API, ABI-
stable across Electron) — degrades to no-op if the native module is unavailable.
Windows-first; maps to the primary display.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,12 @@ contextBridge.exposeInMainWorld('bizConnectNative', Object.freeze({
|
||||
// Ask the shell to show native spelling suggestions for the word at page coords (x,y) — used to bring
|
||||
// up corrections on a LEFT click in the message box (not just right-click).
|
||||
spellSuggestAt: (x, y) => { try { ipcRenderer.send('spell-suggest', { x, y }); } catch (_) {} },
|
||||
// Remote control (screen the local user is sharing): whether OS injection is possible on this machine,
|
||||
// arm/disarm the consent gate, and forward a viewer's input event for injection. Injection only happens
|
||||
// while armed (the user granted control) — see main.js rcArmed.
|
||||
rcAvailable: () => { try { return !!ipcRenderer.sendSync('rc-available'); } catch (_) { return false; } },
|
||||
rcArm: (on) => { try { ipcRenderer.send('rc-arm', !!on); } catch (_) {} },
|
||||
rcInput: (evt) => { try { ipcRenderer.send('rc-input', evt); } catch (_) {} },
|
||||
// Manual "Check for updates" from Settings. Resolves {status:'available'|'current'|'dev'|'error', version?}.
|
||||
// On 'available' the shell downloads in the background and prompts to restart when ready.
|
||||
checkForUpdates: () => ipcRenderer.invoke('check-updates'),
|
||||
|
||||
Reference in New Issue
Block a user