diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2022-10-17 17:21:55 +0200 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2022-10-17 17:21:55 +0200 |
| commit | 4f442798935846f3d55f541fe810ce2474e0dffd (patch) | |
| tree | 6f4a183ee1ef8ac151a271bb074e874e3c3538ff /gui/src | |
| parent | e8a328034d72c56db3a2202fa990d70b5e4ea6bd (diff) | |
| parent | 0e9745bcc3b2513e54aeeb7899156dca24b62f44 (diff) | |
| download | mullvadvpn-4f442798935846f3d55f541fe810ce2474e0dffd.tar.xz mullvadvpn-4f442798935846f3d55f541fe810ce2474e0dffd.zip | |
Merge branch 'update-to-electron-21'
Diffstat (limited to 'gui/src')
| -rw-r--r-- | gui/src/main/ipc-event-channel.ts | 44 | ||||
| -rw-r--r-- | gui/src/main/user-interface.ts | 4 | ||||
| -rw-r--r-- | gui/src/shared/ipc-helpers.ts | 29 |
3 files changed, 25 insertions, 52 deletions
diff --git a/gui/src/main/ipc-event-channel.ts b/gui/src/main/ipc-event-channel.ts index bae499910d..80fed8a034 100644 --- a/gui/src/main/ipc-event-channel.ts +++ b/gui/src/main/ipc-event-channel.ts @@ -1,48 +1,12 @@ import { ipcMain, WebContents } from 'electron'; -import { createIpcMain, IpcMain, Notifier, Schema } from '../shared/ipc-helpers'; +import { createIpcMain } from '../shared/ipc-helpers'; import { ipcSchema } from '../shared/ipc-schema'; -// Type where the notify functions have been replaced with either `undefined` if no `WebContents` is -// available, or with the function curried with the `WebContents`. -type IpcMainBootstrappedWithWebContents<S extends Schema> = { - [GK in keyof IpcMain<S>]: { - [CK in keyof IpcMain<S>[GK]]: IpcMain<S>[GK][CK] extends Notifier<infer T> - ? undefined | ((arg: T) => ReturnType<IpcMain<S>[GK][CK]>) - : IpcMain<S>[GK][CK]; - }; -}; - -const ipcMainFromSchema = createIpcMain(ipcSchema, ipcMain); // eslint-disable-next-line @typescript-eslint/naming-convention -export let IpcMainEventChannel = bootstrapIpcMainWithWebContents(); - -// Curries all notify functions with `WebContents` if it's not `undefined`. If it is `undefined` -// then the whole function will be replaced with `undefined`. -function bootstrapIpcMainWithWebContents( - webContents?: WebContents, -): IpcMainBootstrappedWithWebContents<typeof ipcSchema> { - return Object.fromEntries( - Object.entries(ipcMainFromSchema).map(([groupKey, group]) => { - const newGroup = Object.fromEntries( - Object.entries(group).map(([callKey, call]) => { - if (callKey.startsWith('notify')) { - const newCall = webContents - ? (arg: Parameters<typeof call>[1]) => call(webContents, arg) - : undefined; - return [callKey, newCall]; - } else { - return [callKey, call]; - } - }), - ); - - return [groupKey, newGroup]; - }), - ) as IpcMainBootstrappedWithWebContents<typeof ipcSchema>; -} +export let IpcMainEventChannel = createIpcMain(ipcSchema, ipcMain, undefined); // Change the `IpcMainEventChannel` for a new one with a new `WebContents`. -export function changeIpcWebContents(webContents?: WebContents) { - IpcMainEventChannel = bootstrapIpcMainWithWebContents(webContents); +export function changeIpcWebContents(webContents: WebContents | undefined) { + IpcMainEventChannel = createIpcMain(ipcSchema, ipcMain, webContents); } diff --git a/gui/src/main/user-interface.ts b/gui/src/main/user-interface.ts index 4d56d95eac..ae9e9c8592 100644 --- a/gui/src/main/user-interface.ts +++ b/gui/src/main/user-interface.ts @@ -48,7 +48,11 @@ export default class UserInterface implements WindowControllerDelegate { private navigationResetDisabled: boolean, ) { const window = this.createWindow(); + changeIpcWebContents(window.webContents); + window.webContents.on('destroyed', () => { + changeIpcWebContents(undefined); + }); this.windowController = this.createWindowController(window); this.tray = this.createTray(); diff --git a/gui/src/shared/ipc-helpers.ts b/gui/src/shared/ipc-helpers.ts index fda5c2d3b5..27ad17e22a 100644 --- a/gui/src/shared/ipc-helpers.ts +++ b/gui/src/shared/ipc-helpers.ts @@ -5,14 +5,12 @@ import { capitalize } from './string-helpers'; type Handler<T, R> = (callback: (arg: T) => R) => void; type Sender<T, R> = (arg: T) => R; -// Remove export after upgrading to Electron 21+ and removal of code to curry notifiers with -// webContents in ../main/ipc-event-channel.ts. -export type Notifier<T> = (webContents: WebContents | undefined, arg: T) => void; +type Notifier<T> = ((arg: T) => void) | undefined; type Listener<T> = (callback: (arg: T) => void) => void; interface MainToRenderer<T> { direction: 'main-to-renderer'; - send: (event: string, ipcMain: EIpcMain) => Notifier<T>; + send: (event: string, webContents: WebContents) => Notifier<T>; receive: (event: string, ipcRenderer: EIpcRenderer) => Listener<T>; } @@ -64,15 +62,22 @@ export type IpcRenderer<S extends Schema> = { }; // Preforms the transformation of the main event channel in accordance with the above types. -export function createIpcMain<S extends Schema>(schema: S, ipcMain: EIpcMain): IpcMain<S> { +export function createIpcMain<S extends Schema>( + schema: S, + ipcMain: EIpcMain, + webContents: WebContents | undefined, +): IpcMain<S> { return createIpc(schema, (event, key, spec) => { const capitalizedKey = capitalize(key); const newKey = spec.direction === 'main-to-renderer' ? `notify${capitalizedKey}` : `handle${capitalizedKey}`; - const newValue = - spec.direction === 'main-to-renderer' - ? spec.send(event, ipcMain) - : spec.receive(event, ipcMain); + + let newValue; + if (spec.direction === 'main-to-renderer') { + newValue = webContents ? spec.send(event, webContents) : undefined; + } else { + newValue = spec.receive(event, ipcMain); + } return [newKey, newValue]; }); @@ -154,9 +159,9 @@ export function notifyRenderer<T>(): MainToRenderer<T> { }; } -function notifyRendererImpl<T>(event: string, _ipcMain: EIpcMain): Notifier<T> { - return (webContents, value) => { - if (webContents === undefined) { +function notifyRendererImpl<T>(event: string, webContents: WebContents): Notifier<T> { + return (value) => { + if (webContents === undefined || webContents.isDestroyed() || webContents.isCrashed()) { log.error(`sender(${event}): webContents is already destroyed!`); } else { webContents.send(event, value); |
