Browse Source

feat: make `ipc-message` and `ipc-message-sync` events public (#16468)

Milan Burda 6 years ago
parent
commit
6cba2c50a2

+ 20 - 0
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:

+ 4 - 2
lib/browser/api/web-contents.js

@@ -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)
   })
 

+ 2 - 2
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) {

+ 28 - 0
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, message] = await promise
+      expect(channel).to.equal('message')
+      expect(message).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, message] = await promise
+      expect(channel).to.equal('message')
+      expect(message).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) => {

+ 21 - 21
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, message) => {
+        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(message)
+        } else if (channel === 'response') {
+          assert.strictEqual(message, '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, message) => {
+        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 : ${message}`)
+        } else if (channel === 'response') {
+          assert.strictEqual(message, '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) => {
+        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, opener] = await promise
+      expect(channel).to.equal('opener')
+      expect(opener).to.equal(null)
     })
 
     it('is not null for window opened by window.open', (done) => {

+ 6 - 0
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',

+ 1 - 1
spec/webview-spec.js

@@ -651,7 +651,7 @@ describe('<webview> 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`