Repository navigation
4.1 Main Process and Window Lifecycle
Relevant source files
The following files were used as context for generating this wiki page:
This page details the Electron main process implementation within VariantScope, focusing on electron/main.js and electron/menu.js. It covers application initialization, user-data path configuration, custom protocol handling for the renderer bundle, security sandboxing, permission controls, and native menu accelerators communicating via custom DOM events.
The main process entry point (electron/main.js) manages the lifecycle of the desktop application. Upon launch, it configures runtime paths, optional background operational flags, and privileged custom schemes before the Electron framework finishes initialization.
Key bootstrapping mechanisms include:
-
User Data Paths: Tests or custom environments can override the default user data directory via the
VARIANTSCOPE_USER_DATAenvironment variable usingapp.setPath('userData', ...)electron/main.js:24-25. -
Background Mode: Automated headless test runs can enable
VARIANTSCOPE_BACKGROUND=1. On macOS, this sets the activation policy to anaccessoryrole, hiding the Dock icon and preventing the application from taking focus during tests electron/main.js:27-31. -
Custom Secure Scheme: The app registers
app://as a standard, secure protocol with fetch API support usingprotocol.registerSchemesAsPrivilegedelectron/main.js:43-47. This provides a stable origin and real Content Security Policy (CSP) headers for the bundled renderer UI.
graph TD
Start["Electron App Launch"] --> CheckEnv["Check process.env"]
CheckEnv --> SetUserData["app.setPath('userData') electron/main.js"]
CheckEnv --> CheckBg["Check VARIANTSCOPE_BACKGROUND"]
CheckBg -->|True & macOS| SetAcc["app.setActivationPolicy('accessory') electron/main.js"]
CheckBg -->|False / Other| RegScheme["protocol.registerSchemesAsPrivileged electron/main.js"]
SetUserData --> RegScheme
RegScheme --> Ready["app.whenReady()"]
Sources: electron/main.js:24-47
Sources: electron/main.js:24-47
Once the application is ready, BrowserWindow instances are instantiated. Depending on whether the environment is running in development mode (VARIANTSCOPE_DEV_URL) or production packaging, the renderer target changes.
-
Production / Bundled Mode: Requests are intercepted by
handleAppProtocol, which reads files fromdist/electron-rendererover theapp://scheme, mapping paths safely and rejecting directory traversal attempts outsideRENDERER_DIRelectron/main.js:53-68. -
Development Mode: If
VARIANTSCOPE_DEV_URLis provided, the window loads the Vite development server directly electron/main.js:15, andinstallDevCspinjects development CSP headers into incoming response headers viasession.defaultSession.webRequest.onHeadersReceivedelectron/main.js:70-78.
graph TD
Sub["Window Creation & URL Resolution"] --> DevCheck{{"DEV_URL defined?"}}
DevCheck -->|Yes| LoadDev["win.loadURL(DEV_URL)"]
DevCheck -->|No| RegisterProto["protocol.handle('app', handleAppProtocol) electron/main.js"]
RegisterProto --> LoadApp["win.loadURL('app://local/index.html')"]
subgraph "handleAppProtocol electron/main.js"
LoadApp --> ParsePath["Parse pathname and decode URI"]
ParsePath --> ValidatePath["Verify path stays within RENDERER_DIR"]
ValidatePath -->|Escape| Fail["Return 403 Forbidden"]
ValidatePath -->|Safe| ReadFile["fs/promises.readFile()"]
ReadFile --> ReturnResp["Return Response with Content-Type & CSP"]
end
Sources: electron/main.js:15-22, electron/main.js:53-68
Sources: electron/main.js:15-22, electron/main.js:53-68
electron/main.js enforces strict security boundaries to prevent unauthorized navigation, remote code execution, and permission escalation:
-
Permission Management:
denyPermissionsblocks all browser permission requests (geolocation, camera, notifications) exceptfullscreenrequests originating from the trusted application origin, which are required by the 3D viewer component (viewer3d.js) electron/main.js:80-87. -
WebContents Locking:
lockDownWebContentsintercepts navigation and window opening attempts (will-navigate,will-redirect,setWindowOpenHandler). External links must satisfyisAllowedExternalLinkbefore opening in the host system browser viashell.openExternalelectron/main.js:89-107. Webview attachments are unconditionally blocked electron/main.js:106. -
IPC Sender Verification: IPC handlers check message origins against
TRUSTED_ORIGINusingisTrustedSenderto ensure messages originate from valid renderer frames electron/main.js:109-116.
Sources: electron/main.js:80-116
The native application menu is defined and installed in electron/menu.js via installMenu. It configures standard roles, platform-specific menus, and keyboard accelerators such as CmdOrCtrl+E (Export CSV), CmdOrCtrl+K (Focus Search), and CmdOrCtrl+D (Toggle Dark Mode) electron/menu.js:13-91.
When a user interacts with application menus, actions are dispatched to the renderer window through webContents.executeJavaScript by firing a custom DOM event (vs:menu) containing a fixed action string electron/menu.js:17-23.
graph TD
UserAction["User clicks menu item / Accelerator"] --> MenuClick["Menu item click handler electron/menu.js"]
MenuClick --> SendCheck{{"Has active BrowserWindow?"}}
SendCheck -->|No| Exit["Return"]
SendCheck -->|Yes| ExecJS["win.webContents.executeJavaScript electron/menu.js"]
ExecJS --> DispatchEvent["window.dispatchEvent(new CustomEvent('vs:menu', ...))"]
DispatchEvent --> RendererProcess["Renderer processes action (e.g. export-csv, focus-search, toggle-theme)"]
Sources: electron/menu.js:13-91
Sources: electron/menu.js:13-91
Content imported from DeepWiki.