First commit on the local Gitea server, made after moving the tree off the Windows machine. Build outputs, node_modules and the AI models stay out (see .gitignore); everything the installer build needs is tracked. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
31 lines
1.4 KiB
JavaScript
31 lines
1.4 KiB
JavaScript
const { contextBridge, ipcRenderer } = require('electron');
|
|
|
|
// Strict channel allow-lists. Only the channels the renderer actually uses are forwarded,
|
|
// so injected/XSS content cannot reach arbitrary main-process IPC handlers (e.g. read-file).
|
|
const INVOKE_CHANNELS = ['show-about', 'close-app'];
|
|
// mirror:frame-request/-response: the phone remote's live mirror. Main asks the renderer for a JPEG
|
|
// of the stage screen (captured renderer-side via getDisplayMedia, far faster than capturePage) and
|
|
// the renderer answers with the encoded bytes.
|
|
const RECEIVE_CHANNELS = ['server-log', 'splash:update', 'control:perform', 'mirror:frame-request'];
|
|
const SEND_CHANNELS = ['mirror:frame-response'];
|
|
|
|
contextBridge.exposeInMainWorld('electron', {
|
|
ipcRenderer: {
|
|
invoke: (channel, ...args) => {
|
|
if (INVOKE_CHANNELS.includes(channel)) return ipcRenderer.invoke(channel, ...args);
|
|
return Promise.reject(new Error(`Blocked IPC invoke on disallowed channel: ${channel}`));
|
|
},
|
|
on: (channel, listener) => {
|
|
if (RECEIVE_CHANNELS.includes(channel)) ipcRenderer.on(channel, listener);
|
|
},
|
|
removeListener: (channel, listener) => {
|
|
if (RECEIVE_CHANNELS.includes(channel)) ipcRenderer.removeListener(channel, listener);
|
|
},
|
|
send: (channel, ...args) => {
|
|
if (SEND_CHANNELS.includes(channel)) ipcRenderer.send(channel, ...args);
|
|
}
|
|
}
|
|
});
|
|
|
|
|