Skip to content

WindowManager

Defined in: main/WindowManager.ts:181

Main process window manager. Renderer calls RegisterWindow(id, props) + window.open(url, id), then this class intercepts the new window via setWindowOpenHandler / did-create-window and wraps it.

Security model:

  • Iframe enforcement (main-frame-only) is handled by the generated IPC AppOrigin validator — it runs before these handlers at the IPC layer.
  • Parent renderer origin is validated here via allowedOrigins config.
  • Per-WebContents ownership: a renderer can only mutate windows it created. UnregisterWindow/UpdateWindow/DestroyWindow/WindowAction check that the caller’s WebContents matches the one that registered the window.

new WindowManager(config?): WindowManager

Defined in: main/WindowManager.ts:259

WindowManagerConfig = {}

WindowManager

cancelQuit(): void

Defined in: main/WindowManager.ts:929

Re-arm every managed window’s close veto after a cancelled quit.

setupWindowManager() calls this automatically when before-quit was vetoed by another listener. Exposed for manual flows that mirror that cancellation (e.g., a custom updater that may abort).

void


destroy(): void

Defined in: main/WindowManager.ts:935

void


getAllWindows(): WindowInstance[]

Defined in: main/WindowManager.ts:872

WindowInstance[]


getWindow(id): WindowInstance | undefined

Defined in: main/WindowManager.ts:868

string

WindowInstance | undefined


getWindowState(id): WindowState | null

Defined in: main/WindowManager.ts:876

string

WindowState | null


owns(win): boolean

Defined in: main/WindowManager.ts:887

O(1) check: is this BrowserWindow managed by this WindowManager?

Use this in browser-window-focus / -blur / will-navigate listeners instead of scanning getAllWindows().some(w => w.window === win) per event.

BrowserWindow

boolean


prepareForQuit(): void

Defined in: main/WindowManager.ts:916

Disarm every managed window’s close veto so an app quit can drain.

hideOnClose pool windows event.preventDefault() their own close. app.quit() and autoUpdater.quitAndInstall() close every BrowserWindow and wait for the count to hit zero — a window that vetoes its own close stalls the drain forever; before-quit / will-quit never fire and the app becomes a zombie.

Wired automatically via app.on("before-quit") by setupWindowManager (with auto-cancelQuit if another listener vetoes the quit). On Windows, the per-window session-end event is also handled inside WindowInstance.

Call it manually from your own quit-adjacent listeners when the quit signal does NOT route through Electron’s app — most commonly electron-updater’s autoUpdater.on("before-quit-for-update"), which fires on its own emitter, not Electron’s:

autoUpdater.on("before-quit-for-update", () => {
getWindowManager()?.prepareForQuit();
});

void


setupForWindow(target, options?): void

Defined in: main/WindowManager.ts:357

Attach IPC handling and window.open interception to a WebContents. Works with BrowserWindow, WebContentsView, or any object with a webContents property.

WebContents | BrowserWindow | { webContents: WebContents; }

SetupOptions

void

// BrowserWindow
manager.setupForWindow(mainWindow);
// WebContentsView (e.g., when the renderer is in a view, not the BrowserWindow itself)
manager.setupForWindow(mainView);
// With fallback handler for non-library window.open calls
manager.setupForWindow(mainView, {
fallbackWindowOpenHandler: ({ url }) => {
if (isExternalURL(url)) { shell.openExternal(url); return { action: "deny" }; }
return { action: "allow" };
},
});