Browse Source

fix: ensure that internal messages are sent from the main process (#26436)

Milan Burda 4 years ago
parent
commit
0abee95aa2

+ 1 - 1
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 {

+ 3 - 3
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);
   });
 

+ 2 - 2
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);
     });
   }

+ 1 - 1
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 <T extends IPCHandler> (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));

+ 23 - 0
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);
+    });
+  };
 }

+ 3 - 3
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;

+ 3 - 3
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'));

+ 2 - 0
typings/internal-electron.d.ts

@@ -65,6 +65,8 @@ declare namespace Electron {
   interface IpcRendererInternal extends Electron.IpcRenderer {
     invoke<T>(channel: string, ...args: any[]): Promise<T>;
     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 {