fix(desktop): use different method to send messages across main and render without node integration in preload (#1769)

This commit is contained in:
Mo
2022-10-07 14:30:07 -05:00
committed by GitHub
parent a1352d9f65
commit 20226c3269
4 changed files with 47 additions and 69 deletions

View File

@@ -5,6 +5,7 @@ import { autoUpdater } from 'electron-updater'
import { action, autorun, computed, makeObservable, observable } from 'mobx' import { action, autorun, computed, makeObservable, observable } from 'mobx'
import { MessageType } from '../../../test/TestIpcMessage' import { MessageType } from '../../../test/TestIpcMessage'
import { AppState } from '../../AppState' import { AppState } from '../../AppState'
import { MessageToWebApp } from '../Shared/IpcMessages'
import { BackupsManagerInterface } from './Backups/BackupsManagerInterface' import { BackupsManagerInterface } from './Backups/BackupsManagerInterface'
import { StoreKeys } from './Store/StoreKeys' import { StoreKeys } from './Store/StoreKeys'
import { updates as str } from './Strings' import { updates as str } from './Strings'
@@ -113,12 +114,12 @@ export function setupUpdates(window: BrowserWindow, appState: AppState, backupsM
setInterval(checkUpdateSafety, oneHour) setInterval(checkUpdateSafety, oneHour)
autoUpdater.on('update-downloaded', (info: { version?: string }) => { autoUpdater.on('update-downloaded', (info: { version?: string }) => {
window.webContents.send('update-available', null) window.webContents.send(MessageToWebApp.UpdateAvailable, null)
updateState.autoUpdateHasBeenDownloaded(info.version || null) updateState.autoUpdateHasBeenDownloaded(info.version || null)
}) })
autoUpdater.on('error', logError) autoUpdater.on('error', logError)
autoUpdater.on('update-available', (info: { version?: string }) => { autoUpdater.on(MessageToWebApp.UpdateAvailable, (info: { version?: string }) => {
updateState.checkedForUpdate(info.version || null) updateState.checkedForUpdate(info.version || null)
if (updateState.enableAutoUpdate) { if (updateState.enableAutoUpdate) {
const canUpdate = checkUpdateSafety() const canUpdate = checkUpdateSafety()

View File

@@ -166,6 +166,7 @@ async function createWindow(store: Store): Promise<Electron.BrowserWindow> {
spellcheck: true, spellcheck: true,
nodeIntegration: isTesting(), nodeIntegration: isTesting(),
contextIsolation: true, contextIsolation: true,
sandbox: true,
preload: Paths.preloadJs, preload: Paths.preloadJs,
}, },
}) })

View File

@@ -1,42 +1,28 @@
import { IpcRendererEvent } from 'electron/renderer'
import { MessageToWebApp } from '../Shared/IpcMessages' import { MessageToWebApp } from '../Shared/IpcMessages'
const { ipcRenderer } = require('electron') const { ipcRenderer } = require('electron')
const path = require('path')
const rendererPath = path.join('file://', __dirname, '/renderer.js')
const RemoteBridge = require('@electron/remote').getGlobal('RemoteBridge') const RemoteBridge = require('@electron/remote').getGlobal('RemoteBridge')
const { contextBridge } = require('electron') const { contextBridge } = require('electron')
type MainEventCallback = (event: IpcRendererEvent, value: any) => void
process.once('loaded', function () { process.once('loaded', function () {
contextBridge.exposeInMainWorld('electronRemoteBridge', RemoteBridge.exposableValue) contextBridge.exposeInMainWorld('electronRemoteBridge', RemoteBridge.exposableValue)
listenForIpcEventsFromMainProcess() contextBridge.exposeInMainWorld('electronMainEvents', {
}) handleUpdateAvailable: (callback: MainEventCallback) => ipcRenderer.on(MessageToWebApp.UpdateAvailable, callback),
function listenForIpcEventsFromMainProcess() { handlePerformAutomatedBackup: (callback: MainEventCallback) =>
const sendMessageToRenderProcess = (message: string, payload = {}) => { ipcRenderer.on(MessageToWebApp.PerformAutomatedBackup, callback),
window.postMessage(JSON.stringify({ message, data: payload }), rendererPath)
}
ipcRenderer.on(MessageToWebApp.UpdateAvailable, function (_event, data) { handleFinishedSavingBackup: (callback: MainEventCallback) =>
sendMessageToRenderProcess(MessageToWebApp.UpdateAvailable, data) ipcRenderer.on(MessageToWebApp.FinishedSavingBackup, callback),
})
ipcRenderer.on(MessageToWebApp.PerformAutomatedBackup, function (_event, data) { handleWindowBlurred: (callback: MainEventCallback) => ipcRenderer.on(MessageToWebApp.WindowBlurred, callback),
sendMessageToRenderProcess(MessageToWebApp.PerformAutomatedBackup, data)
})
ipcRenderer.on(MessageToWebApp.FinishedSavingBackup, function (_event, data) { handleWindowFocused: (callback: MainEventCallback) => ipcRenderer.on(MessageToWebApp.WindowFocused, callback),
sendMessageToRenderProcess(MessageToWebApp.FinishedSavingBackup, data)
})
ipcRenderer.on(MessageToWebApp.WindowBlurred, function (_event, data) { handleInstallComponentComplete: (callback: MainEventCallback) =>
sendMessageToRenderProcess(MessageToWebApp.WindowBlurred, data) ipcRenderer.on(MessageToWebApp.InstallComponentComplete, callback),
}) })
ipcRenderer.on(MessageToWebApp.WindowFocused, function (_event, data) {
sendMessageToRenderProcess(MessageToWebApp.WindowFocused, data)
}) })
ipcRenderer.on(MessageToWebApp.InstallComponentComplete, function (_event, data) {
sendMessageToRenderProcess(MessageToWebApp.InstallComponentComplete, data)
})
}

View File

@@ -1,6 +1,6 @@
import { DesktopClientRequiresWebMethods } from '@web/Application/Device/DesktopSnjsExports' import { DesktopClientRequiresWebMethods } from '@web/Application/Device/DesktopSnjsExports'
import { StartApplication } from '@web/Application/Device/StartApplication' import { StartApplication } from '@web/Application/Device/StartApplication'
import { MessageToWebApp } from '../Shared/IpcMessages' import { IpcRendererEvent } from 'electron/renderer'
import { CrossProcessBridge } from './CrossProcessBridge' import { CrossProcessBridge } from './CrossProcessBridge'
import { DesktopDevice } from './DesktopDevice' import { DesktopDevice } from './DesktopDevice'
@@ -23,6 +23,7 @@ declare global {
purchaseUrl: string purchaseUrl: string
startApplication: StartApplication startApplication: StartApplication
zip: any zip: any
electronMainEvents: any
} }
} }
@@ -41,8 +42,6 @@ const loadAndStartApplication = async () => {
window.device = await createDesktopDevice(remoteBridge) window.device = await createDesktopDevice(remoteBridge)
window.startApplication(DEFAULT_SYNC_SERVER, window.device, window.enableUnfinishedFeatures, WEBSOCKET_URL) window.startApplication(DEFAULT_SYNC_SERVER, window.device, window.enableUnfinishedFeatures, WEBSOCKET_URL)
listenForMessagesSentFromMainToPreloadToUs(window.device)
} }
window.onload = () => { window.onload = () => {
@@ -134,35 +133,26 @@ async function configureWindow(remoteBridge: CrossProcessBridge) {
} }
} }
function listenForMessagesSentFromMainToPreloadToUs(device: DesktopDevice) { window.electronMainEvents.handleUpdateAvailable(() => {
window.addEventListener('message', async (event) => { window.webClient.updateAvailable()
// We don't have access to the full file path. })
if (event.origin !== 'file://') {
return window.electronMainEvents.handlePerformAutomatedBackup(() => {
} void window.device.downloadBackup()
let payload })
try {
payload = JSON.parse(event.data) window.electronMainEvents.handleFinishedSavingBackup((_: IpcRendererEvent, data: any) => {
} catch (e) { window.webClient.didFinishBackup(data.success)
// message doesn't belong to us })
return
} window.electronMainEvents.handleWindowBlurred(() => {
const receiver = window.webClient window.webClient.windowLostFocus()
const message = payload.message })
const data = payload.data
window.electronMainEvents.handleWindowFocused(() => {
if (message === MessageToWebApp.WindowBlurred) { window.webClient.windowGainedFocus()
receiver.windowLostFocus() })
} else if (message === MessageToWebApp.WindowFocused) {
receiver.windowGainedFocus() window.electronMainEvents.handleInstallComponentComplete((_: IpcRendererEvent, data: any) => {
} else if (message === MessageToWebApp.InstallComponentComplete) { window.webClient.onComponentInstallationComplete(data.component, undefined)
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)
}
}) })
}