From 0abee95aa26a91237e0659f6d87cef640a1e5065 Mon Sep 17 00:00:00 2001 From: Milan Burda Date: Mon, 16 Nov 2020 07:33:36 +0100 Subject: [PATCH] fix: ensure that internal messages are sent from the main process (#26436) --- lib/renderer/api/remote.js | 2 +- lib/renderer/chrome-api.ts | 6 ++--- lib/renderer/extensions/web-navigation.ts | 4 ++-- lib/renderer/ipc-renderer-internal-utils.ts | 2 +- lib/renderer/ipc-renderer-internal.ts | 23 ++++++++++++++++++++ lib/renderer/web-view/guest-view-internal.ts | 6 ++--- lib/renderer/window-setup.ts | 6 ++--- typings/internal-electron.d.ts | 2 ++ 8 files changed, 38 insertions(+), 13 deletions(-) diff --git a/lib/renderer/api/remote.js b/lib/renderer/api/remote.js index a63bb7c09129c..b049fe7380a7d 100644 --- a/lib/renderer/api/remote.js +++ b/lib/renderer/api/remote.js @@ -271,7 +271,7 @@ function metaToError (meta) { } function handleMessage (channel, handler) { - ipcRendererInternal.on(channel, (event, passedContextId, id, ...args) => { + ipcRendererInternal.onMessageFromMain(channel, (event, passedContextId, id, ...args) => { if (passedContextId === contextId) { handler(id, ...args); } else { diff --git a/lib/renderer/chrome-api.ts b/lib/renderer/chrome-api.ts index cdd9db6395279..c9834016a5ef7 100644 --- a/lib/renderer/chrome-api.ts +++ b/lib/renderer/chrome-api.ts @@ -73,7 +73,7 @@ export function injectTo (extensionId: string, context: any) { const chrome = context.chrome = context.chrome || {}; - ipcRendererInternal.on(`CHROME_RUNTIME_ONCONNECT_${extensionId}`, ( + ipcRendererInternal.onMessageFromMain(`CHROME_RUNTIME_ONCONNECT_${extensionId}`, ( _event: Electron.Event, tabId: number, portId: number, connectInfo: { name: string } ) => { chrome.runtime.onConnect.emit(new Port(tabId, portId, extensionId, connectInfo.name)); @@ -87,11 +87,11 @@ export function injectTo (extensionId: string, context: any) { }); }); - ipcRendererInternal.on('CHROME_TABS_ONCREATED', (_event: Electron.Event, tabId: number) => { + ipcRendererInternal.onMessageFromMain('CHROME_TABS_ONCREATED', (_event: Electron.Event, tabId: number) => { chrome.tabs.onCreated.emit(new Tab(tabId)); }); - ipcRendererInternal.on('CHROME_TABS_ONREMOVED', (_event: Electron.Event, tabId: number) => { + ipcRendererInternal.onMessageFromMain('CHROME_TABS_ONREMOVED', (_event: Electron.Event, tabId: number) => { chrome.tabs.onRemoved.emit(tabId); }); diff --git a/lib/renderer/extensions/web-navigation.ts b/lib/renderer/extensions/web-navigation.ts index 768eb342804b1..a8000bfd7afa6 100644 --- a/lib/renderer/extensions/web-navigation.ts +++ b/lib/renderer/extensions/web-navigation.ts @@ -6,11 +6,11 @@ class WebNavigation { private onCompleted = new Event() constructor () { - ipcRendererInternal.on('CHROME_WEBNAVIGATION_ONBEFORENAVIGATE', (event: Electron.IpcRendererEvent, details: any) => { + ipcRendererInternal.onMessageFromMain('CHROME_WEBNAVIGATION_ONBEFORENAVIGATE', (event: Electron.IpcRendererEvent, details: any) => { this.onBeforeNavigate.emit(details); }); - ipcRendererInternal.on('CHROME_WEBNAVIGATION_ONCOMPLETED', (event: Electron.IpcRendererEvent, details: any) => { + ipcRendererInternal.onMessageFromMain('CHROME_WEBNAVIGATION_ONCOMPLETED', (event: Electron.IpcRendererEvent, details: any) => { this.onCompleted.emit(details); }); } diff --git a/lib/renderer/ipc-renderer-internal-utils.ts b/lib/renderer/ipc-renderer-internal-utils.ts index 28bd02e82dd38..86c412db39e41 100644 --- a/lib/renderer/ipc-renderer-internal-utils.ts +++ b/lib/renderer/ipc-renderer-internal-utils.ts @@ -3,7 +3,7 @@ import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-in type IPCHandler = (event: Electron.IpcRendererEvent, ...args: any[]) => any export const handle = function (channel: string, handler: T) { - ipcRendererInternal.on(channel, async (event, requestId, ...args) => { + ipcRendererInternal.onMessageFromMain(channel, async (event, requestId, ...args) => { const replyChannel = `${channel}_RESPONSE_${requestId}`; try { event.sender.send(replyChannel, null, await handler(event, ...args)); diff --git a/lib/renderer/ipc-renderer-internal.ts b/lib/renderer/ipc-renderer-internal.ts index 045e78c381d5c..4e1fb9f8cfb76 100644 --- a/lib/renderer/ipc-renderer-internal.ts +++ b/lib/renderer/ipc-renderer-internal.ts @@ -29,4 +29,27 @@ if (!ipcRendererInternal.send) { } return result; }; + + ipcRendererInternal.onMessageFromMain = function (channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => void) { + return ipcRendererInternal.on(channel, (event, ...args) => { + if (event.senderId !== 0) { + console.error(`Message ${channel} sent by unexpected WebContents (${event.senderId})`); + return; + } + + listener(event, ...args); + }); + }; + + ipcRendererInternal.onceMessageFromMain = function (channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => void) { + return ipcRendererInternal.on(channel, function wrapper (event, ...args) { + if (event.senderId !== 0) { + console.error(`Message ${channel} sent by unexpected WebContents (${event.senderId})`); + return; + } + + ipcRendererInternal.removeListener(channel, wrapper); + listener(event, ...args); + }); + }; } diff --git a/lib/renderer/web-view/guest-view-internal.ts b/lib/renderer/web-view/guest-view-internal.ts index 3ca3ae3f5f599..cb4f635ebec5f 100644 --- a/lib/renderer/web-view/guest-view-internal.ts +++ b/lib/renderer/web-view/guest-view-internal.ts @@ -66,18 +66,18 @@ const dispatchEvent = function ( }; export function registerEvents (webView: WebViewImpl, viewInstanceId: number) { - ipcRendererInternal.on(`ELECTRON_GUEST_VIEW_INTERNAL_DESTROY_GUEST-${viewInstanceId}`, function () { + ipcRendererInternal.onMessageFromMain(`ELECTRON_GUEST_VIEW_INTERNAL_DESTROY_GUEST-${viewInstanceId}`, function () { webView.guestInstanceId = undefined; webView.reset(); const domEvent = new Event('destroyed'); webView.dispatchEvent(domEvent); }); - ipcRendererInternal.on(`ELECTRON_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-${viewInstanceId}`, function (event, eventName, ...args) { + ipcRendererInternal.onMessageFromMain(`ELECTRON_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-${viewInstanceId}`, function (event, eventName, ...args) { dispatchEvent(webView, eventName, eventName, ...args); }); - ipcRendererInternal.on(`ELECTRON_GUEST_VIEW_INTERNAL_IPC_MESSAGE-${viewInstanceId}`, function (event, channel, ...args) { + ipcRendererInternal.onMessageFromMain(`ELECTRON_GUEST_VIEW_INTERNAL_IPC_MESSAGE-${viewInstanceId}`, function (event, channel, ...args) { const domEvent = new Event('ipc-message') as IpcMessageEvent; domEvent.channel = channel; domEvent.args = args; diff --git a/lib/renderer/window-setup.ts b/lib/renderer/window-setup.ts index 5c9b4b819b547..254d8475bc4fa 100644 --- a/lib/renderer/window-setup.ts +++ b/lib/renderer/window-setup.ts @@ -181,7 +181,7 @@ class BrowserWindowProxy { this.guestId = guestId; this._location = new LocationProxy(guestId); - ipcRendererInternal.once(`ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_${guestId}`, () => { + ipcRendererInternal.onceMessageFromMain(`ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_CLOSED_${guestId}`, () => { removeProxy(guestId); this.closed = true; }); @@ -281,7 +281,7 @@ export const windowSetup = ( if (shouldUseContextBridge) internalContextBridge.overrideGlobalValueFromIsolatedWorld(['prompt'], window.prompt); if (!usesNativeWindowOpen || openerId != null) { - ipcRendererInternal.on('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function ( + ipcRendererInternal.onMessageFromMain('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function ( _event, sourceId: number, message: any, sourceOrigin: string ) { // Manually dispatch event instead of using postMessage because we also need to @@ -337,7 +337,7 @@ export const windowSetup = ( let cachedVisibilityState = isHiddenPage ? 'hidden' : 'visible'; // Subscribe to visibilityState changes. - ipcRendererInternal.on('ELECTRON_GUEST_INSTANCE_VISIBILITY_CHANGE', function (_event, visibilityState: VisibilityState) { + ipcRendererInternal.onMessageFromMain('ELECTRON_GUEST_INSTANCE_VISIBILITY_CHANGE', function (_event, visibilityState: VisibilityState) { if (cachedVisibilityState !== visibilityState) { cachedVisibilityState = visibilityState; document.dispatchEvent(new Event('visibilitychange')); diff --git a/typings/internal-electron.d.ts b/typings/internal-electron.d.ts index 8f23a11289c66..d5b49a58e0fc7 100644 --- a/typings/internal-electron.d.ts +++ b/typings/internal-electron.d.ts @@ -65,6 +65,8 @@ declare namespace Electron { interface IpcRendererInternal extends Electron.IpcRenderer { invoke(channel: string, ...args: any[]): Promise; sendToAll(webContentsId: number, channel: string, ...args: any[]): void + onMessageFromMain(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => void): this; + onceMessageFromMain(channel: string, listener: (event: Electron.IpcRendererEvent, ...args: any[]) => void): this; } interface RemoteInternal extends Electron.Remote {