# Draw.io Desktop electron.js Main Process File Structure and IPC Handlers Explained

> Explore the electron.js main process file structure in Draw.io Desktop. Understand key IPC handlers bridging renderer process and native OS features.

- Repository: [draw.io/drawio-desktop](https://github.com/jgraph/drawio-desktop)
- Tags: internals
- Published: 2026-03-05

---

**The [`src/main/electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron.js) file serves as the entry point for the Draw.io Desktop Electron application, organizing imports, security policies, window management, and inter-process communication through a structured series of IPC handlers that bridge the renderer process and native OS capabilities.**

The `jgraph/drawio-desktop` repository bundles the popular draw.io diagram editor as a cross-platform desktop application. Understanding the **electron.js main process file structure** is essential for developers extending the application or debugging its native behavior, as this file orchestrates everything from window creation to export pipelines and auto-updates according to the source code in the `dev` branch.

## Overview of the Main Process Architecture

The main process file follows a layered architecture that prioritizes security and modularity. At approximately 1,500+ lines, [`src/main/electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron.js) (viewable on GitHub at [[`src/main/electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron.js)](https://github.com/jgraph/drawio-desktop/blob/dev/src/main/electron.js)) divides functionality into distinct regions: global constants and imports, security helpers, window factory functions, IPC handler registrations, the export pipeline, and application lifecycle management.

## File Structure and Organization

### Imports and Global Configuration

The first 21 lines establish the runtime environment by loading Node.js modules, Electron APIs (`app`, `BrowserWindow`, `ipcMain`, `session`), and third-party dependencies including `electron-log`, `commander`, `electron-updater`, `@cantoo/pdf-lib`, and `electron-store` (lines 1-21). This section defines critical path constants such as `__dirname`, `codeDir`, and `appBaseDir` that anchor the application relative to the bundled draw.io submodule.

Following imports, the code initializes an `electron-store` instance and evaluates update flags including `disableUpdate` and `silentUpdate`, which determine whether the auto-updater runs silently or prompts the user (lines 22-41).

### Security Helpers and Window Factory

Three essential functions located in the helper section (lines 36-66) enforce security and window integrity:

- **`validateSender(frame)`** – Guarantees that IPC messages originate exclusively from the bundled draw.io code by verifying the sender URL against `codeUrl`.
- **`isWithinDisplayBounds(pos)`** – Validates that a saved window position actually exists on a connected display before restoration.
- **`createWindow(opt)`** – Builds a `BrowserWindow` with hardened security flags, restores previous size/position from the store, injects the preload script at [`src/main/electron-preload.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron-preload.js), and registers per-window IPC listeners.

## Key IPC Handlers in electron.js

The file registers two categories of IPC channels: per-window handlers created inside `createWindow`, and global handlers attached directly to `ipcMain` outside any window context.

### Per-Window IPC Channels

Inside `createWindow()` (around lines 44-53), the main process attaches listeners specific to each browser instance:

- **`openDevTools`** – Opens Chrome DevTools on demand when the renderer sends a debug request.
- **`isModified-result`** – Receives the answer to a "has the document changed?" query from the renderer. The handler shows a save modal if needed, deletes draft files, or forces window closure based on the `isModified` boolean and `draftPath` provided.

### Global Application IPC Channels

Outside the window factory, the file registers global channels (approximately lines 106-120) that respond to application-wide shortcuts and menu actions:

- **`newfile`** – Creates a brand-new window with optional dimension parameters.
- **`toggleSpellCheck`**, **`toggleStoreBkp`**, **`toggleGoogleFonts`**, **`toggleFullscreen`** – Toggle boolean user settings persisted in `electron-store`.
- **`checkForUpdates`** – Manually triggers `autoUpdater.checkForUpdates()`.
- **`zoomIn`**, **`zoomOut`**, **`resetZoom`** – UI-level zoom controls wired to the application menu.

### The Export Pipeline (exportDiagram)

The most complex IPC handler is the **export pipeline** (starting at line 378 and spanning to line 754). When the renderer sends an `export` event, `exportDiagram` executes the following workflow:

1. Creates an off-screen `BrowserWindow` invisible to the user.
2. Loads [`export3.html`](https://github.com/jgraph/drawio-desktop/blob/main/export3.html) from the bundled drawio submodule ([`drawio/src/main/webapp/export3.html`](https://github.com/jgraph/drawio-desktop/blob/main/drawio/src/main/webapp/export3.html)).
3. Listens for **`render-finished`** from the off-screen renderer, indicating the diagram has rasterized.
4. Sends **`render`** to the off-screen window with export arguments (format, width, height, XML data).
5. Handles callbacks **`export-success`**, **`export-error`**, **`svg-data`**, **`xml-data`**, and **`export-finalize`** to coordinate PDF merging (via `mergePdfs` using `@cantoo/pdf-lib`), PNG metadata injection (via `writePngWithText`), DPI settings, and base64 encoding.

## Security Implementation

Security hardening begins before any window loads. The `app.whenReady()` block (lines 671-752) installs a strict Content Security Policy via `session.defaultSession.webRequest.onHeadersReceived` and registers a `file://` request filter.

The **navigation guard** (lines 724-796) blocks all `will-navigate` events and disallows external `webview` creation. The `setWindowOpenHandler` only permits `about:blank` or external URLs opened via `shell.openExternal`, preventing unwanted redirects from the draw.io web codebase.

## Code Examples for Renderer Communication

Below are minimal snippets that a renderer process uses to interact with the main-process IPC channels defined in [`electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/electron.js).

### Open DevTools

```javascript
// In a renderer script (via the contextBridge API)
window.electronAPI.request('openDevTools');

```

*Handled in `createWindow()` → `ipcMain.on('openDevTools', …)` (lines 44-53).*

### Check Modified Document Status

```javascript
const uid = crypto.randomUUID();
ipcRenderer.send('isModified-result', { 
    uniqueId: uid, 
    isModified: true, 
    draftPath: '/tmp/foo.dtmp' 
});

```

The main process validates the sender via `validateSender(frame)` before processing the modification state.

### Export Diagram to PNG (Base64)

```javascript
ipcRenderer.send('export', {
    format: 'png',
    w: 800,
    h: 600,
    base64: '1',
    embedXml: '1',
    xml: '<mxGraphModel>…</mxGraphModel>'
});

ipcRenderer.once('export-success', (e, data) => {
    // data is a base64 PNG string
    const img = document.createElement('img');
    img.src = `data:image/png;base64,${data}`;
    document.body.append(img);
});

```

The `exportDiagram` function (line 378) coordinates this operation through the off-screen window pipeline.

### Toggle Spell Check Setting

```javascript
ipcRenderer.send('toggleSpellCheck');

```

This triggers the handler at approximately line 885, which persists the new boolean value to `electron-store`.

### Manual Update Check

```javascript
ipcRenderer.send('checkForUpdates');

```

The handler at line 1002 invokes `autoUpdater.checkForUpdates()`, displaying a progress bar via `electron-progressbar` unless running in `silentUpdate` mode (lines 818-874).

## Summary

- **[`src/main/electron.js`](https://github.com/jgraph/drawio-desktop/blob/main/src/main/electron.js)** is the single entry point that bootstraps the Draw.io Desktop application, initializes security policies, and manages the window lifecycle.
- **Security-first design** mandates that all IPC messages pass through `validateSender()` and that navigation is blocked via `webRequest` filters and `setWindowOpenHandler`.
- **Two-tier IPC architecture** separates per-window channels (like `openDevTools`) from global channels (like `newfile` and `toggleSpellCheck`).
- **Export pipeline** uses an off-screen `BrowserWindow` loading [`export3.html`](https://github.com/jgraph/drawio-desktop/blob/main/export3.html) to rasterize diagrams, handling PNG metadata injection and PDF merging through dedicated helper functions (`writePngWithText`, `mergePdfs`) at lines 1445-1527.
- **Auto-update logic** respects the `disableUpdate` and `silentUpdate` flags established early in the file (lines 22-41) before wiring the `checkForUpdates` IPC handler.

## Frequently Asked Questions

### How does electron.js verify that IPC messages come from legitimate renderer processes?

The file implements a `validateSender(frame)` helper function that checks the `senderFrame` URL against the `codeUrl` constant (pointing to the bundled draw.io source). If the message originates from any other origin, the handler returns early, preventing malicious scripts from invoking main-process capabilities. This validation runs before processing sensitive channels like `isModified-result` or `export`.

### What is the purpose of the exportDiagram function and how does it handle different file formats?

`exportDiagram` (starting at line 378) creates a hidden `BrowserWindow`, loads [`export3.html`](https://github.com/jgraph/drawio-desktop/blob/main/export3.html), and establishes a coordination protocol with the off-screen renderer. It sends a `render` event with export parameters, then waits for `render-finished`. Depending on the requested format, it processes `svg-data`, `xml-data`, or binary buffers, injects DPI metadata into PNGs via `writePngWithText`, and merges multi-page PDFs via `mergePdfs` using `@cantoo/pdf-lib`.

### Where are user preferences like spell check and backup settings stored?

Toggle handlers such as `toggleSpellCheck`, `toggleStoreBkp`, and `toggleGoogleFonts` modify an `electron-store` instance initialized near line 22. These settings persist across application restarts and are accessed by both the main process (to configure window behavior) and indirectly by the renderer through IPC queries.

### How does the application prevent navigation to external URLs or unauthorized content?

The security block (lines 724-796) registers `session.defaultSession.webRequest.onHeadersReceived` to inject a strict CSP, blocks all `will-navigate` events on `web-contents-created`, and sets a `setWindowOpenHandler` that only allows `about:blank` or explicitly allowed URLs opened via `shell.openExternal`. This ensures the draw.io web app cannot be redirected to malicious sites or open unapproved windows.