Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add a getScopedToSender API on ipcMain #17489

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions docs/api/ipc-main.md
Expand Up @@ -88,6 +88,17 @@ Removes the specified `listener` from the listener array for the specified

Removes listeners of the specified `channel`.

### `ipcMain.getScopedToSender(sender)`

* `sender` [WebContents](web-contents.md)

Returns `IpcMain`

Gets a new instance of `IpcMain` that is scoped to only emit ipc messages from
the given sender. This is useful for ensuring the messages you are handling
only come from a webContents you trust without having to check the sender
for every message.

## Event object

The documentation for the `event` object passed to the `callback` can be found
Expand Down
1 change: 1 addition & 0 deletions filenames.gni
Expand Up @@ -42,6 +42,7 @@ filenames = {
"lib/browser/guest-window-manager.js",
"lib/browser/init.ts",
"lib/browser/ipc-main-internal-utils.ts",
"lib/browser/ipc-main-creator.ts",
"lib/browser/ipc-main-internal.ts",
"lib/browser/navigation-controller.js",
"lib/browser/objects-registry.js",
Expand Down
9 changes: 2 additions & 7 deletions lib/browser/api/ipc-main.ts
@@ -1,8 +1,3 @@
import { EventEmitter } from 'events'
import { createIndependentIpcMain } from '@electron/internal/browser/ipc-main-creator'

const emitter = new EventEmitter()

// Do not throw exception when channel name is "error".
emitter.on('error', () => {})

export default emitter
export default createIndependentIpcMain()
47 changes: 47 additions & 0 deletions lib/browser/ipc-main-creator.ts
@@ -0,0 +1,47 @@
import {
EventEmitter
} from 'events'

enum IpcMainHeirachy {
ROOT = 'ROOT',
SCOPED = 'SCOPED',
}

export const createIndependentIpcMain = () => {
const senderScoped = new WeakMap<Electron.WebContents, IpcMain>()

class IpcMain extends EventEmitter implements Electron.IpcMain {
constructor (private heirachy: IpcMainHeirachy) {
super()
// Do not throw exception when channel name is "error".
this.on('error', () => {})
}

getScopedToSender (webContents: Electron.WebContents) {
let scoped = senderScoped.get(webContents)
if (!scoped) {
// Store based on senderId here and don't persist the webContents to avoid it leaking
scoped = new IpcMain(IpcMainHeirachy.SCOPED)
senderScoped.set(webContents, scoped)
}
return scoped
}

emit (channel: string, event: Electron.IpcMainEvent, ...args: any[]): boolean {
let handled = false
// If this is the root instance of IpcMain and we have an event with a valid sender
// we should try emit the event on the scoped IpcMain instance
if (this.heirachy === IpcMainHeirachy.ROOT && event && event.sender && event.sender.id) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to check event.sender.id anymore

const scoped = senderScoped.get(event.sender)
if (scoped) {
handled = scoped.emit(channel, event, ...args) || handled
}
}
handled = super.emit(channel, event, ...args) || handled
return handled
}
}

const ipcMain = new IpcMain(IpcMainHeirachy.ROOT)
return ipcMain
}
9 changes: 2 additions & 7 deletions lib/browser/ipc-main-internal.ts
@@ -1,8 +1,3 @@
import { EventEmitter } from 'events'
import { createIndependentIpcMain } from '@electron/internal/browser/ipc-main-creator'

const emitter = new EventEmitter()

// Do not throw exception when channel name is "error".
emitter.on('error', () => {})

export const ipcMainInternal = emitter as ElectronInternal.IpcMainInternal
export const ipcMainInternal = createIndependentIpcMain() as ElectronInternal.IpcMainInternal