From 20226c326945ad9dc524f6dcbfc1c1274befb652 Mon Sep 17 00:00:00 2001 From: Mo Date: Fri, 7 Oct 2022 14:30:07 -0500 Subject: [PATCH] fix(desktop): use different method to send messages across main and render without node integration in preload (#1769) --- .../app/javascripts/Main/UpdateManager.ts | 5 +- .../desktop/app/javascripts/Main/Window.ts | 1 + .../app/javascripts/Renderer/Preload.ts | 52 ++++++----------- .../app/javascripts/Renderer/Renderer.ts | 58 ++++++++----------- 4 files changed, 47 insertions(+), 69 deletions(-) diff --git a/packages/desktop/app/javascripts/Main/UpdateManager.ts b/packages/desktop/app/javascripts/Main/UpdateManager.ts index d5e04f029..fdd448745 100644 --- a/packages/desktop/app/javascripts/Main/UpdateManager.ts +++ b/packages/desktop/app/javascripts/Main/UpdateManager.ts @@ -5,6 +5,7 @@ import { autoUpdater } from 'electron-updater' import { action, autorun, computed, makeObservable, observable } from 'mobx' import { MessageType } from '../../../test/TestIpcMessage' import { AppState } from '../../AppState' +import { MessageToWebApp } from '../Shared/IpcMessages' import { BackupsManagerInterface } from './Backups/BackupsManagerInterface' import { StoreKeys } from './Store/StoreKeys' import { updates as str } from './Strings' @@ -113,12 +114,12 @@ export function setupUpdates(window: BrowserWindow, appState: AppState, backupsM setInterval(checkUpdateSafety, oneHour) autoUpdater.on('update-downloaded', (info: { version?: string }) => { - window.webContents.send('update-available', null) + window.webContents.send(MessageToWebApp.UpdateAvailable, null) updateState.autoUpdateHasBeenDownloaded(info.version || null) }) autoUpdater.on('error', logError) - autoUpdater.on('update-available', (info: { version?: string }) => { + autoUpdater.on(MessageToWebApp.UpdateAvailable, (info: { version?: string }) => { updateState.checkedForUpdate(info.version || null) if (updateState.enableAutoUpdate) { const canUpdate = checkUpdateSafety() diff --git a/packages/desktop/app/javascripts/Main/Window.ts b/packages/desktop/app/javascripts/Main/Window.ts index e4dd46b70..ca6fff845 100644 --- a/packages/desktop/app/javascripts/Main/Window.ts +++ b/packages/desktop/app/javascripts/Main/Window.ts @@ -166,6 +166,7 @@ async function createWindow(store: Store): Promise { spellcheck: true, nodeIntegration: isTesting(), contextIsolation: true, + sandbox: true, preload: Paths.preloadJs, }, }) diff --git a/packages/desktop/app/javascripts/Renderer/Preload.ts b/packages/desktop/app/javascripts/Renderer/Preload.ts index 94f70d8d9..b58dd3cba 100644 --- a/packages/desktop/app/javascripts/Renderer/Preload.ts +++ b/packages/desktop/app/javascripts/Renderer/Preload.ts @@ -1,42 +1,28 @@ +import { IpcRendererEvent } from 'electron/renderer' import { MessageToWebApp } from '../Shared/IpcMessages' const { ipcRenderer } = require('electron') -const path = require('path') -const rendererPath = path.join('file://', __dirname, '/renderer.js') const RemoteBridge = require('@electron/remote').getGlobal('RemoteBridge') const { contextBridge } = require('electron') +type MainEventCallback = (event: IpcRendererEvent, value: any) => void + process.once('loaded', function () { contextBridge.exposeInMainWorld('electronRemoteBridge', RemoteBridge.exposableValue) - listenForIpcEventsFromMainProcess() + contextBridge.exposeInMainWorld('electronMainEvents', { + handleUpdateAvailable: (callback: MainEventCallback) => ipcRenderer.on(MessageToWebApp.UpdateAvailable, callback), + + handlePerformAutomatedBackup: (callback: MainEventCallback) => + ipcRenderer.on(MessageToWebApp.PerformAutomatedBackup, callback), + + handleFinishedSavingBackup: (callback: MainEventCallback) => + ipcRenderer.on(MessageToWebApp.FinishedSavingBackup, callback), + + handleWindowBlurred: (callback: MainEventCallback) => ipcRenderer.on(MessageToWebApp.WindowBlurred, callback), + + handleWindowFocused: (callback: MainEventCallback) => ipcRenderer.on(MessageToWebApp.WindowFocused, callback), + + handleInstallComponentComplete: (callback: MainEventCallback) => + ipcRenderer.on(MessageToWebApp.InstallComponentComplete, callback), + }) }) - -function listenForIpcEventsFromMainProcess() { - const sendMessageToRenderProcess = (message: string, payload = {}) => { - window.postMessage(JSON.stringify({ message, data: payload }), rendererPath) - } - - ipcRenderer.on(MessageToWebApp.UpdateAvailable, function (_event, data) { - sendMessageToRenderProcess(MessageToWebApp.UpdateAvailable, data) - }) - - ipcRenderer.on(MessageToWebApp.PerformAutomatedBackup, function (_event, data) { - sendMessageToRenderProcess(MessageToWebApp.PerformAutomatedBackup, data) - }) - - ipcRenderer.on(MessageToWebApp.FinishedSavingBackup, function (_event, data) { - sendMessageToRenderProcess(MessageToWebApp.FinishedSavingBackup, data) - }) - - ipcRenderer.on(MessageToWebApp.WindowBlurred, function (_event, data) { - sendMessageToRenderProcess(MessageToWebApp.WindowBlurred, data) - }) - - ipcRenderer.on(MessageToWebApp.WindowFocused, function (_event, data) { - sendMessageToRenderProcess(MessageToWebApp.WindowFocused, data) - }) - - ipcRenderer.on(MessageToWebApp.InstallComponentComplete, function (_event, data) { - sendMessageToRenderProcess(MessageToWebApp.InstallComponentComplete, data) - }) -} diff --git a/packages/desktop/app/javascripts/Renderer/Renderer.ts b/packages/desktop/app/javascripts/Renderer/Renderer.ts index 849737694..2dcc91da7 100644 --- a/packages/desktop/app/javascripts/Renderer/Renderer.ts +++ b/packages/desktop/app/javascripts/Renderer/Renderer.ts @@ -1,6 +1,6 @@ import { DesktopClientRequiresWebMethods } from '@web/Application/Device/DesktopSnjsExports' import { StartApplication } from '@web/Application/Device/StartApplication' -import { MessageToWebApp } from '../Shared/IpcMessages' +import { IpcRendererEvent } from 'electron/renderer' import { CrossProcessBridge } from './CrossProcessBridge' import { DesktopDevice } from './DesktopDevice' @@ -23,6 +23,7 @@ declare global { purchaseUrl: string startApplication: StartApplication zip: any + electronMainEvents: any } } @@ -41,8 +42,6 @@ const loadAndStartApplication = async () => { window.device = await createDesktopDevice(remoteBridge) window.startApplication(DEFAULT_SYNC_SERVER, window.device, window.enableUnfinishedFeatures, WEBSOCKET_URL) - - listenForMessagesSentFromMainToPreloadToUs(window.device) } window.onload = () => { @@ -134,35 +133,26 @@ async function configureWindow(remoteBridge: CrossProcessBridge) { } } -function listenForMessagesSentFromMainToPreloadToUs(device: DesktopDevice) { - window.addEventListener('message', async (event) => { - // We don't have access to the full file path. - if (event.origin !== 'file://') { - return - } - let payload - try { - payload = JSON.parse(event.data) - } catch (e) { - // message doesn't belong to us - return - } - const receiver = window.webClient - const message = payload.message - const data = payload.data +window.electronMainEvents.handleUpdateAvailable(() => { + window.webClient.updateAvailable() +}) - if (message === MessageToWebApp.WindowBlurred) { - receiver.windowLostFocus() - } else if (message === MessageToWebApp.WindowFocused) { - receiver.windowGainedFocus() - } else if (message === MessageToWebApp.InstallComponentComplete) { - receiver.onComponentInstallationComplete(data.component, undefined) - } else if (message === MessageToWebApp.UpdateAvailable) { - receiver.updateAvailable() - } else if (message === MessageToWebApp.PerformAutomatedBackup) { - void device.downloadBackup() - } else if (message === MessageToWebApp.FinishedSavingBackup) { - receiver.didFinishBackup(data.success) - } - }) -} +window.electronMainEvents.handlePerformAutomatedBackup(() => { + void window.device.downloadBackup() +}) + +window.electronMainEvents.handleFinishedSavingBackup((_: IpcRendererEvent, data: any) => { + window.webClient.didFinishBackup(data.success) +}) + +window.electronMainEvents.handleWindowBlurred(() => { + window.webClient.windowLostFocus() +}) + +window.electronMainEvents.handleWindowFocused(() => { + window.webClient.windowGainedFocus() +}) + +window.electronMainEvents.handleInstallComponentComplete((_: IpcRendererEvent, data: any) => { + window.webClient.onComponentInstallationComplete(data.component, undefined) +})