From cfe761a03fb8b6bb751111f7f4d4daa31f999cc9 Mon Sep 17 00:00:00 2001 From: Rafael Araujo Lehmkuhl Date: Fri, 22 Nov 2024 13:26:42 -0300 Subject: [PATCH 1/2] electron: Isolate main and renderer processes Turn on security and isolation features and add a preload script. --- electron/main.ts | 7 +++---- electron/preload.ts | 0 vite.config.ts | 36 +++++++++++++++++++++++------------- 3 files changed, 26 insertions(+), 17 deletions(-) create mode 100644 electron/preload.ts diff --git a/electron/main.ts b/electron/main.ts index 0454c4917..b560ea0f6 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -15,10 +15,9 @@ function createWindow(): void { mainWindow = new BrowserWindow({ icon: join(ROOT_PATH.dist, 'pwa-512x512.png'), webPreferences: { - webSecurity: false, - contextIsolation: false, - nodeIntegration: true, - allowRunningInsecureContent: true, + preload: join(ROOT_PATH.dist, 'electron/preload.js'), + contextIsolation: true, + nodeIntegration: false, }, width, height, diff --git a/electron/preload.ts b/electron/preload.ts new file mode 100644 index 000000000..e69de29bb diff --git a/vite.config.ts b/vite.config.ts index 7def5da23..3bbdf9ef0 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -14,22 +14,32 @@ const isBuilding = process.argv.includes('build') export default defineConfig({ plugins: [ (isElectron || isBuilding) && - electron({ - entry: 'electron/main.ts', - vite: { - build: { - outDir: 'dist/electron', + electron([ + { + entry: 'electron/main.ts', + vite: { + build: { + outDir: 'dist/electron', + }, + }, + onstart: () => { + // @ts-ignore: process.electronApp exists in vite-plugin-electron but not in the types + if (process.electronApp) { + // @ts-ignore: process.electronApp.pid exists in vite-plugin-electron but not in the types + treeKillSync(process.electronApp.pid) + } + startup() }, }, - onstart: () => { - // @ts-ignore: process.electronApp exists in vite-plugin-electron but not in the types - if (process.electronApp) { - // @ts-ignore: process.electronApp.pid exists in vite-plugin-electron but not in the types - treeKillSync(process.electronApp.pid) - } - startup() + { + entry: 'electron/preload.ts', + vite: { + build: { + outDir: 'dist/electron', + }, + }, }, - }), + ]), vue(), vuetify({ autoImport: true, From 7044a12983dae6f66416cb28e39d6fa4f8dc8578 Mon Sep 17 00:00:00 2001 From: Rafael Araujo Lehmkuhl Date: Fri, 22 Nov 2024 13:26:42 -0300 Subject: [PATCH 2/2] general: Add vehicle discovery system (electron-only) --- electron/main.ts | 4 + electron/preload.ts | 5 + electron/services/network.ts | 39 ++++++ src/App.vue | 18 ++- src/components/InteractionDialog.vue | 2 +- src/components/VehicleDiscoveryDialog.vue | 150 ++++++++++++++++++++++ src/libs/cosmos.ts | 10 ++ src/libs/electron/vehicle-discovery.ts | 127 ++++++++++++++++++ src/views/ConfigurationGeneralView.vue | 23 +++- 9 files changed, 369 insertions(+), 9 deletions(-) create mode 100644 electron/services/network.ts create mode 100644 src/components/VehicleDiscoveryDialog.vue create mode 100644 src/libs/electron/vehicle-discovery.ts diff --git a/electron/main.ts b/electron/main.ts index b560ea0f6..abe2a48d2 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -1,6 +1,8 @@ import { app, BrowserWindow, protocol, screen } from 'electron' import { join } from 'path' +import { setupNetworkService } from './services/network' + export const ROOT_PATH = { dist: join(__dirname, '..'), } @@ -59,6 +61,8 @@ protocol.registerSchemesAsPrivileged([ }, ]) +setupNetworkService() + app.whenReady().then(createWindow) app.on('before-quit', () => { diff --git a/electron/preload.ts b/electron/preload.ts index e69de29bb..bfdd3fe8c 100644 --- a/electron/preload.ts +++ b/electron/preload.ts @@ -0,0 +1,5 @@ +import { contextBridge, ipcRenderer } from 'electron' + +contextBridge.exposeInMainWorld('electronAPI', { + getNetworkInfo: () => ipcRenderer.invoke('get-network-info'), +}) diff --git a/electron/services/network.ts b/electron/services/network.ts new file mode 100644 index 000000000..991b0f60f --- /dev/null +++ b/electron/services/network.ts @@ -0,0 +1,39 @@ +import { ipcMain } from 'electron' +import { networkInterfaces } from 'os' + +/** + * Information about the network + */ +interface NetworkInfo { + /** + * The subnet of the local machine + */ + subnet: string +} + +/** + * Get the network information + * @returns {NetworkInfo} The network information + */ +const getNetworkInfo = (): NetworkInfo => { + const nets = networkInterfaces() + + for (const name of Object.keys(nets)) { + for (const net of nets[name] ?? []) { + // Skip over non-IPv4 and internal addresses + if (net.family === 'IPv4' && !net.internal) { + // Return the subnet (e.g., if IP is 192.168.1.5, return 192.168.1) + return { subnet: net.address.split('.').slice(0, 3).join('.') } + } + } + } + + throw new Error('No network interface found.') +} + +/** + * Setup the network service + */ +export const setupNetworkService = (): void => { + ipcMain.handle('get-network-info', getNetworkInfo) +} diff --git a/src/App.vue b/src/App.vue index fc19580ca..94af043d2 100644 --- a/src/App.vue +++ b/src/App.vue @@ -315,15 +315,17 @@ +