From f19fda81b26ca1d6e2117f42f7fee6d043df5d20 Mon Sep 17 00:00:00 2001 From: Milan Burda Date: Mon, 21 Jan 2019 23:57:13 +0100 Subject: [PATCH] feat: make `ipc-message` and `ipc-message-sync` events public --- atom/renderer/atom_render_frame_observer.cc | 2 +- docs/api/web-contents.md | 20 ++++++++++ lib/browser/api/web-contents.js | 10 +++-- lib/renderer/api/ipc-renderer.js | 4 +- spec/api-web-contents-spec.js | 28 ++++++++++++++ spec/chromium-spec.js | 42 ++++++++++----------- spec/static/main.js | 6 +++ spec/webview-spec.js | 2 +- 8 files changed, 85 insertions(+), 29 deletions(-) diff --git a/atom/renderer/atom_render_frame_observer.cc b/atom/renderer/atom_render_frame_observer.cc index 753a4362749c2..09d36b80ccec7 100644 --- a/atom/renderer/atom_render_frame_observer.cc +++ b/atom/renderer/atom_render_frame_observer.cc @@ -216,7 +216,7 @@ void AtomRenderFrameObserver::OnTakeHeapSnapshot( args.AppendBoolean(success); render_frame_->Send(new AtomFrameHostMsg_Message( - render_frame_->GetRoutingID(), "ipc-message", args)); + render_frame_->GetRoutingID(), "ipc-internal-message", args)); } void AtomRenderFrameObserver::EmitIPCEvent(blink::WebLocalFrame* frame, diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 73d4875b99a87..b0a206cd31b8a 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -673,6 +673,26 @@ Returns: Emitted when the preload script `preloadPath` throws an unhandled exception `error`. +#### Event: 'ipc-message' + +Returns: + +* `event` Event +* `channel` String +* `...args` any[] + +Emitted when the renderer process sends an asynchronous message via `ipcRenderer.send()`. + +#### Event: 'ipc-message-sync' + +Returns: + +* `event` Event +* `channel` String +* `...args` any[] + +Emitted when the renderer process sends a synchronous message via `ipcRenderer.sendSync()`. + #### Event: 'desktop-capturer-get-sources' Returns: diff --git a/lib/browser/api/web-contents.js b/lib/browser/api/web-contents.js index 10a506fac0e45..8d9d9623309a7 100644 --- a/lib/browser/api/web-contents.js +++ b/lib/browser/api/web-contents.js @@ -237,7 +237,7 @@ WebContents.prototype.getZoomFactor = function (callback) { WebContents.prototype.takeHeapSnapshot = function (filePath) { return new Promise((resolve, reject) => { const channel = `ELECTRON_TAKE_HEAP_SNAPSHOT_RESULT_${getNextId()}` - ipcMain.once(channel, (event, success) => { + ipcMainInternal.once(channel, (event, success) => { if (success) { resolve() } else { @@ -245,7 +245,7 @@ WebContents.prototype.takeHeapSnapshot = function (filePath) { } }) if (!this._takeHeapSnapshot(filePath, channel)) { - ipcMain.emit(channel, false) + ipcMainInternal.emit(channel, false) } }) } @@ -342,17 +342,19 @@ WebContents.prototype._init = function () { this.capturePage = deprecate.promisify(this.capturePage, 2) // Dispatch IPC messages to the ipc module. - this.on('ipc-message', function (event, [channel, ...args]) { + this.on('-ipc-message', function (event, [channel, ...args]) { + this.emit('ipc-message', event, channel, ...args) ipcMain.emit(channel, event, ...args) }) - this.on('ipc-message-sync', function (event, [channel, ...args]) { + this.on('-ipc-message-sync', function (event, [channel, ...args]) { Object.defineProperty(event, 'returnValue', { set: function (value) { return event.sendReply([value]) }, get: function () {} }) + this.emit('ipc-message-sync', event, channel, ...args) ipcMain.emit(channel, event, ...args) }) diff --git a/lib/renderer/api/ipc-renderer.js b/lib/renderer/api/ipc-renderer.js index 7705f9f9ae77c..1911543e42a7c 100644 --- a/lib/renderer/api/ipc-renderer.js +++ b/lib/renderer/api/ipc-renderer.js @@ -8,11 +8,11 @@ const ipcRenderer = v8Util.getHiddenValue(global, 'ipc') const internal = false ipcRenderer.send = function (...args) { - return binding.send('ipc-message', args) + return binding.send('-ipc-message', args) } ipcRenderer.sendSync = function (...args) { - return binding.sendSync('ipc-message-sync', args)[0] + return binding.sendSync('-ipc-message-sync', args)[0] } ipcRenderer.sendToHost = function (...args) { diff --git a/spec/api-web-contents-spec.js b/spec/api-web-contents-spec.js index 4344a7f6a0f44..7de845c078e61 100644 --- a/spec/api-web-contents-spec.js +++ b/spec/api-web-contents-spec.js @@ -995,6 +995,34 @@ describe('webContents module', () => { }) }) + describe('ipc-message event', () => { + it('emits when the renderer process sends an asynchronous message', async () => { + const webContents = remote.getCurrentWebContents() + const promise = emittedOnce(webContents, 'ipc-message') + + ipcRenderer.send('message', 'Hello World!') + + const [, channel, args] = await promise + expect(channel).to.equal('message') + expect(args[0]).to.equal('Hello World!') + }) + }) + + describe('ipc-message-sync event', () => { + it('emits when the renderer process sends a synchronous message', async () => { + const webContents = remote.getCurrentWebContents() + const promise = emittedOnce(webContents, 'ipc-message-sync') + + ipcRenderer.send('handle-next-ipc-message-sync', 'foobar') + const result = ipcRenderer.sendSync('message', 'Hello World!') + + const [, channel, args] = await promise + expect(channel).to.equal('message') + expect(args[0]).to.equal('Hello World!') + expect(result).to.equal('foobar') + }) + }) + describe('referrer', () => { it('propagates referrer information to new target=_blank windows', (done) => { const server = http.createServer((req, res) => { diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index 9ef8a7a05c0ff..f0b5ec99bb689 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -175,8 +175,8 @@ describe('chromium feature', () => { session: ses } }) - w.webContents.on('ipc-message', (event, args) => { - if (args[0] === 'deviceIds') deviceIds.push(args[1]) + w.webContents.on('ipc-message', (event, channel, [deviceId]) => { + if (channel === 'deviceIds') deviceIds.push(deviceId) if (deviceIds.length === 2) { assert.notDeepStrictEqual(deviceIds[0], deviceIds[1]) closeWindow(w).then(() => { @@ -216,13 +216,13 @@ describe('chromium feature', () => { partition: 'sw-file-scheme-spec' } }) - w.webContents.on('ipc-message', (event, args) => { - if (args[0] === 'reload') { + w.webContents.on('ipc-message', (event, channel, args) => { + if (channel === 'reload') { w.webContents.reload() - } else if (args[0] === 'error') { - done(args[1]) - } else if (args[0] === 'response') { - assert.strictEqual(args[1], 'Hello from serviceWorker!') + } else if (channel === 'error') { + done(args[0]) + } else if (channel === 'response') { + assert.strictEqual(args[0], 'Hello from serviceWorker!') session.fromPartition('sw-file-scheme-spec').clearStorageData({ storages: ['serviceworkers'] }, () => done()) @@ -255,13 +255,13 @@ describe('chromium feature', () => { session: customSession } }) - w.webContents.on('ipc-message', (event, args) => { - if (args[0] === 'reload') { + w.webContents.on('ipc-message', (event, channel, args) => { + if (channel === 'reload') { w.webContents.reload() - } else if (args[0] === 'error') { - done(`unexpected error : ${args[1]}`) - } else if (args[0] === 'response') { - assert.strictEqual(args[1], 'Hello from serviceWorker!') + } else if (channel === 'error') { + done(`unexpected error : ${args[0]}`) + } else if (channel === 'response') { + assert.strictEqual(args[0], 'Hello from serviceWorker!') customSession.clearStorageData({ storages: ['serviceworkers'] }, () => { @@ -298,8 +298,8 @@ describe('chromium feature', () => { partition: 'geolocation-spec' } }) - w.webContents.on('ipc-message', (event, args) => { - if (args[0] === 'success') { + w.webContents.on('ipc-message', (event, channel, args) => { + if (channel === 'success') { done() } else { done('unexpected response from geolocation api') @@ -584,18 +584,18 @@ describe('chromium feature', () => { describe('window.opener', () => { const url = `file://${fixtures}/pages/window-opener.html` - it('is null for main window', (done) => { + it('is null for main window', async () => { w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } }) - w.webContents.once('ipc-message', (event, args) => { - assert.deepStrictEqual(args, ['opener', null]) - done() - }) + const promise = emittedOnce(w.webContents, 'ipc-message') w.loadFile(path.join(fixtures, 'pages', 'window-opener.html')) + const [, channel, args] = await promise + expect(channel).to.equal('opener') + expect(args[0]).to.equal(null) }) it('is not null for window opened by window.open', (done) => { diff --git a/spec/static/main.js b/spec/static/main.js index fd777611a0203..7a49d9190212f 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -235,6 +235,12 @@ app.on('ready', function () { }) }) +ipcMain.on('handle-next-ipc-message-sync', function (event, returnValue) { + event.sender.once('ipc-message-sync', (event, channel, args) => { + event.returnValue = returnValue + }) +}) + for (const eventName of [ 'remote-require', 'remote-get-global', diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 9370a01bb6da7..65d28db74b25c 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -624,7 +624,7 @@ describe(' tag', function () { }) describe('ipc-message event', () => { - it('emits when guest sends a ipc message to browser', async () => { + it('emits when guest sends an ipc message to browser', async () => { loadWebView(webview, { nodeintegration: 'on', src: `file://${fixtures}/pages/ipc-message.html`