diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2021-03-09 11:21:14 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2021-03-10 15:39:31 +0100 |
| commit | de735b7ced8bb1148a1f282d975745cfd9d13435 (patch) | |
| tree | dc74c80de7356f9bcfc58861a23896f3609b3f3d /gui/src/main | |
| parent | 9f8cb65cb0bfbb20793819aa73f12f48259b666a (diff) | |
| download | mullvadvpn-de735b7ced8bb1148a1f282d975745cfd9d13435.tar.xz mullvadvpn-de735b7ced8bb1148a1f282d975745cfd9d13435.zip | |
Return undefined if window or webview is destroyed
Diffstat (limited to 'gui/src/main')
| -rw-r--r-- | gui/src/main/index.ts | 54 | ||||
| -rw-r--r-- | gui/src/main/window-controller.ts | 58 |
2 files changed, 62 insertions, 50 deletions
diff --git a/gui/src/main/index.ts b/gui/src/main/index.ts index 45a21bf8f6..5d08689036 100644 --- a/gui/src/main/index.ts +++ b/gui/src/main/index.ts @@ -355,7 +355,7 @@ class ApplicationMain { // closing normally, even programmatically. Therefore re-enable the close button just before // quitting the app. // Github issue: https://github.com/electron/electron/issues/15008 - if (process.platform === 'darwin' && this.windowController) { + if (process.platform === 'darwin' && this.windowController?.window) { this.windowController.window.closable = true; } @@ -435,9 +435,9 @@ class ApplicationMain { }; private async initializeWindow() { - if (this.windowController && this.tray) { + if (this.windowController?.window && this.tray) { this.registerWindowListener(this.windowController); - this.addContextMenu(this.windowController.window); + this.addContextMenu(this.windowController); if (process.env.NODE_ENV === 'development') { await this.installDevTools(); @@ -466,18 +466,20 @@ class ApplicationMain { const filePath = path.resolve(path.join(__dirname, '../renderer/index.html')); try { if (process.env.NODE_ENV === 'development') { - await this.windowController?.window.loadURL( + await this.windowController.window.loadURL( 'http://localhost:8080/src/renderer/index.html', ); } else { - await this.windowController?.window.loadFile(filePath); + await this.windowController.window.loadFile(filePath); } } catch (error) { log.error(`Failed to load index file: ${error.message}`); } // disable pinch to zoom - consumePromise(this.windowController.webContents.setVisualZoomLevelLimits(1, 1)); + if (this.windowController.webContents) { + consumePromise(this.windowController.webContents.setVisualZoomLevelLimits(1, 1)); + } } } @@ -990,14 +992,14 @@ class ApplicationMain { } private registerWindowListener(windowController: WindowController) { - windowController.window.on('show', () => { + windowController.window?.on('show', () => { // cancel notifications when window appears this.notificationController.cancelPendingNotifications(); this.updateAccountData(); }); - windowController.window.on('hide', () => { + windowController.window?.on('hide', () => { // ensure notification guard is reset this.notificationController.resetTunnelStateAnnouncements(); }); @@ -1613,7 +1615,7 @@ class ApplicationMain { } } - private addContextMenu(window: BrowserWindow) { + private addContextMenu(windowController: WindowController) { const menuTemplate: Electron.MenuItemConstructorOptions[] = [ { role: 'cut' }, { role: 'copy' }, @@ -1623,15 +1625,15 @@ class ApplicationMain { ]; // add inspect element on right click menu - window.webContents.on( + windowController.window?.webContents.on( 'context-menu', (_e: Event, props: { x: number; y: number; isEditable: boolean }) => { const inspectTemplate = [ { label: 'Inspect element', click() { - window.webContents.openDevTools({ mode: 'detach' }); - window.webContents.inspectElement(props.x, props.y); + windowController.window?.webContents.openDevTools({ mode: 'detach' }); + windowController.window?.webContents.inspectElement(props.x, props.y); }, }, ]; @@ -1644,14 +1646,14 @@ class ApplicationMain { ...inspectTemplate, ]; - Menu.buildFromTemplate(inputMenu).popup({ window }); + Menu.buildFromTemplate(inputMenu).popup({ window: windowController.window }); } else { - Menu.buildFromTemplate(menuTemplate).popup({ window }); + Menu.buildFromTemplate(menuTemplate).popup({ window: windowController.window }); } } else if (process.env.NODE_ENV === 'development') { // display inspect element for all non-editable // elements when in development mode - Menu.buildFromTemplate(inspectTemplate).popup({ window }); + Menu.buildFromTemplate(inspectTemplate).popup({ window: windowController.window }); } }, ); @@ -1685,7 +1687,7 @@ class ApplicationMain { private installWindowsMenubarAppWindowHandlers(tray: Tray, windowController: WindowController) { if (!this.guiSettings.unpinnedWindow) { - windowController.window.on('blur', () => { + windowController.window?.on('blur', () => { // Detect if blur happened when user had a cursor above the tray icon. const trayBounds = tray.getBounds(); const cursorPos = screen.getCursorScreenPoint(); @@ -1709,14 +1711,18 @@ class ApplicationMain { const { NSEventMonitor, NSEventMask } = require('nseventmonitor'); const macEventMonitor = new NSEventMonitor(); const eventMask = NSEventMask.leftMouseDown | NSEventMask.rightMouseDown; - const window = windowController.window; - window.on('show', () => macEventMonitor.start(eventMask, () => windowController.hide())); - window.on('hide', () => macEventMonitor.stop()); - window.on('blur', () => { + windowController.window?.on('show', () => + macEventMonitor.start(eventMask, () => windowController.hide()), + ); + windowController.window?.on('hide', () => macEventMonitor.stop()); + windowController.window?.on('blur', () => { // Make sure to hide the menubar window when other program captures the focus. // But avoid doing that when dev tools capture the focus to make it possible to inspect the UI - if (window.isVisible() && !window.webContents.isDevToolsFocused()) { + if ( + windowController.window?.isVisible() && + !windowController.window?.webContents.isDevToolsFocused() + ) { windowController.hide(); } }); @@ -1725,7 +1731,7 @@ class ApplicationMain { private installWindowCloseHandler(windowController: WindowController) { if (this.guiSettings.unpinnedWindow) { - windowController.window.on('close', (closeEvent: Event) => { + windowController.window?.on('close', (closeEvent: Event) => { if (this.quitStage !== AppQuitStage.ready) { closeEvent.preventDefault(); windowController.hide(); @@ -1735,10 +1741,10 @@ class ApplicationMain { } private installGenericFocusHandlers(windowController: WindowController) { - windowController.window.on('focus', () => { + windowController.window?.on('focus', () => { IpcMainEventChannel.windowFocus.notify(windowController.webContents, true); }); - windowController.window.on('blur', () => { + windowController.window?.on('blur', () => { IpcMainEventChannel.windowFocus.notify(windowController.webContents, false); }); } diff --git a/gui/src/main/window-controller.ts b/gui/src/main/window-controller.ts index 69ae6acb02..450123d035 100644 --- a/gui/src/main/window-controller.ts +++ b/gui/src/main/window-controller.ts @@ -135,12 +135,12 @@ export default class WindowController { private windowPositioning: IWindowPositioning; private isWindowReady = false; - get window(): BrowserWindow { - return this.windowValue; + get window(): BrowserWindow | undefined { + return this.windowValue.isDestroyed() ? undefined : this.windowValue; } - get webContents(): WebContents { - return this.webContentsValue; + get webContents(): WebContents | undefined { + return this.webContentsValue.isDestroyed() ? undefined : this.webContentsValue; } constructor(windowValue: BrowserWindow, private tray: Tray, unpinnedWindow: boolean) { @@ -158,8 +158,8 @@ export default class WindowController { } public replaceWindow(window: BrowserWindow, unpinnedWindow: boolean) { - this.window.removeAllListeners(); - this.window.destroy(); + this.window?.removeAllListeners(); + this.window?.destroy(); this.windowValue = window; this.webContentsValue = window.webContents; @@ -181,11 +181,11 @@ export default class WindowController { } public hide() { - this.windowValue.hide(); + this.window?.hide(); } public toggle() { - if (this.windowValue.isVisible()) { + if (this.window?.isVisible()) { this.hide(); } else { this.show(); @@ -193,11 +193,11 @@ export default class WindowController { } public isVisible(): boolean { - return this.windowValue.isVisible(); + return this.window?.isVisible() ?? false; } private showImmediately() { - const window = this.windowValue; + const window = this.window; // When running with unpinned window on Windows there's a bug that causes the app to become // wider if opened from minimized if the updated position is set before the window is opened. @@ -207,8 +207,8 @@ export default class WindowController { process.platform === 'win32' && this.windowPositioning instanceof StandaloneWindowPositioning ) { - window.show(); - window.focus(); + window?.show(); + window?.focus(); this.updatePosition(); this.notifyUpdateWindowShape(); @@ -216,29 +216,35 @@ export default class WindowController { this.updatePosition(); this.notifyUpdateWindowShape(); - window.show(); - window.focus(); + window?.show(); + window?.focus(); } } private updatePosition() { - const { x, y } = this.windowPositioning.getPosition(this.windowValue); - this.windowValue.setPosition(x, y, false); + if (this.window) { + const { x, y } = this.windowPositioning.getPosition(this.window); + this.window.setPosition(x, y, false); + } } private notifyUpdateWindowShape() { - const shapeParameters = this.windowPositioning.getWindowShapeParameters(this.windowValue); + if (this.window) { + const shapeParameters = this.windowPositioning.getWindowShapeParameters(this.window); - IpcMainEventChannel.windowShape.notify(this.webContentsValue, shapeParameters); + IpcMainEventChannel.windowShape.notify(this.webContentsValue, shapeParameters); + } } // Installs display event handlers to update the window position on any changes in the display or // workarea dimensions. private installDisplayMetricsHandler() { - screen.addListener('display-metrics-changed', this.onDisplayMetricsChanged); - this.windowValue.once('closed', () => { - screen.removeListener('display-metrics-changed', this.onDisplayMetricsChanged); - }); + if (this.window) { + screen.addListener('display-metrics-changed', this.onDisplayMetricsChanged); + this.window.once('closed', () => { + screen.removeListener('display-metrics-changed', this.onDisplayMetricsChanged); + }); + } } private onDisplayMetricsChanged = ( @@ -246,7 +252,7 @@ export default class WindowController { _display: Display, changedMetrics: string[], ) => { - if (changedMetrics.includes('workArea') && this.windowValue.isVisible()) { + if (changedMetrics.includes('workArea') && this.window?.isVisible()) { this.updatePosition(); this.notifyUpdateWindowShape(); } @@ -260,11 +266,11 @@ export default class WindowController { }; private forceResizeWindow() { - this.windowValue.setSize(this.width, this.height); + this.window?.setSize(this.width, this.height); } private installWindowReadyHandlers() { - this.windowValue.once('ready-to-show', () => { + this.window?.once('ready-to-show', () => { this.isWindowReady = true; }); } @@ -273,7 +279,7 @@ export default class WindowController { if (this.isWindowReady) { closure(); } else { - this.windowValue.once('ready-to-show', () => { + this.window?.once('ready-to-show', () => { closure(); }); } |
