Browse Source

feat: add event.senderFrame property returning the originating webFrameMain (#26764)

Milan Burda 4 years ago
parent
commit
cec6378881

+ 1 - 0
docs/api/structures/ipc-main-event.md

@@ -4,6 +4,7 @@
 * `frameId` Integer - The ID of the renderer frame that sent this message
 * `returnValue` any - Set this to the value to be returned in a synchronous message
 * `sender` WebContents - Returns the `webContents` that sent the message
+* `senderFrame` WebFrameMain _Readonly_ - The frame that sent this message
 * `ports` MessagePortMain[] - A list of MessagePorts that were transferred with this message
 * `reply` Function - A function that will send an IPC message to the renderer frame that sent the original message that you are currently handling.  You should use this method to "reply" to the sent message in order to guarantee the reply will go to the correct process and frame.
   * `channel` String

+ 1 - 0
docs/api/structures/ipc-main-invoke-event.md

@@ -3,3 +3,4 @@
 * `processId` Integer - The internal ID of the renderer process that sent this message
 * `frameId` Integer - The ID of the renderer frame that sent this message
 * `sender` WebContents - Returns the `webContents` that sent the message
+* `senderFrame` WebFrameMain _Readonly_ - The frame that sent this message

+ 3 - 3
docs/api/web-frame-main.md

@@ -26,7 +26,7 @@ win.webContents.on(
 )
 ```
 
-You can also access frames of existing pages by using the `webFrame` property
+You can also access frames of existing pages by using the `mainFrame` property
 of [`WebContents`](web-contents.md).
 
 ```javascript
@@ -57,8 +57,8 @@ These methods can be accessed from the `webFrameMain` module:
 
 ### `webFrameMain.fromId(processId, routingId)`
 
-* `processId` Integer - An `Integer` representing the id of the process which owns the frame.
-* `routingId` Integer - An `Integer` representing the unique frame id in the
+* `processId` Integer - An `Integer` representing the internal ID of the process which owns the frame.
+* `routingId` Integer - An `Integer` representing the unique frame ID in the
   current renderer process. Routing IDs can be retrieved from `WebFrameMain`
   instances (`frame.routingId`) and are also passed by frame
   specific `WebContents` navigation events (e.g. `did-frame-navigate`).

+ 12 - 2
lib/browser/api/web-contents.ts

@@ -1,5 +1,5 @@
-import { app, ipcMain, session, deprecate, BrowserWindowConstructorOptions } from 'electron/main';
-import type { MenuItem, MenuItemConstructorOptions, LoadURLOptions } from 'electron/main';
+import { app, ipcMain, session, deprecate, webFrameMain } from 'electron/main';
+import type { BrowserWindowConstructorOptions, MenuItem, MenuItemConstructorOptions, LoadURLOptions } from 'electron/main';
 
 import * as url from 'url';
 import * as path from 'path';
@@ -462,6 +462,13 @@ const addReplyToEvent = (event: any) => {
   };
 };
 
+const addSenderFrameToEvent = (event: any) => {
+  const { processId, frameId } = event;
+  Object.defineProperty(event, 'senderFrame', {
+    get: () => webFrameMain.fromId(processId, frameId)
+  });
+};
+
 const addReturnValueToEvent = (event: any) => {
   Object.defineProperty(event, 'returnValue', {
     set: (value) => event.sendReply(value),
@@ -505,6 +512,7 @@ WebContents.prototype._init = function () {
 
   // Dispatch IPC messages to the ipc module.
   this.on('-ipc-message' as any, function (this: Electron.WebContents, event: any, internal: boolean, channel: string, args: any[]) {
+    addSenderFrameToEvent(event);
     if (internal) {
       ipcMainInternal.emit(channel, event, ...args);
     } else {
@@ -515,6 +523,7 @@ WebContents.prototype._init = function () {
   });
 
   this.on('-ipc-invoke' as any, function (event: any, internal: boolean, channel: string, args: any[]) {
+    addSenderFrameToEvent(event);
     event._reply = (result: any) => event.sendReply({ result });
     event._throw = (error: Error) => {
       console.error(`Error occurred in handler for '${channel}':`, error);
@@ -529,6 +538,7 @@ WebContents.prototype._init = function () {
   });
 
   this.on('-ipc-message-sync' as any, function (this: Electron.WebContents, event: any, internal: boolean, channel: string, args: any[]) {
+    addSenderFrameToEvent(event);
     addReturnValueToEvent(event);
     if (internal) {
       ipcMainInternal.emit(channel, event, ...args);

+ 0 - 7
shell/common/gin_converters/frame_converter.cc

@@ -4,15 +4,8 @@
 
 #include "shell/common/gin_converters/frame_converter.h"
 
-#include <string>
-#include <vector>
-
 #include "content/public/browser/render_frame_host.h"
 #include "shell/browser/api/electron_api_web_frame_main.h"
-#include "shell/common/gin_converters/blink_converter.h"
-#include "shell/common/gin_converters/callback_converter.h"
-#include "shell/common/gin_converters/gurl_converter.h"
-#include "shell/common/gin_helper/dictionary.h"
 
 namespace gin {
 

+ 0 - 2
shell/common/gin_converters/frame_converter.h

@@ -5,8 +5,6 @@
 #ifndef SHELL_COMMON_GIN_CONVERTERS_FRAME_CONVERTER_H_
 #define SHELL_COMMON_GIN_CONVERTERS_FRAME_CONVERTER_H_
 
-#include <utility>
-
 #include "gin/converter.h"
 
 namespace content {

+ 8 - 0
spec-main/api-subframe-spec.ts

@@ -35,6 +35,8 @@ describe('renderer nodeIntegrationInSubFrames', () => {
         expect(event1[0].frameId).to.not.equal(event2[0].frameId);
         expect(event1[0].frameId).to.equal(event1[2]);
         expect(event2[0].frameId).to.equal(event2[2]);
+        expect(event1[0].senderFrame.routingId).to.equal(event1[2]);
+        expect(event2[0].senderFrame.routingId).to.equal(event2[2]);
       });
 
       it('should load preload scripts in nested iframes', async () => {
@@ -47,6 +49,9 @@ describe('renderer nodeIntegrationInSubFrames', () => {
         expect(event1[0].frameId).to.equal(event1[2]);
         expect(event2[0].frameId).to.equal(event2[2]);
         expect(event3[0].frameId).to.equal(event3[2]);
+        expect(event1[0].senderFrame.routingId).to.equal(event1[2]);
+        expect(event2[0].senderFrame.routingId).to.equal(event2[2]);
+        expect(event3[0].senderFrame.routingId).to.equal(event3[2]);
       });
 
       it('should correctly reply to the main frame with using event.reply', async () => {
@@ -57,6 +62,7 @@ describe('renderer nodeIntegrationInSubFrames', () => {
         event1[0].reply('preload-ping');
         const details = await pongPromise;
         expect(details[1]).to.equal(event1[0].frameId);
+        expect(details[1]).to.equal(event1[0].senderFrame.routingId);
       });
 
       it('should correctly reply to the sub-frames with using event.reply', async () => {
@@ -67,6 +73,7 @@ describe('renderer nodeIntegrationInSubFrames', () => {
         event2[0].reply('preload-ping');
         const details = await pongPromise;
         expect(details[1]).to.equal(event2[0].frameId);
+        expect(details[1]).to.equal(event2[0].senderFrame.routingId);
       });
 
       it('should correctly reply to the nested sub-frames with using event.reply', async () => {
@@ -77,6 +84,7 @@ describe('renderer nodeIntegrationInSubFrames', () => {
         event3[0].reply('preload-ping');
         const details = await pongPromise;
         expect(details[1]).to.equal(event3[0].frameId);
+        expect(details[1]).to.equal(event3[0].senderFrame.routingId);
       });
 
       it('should not expose globals in main world', async () => {