Browse Source

refactor: use invoke/invokeSync helpers for <webview> implementation (#16784)

Milan Burda 6 years ago
parent
commit
bbd1ae315a

+ 18 - 38
lib/browser/guest-view-manager.js

@@ -2,8 +2,8 @@
 
 const { webContents } = require('electron')
 const { ipcMainInternal } = require('@electron/internal/browser/ipc-main-internal')
+const ipcMainUtils = require('@electron/internal/browser/ipc-main-internal-utils')
 const parseFeaturesString = require('@electron/internal/common/parse-features-string')
-const errorUtils = require('@electron/internal/common/error-utils')
 const {
   syncMethods,
   asyncCallbackMethods,
@@ -341,21 +341,18 @@ const isWebViewTagEnabled = function (contents) {
 }
 
 const handleMessage = function (channel, handler) {
-  ipcMainInternal.on(channel, (event, ...args) => {
+  ipcMainUtils.handle(channel, (event, ...args) => {
     if (isWebViewTagEnabled(event.sender)) {
-      handler(event, ...args)
+      return handler(event, ...args)
     } else {
-      event.returnValue = null
+      console.error(`<webview> IPC message ${channel} sent by WebContents with <webview> disabled (${event.sender.id})`)
+      throw new Error('<webview> disabled')
     }
   })
 }
 
-handleMessage('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', function (event, params, requestId) {
-  event._replyInternal(`ELECTRON_RESPONSE_${requestId}`, createGuest(event.sender, params))
-})
-
-handleMessage('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST_SYNC', function (event, params) {
-  event.returnValue = createGuest(event.sender, params)
+handleMessage('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', function (event, params) {
+  return createGuest(event.sender, params)
 })
 
 handleMessage('ELECTRON_GUEST_VIEW_MANAGER_DESTROY_GUEST', function (event, guestInstanceId) {
@@ -385,36 +382,19 @@ ipcMainInternal.on('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', function (event,
   }
 })
 
-handleMessage('ELECTRON_GUEST_VIEW_MANAGER_ASYNC_CALL', function (event, requestId, guestInstanceId, method, args, hasCallback) {
-  new Promise(resolve => {
-    const guest = getGuestForWebContents(guestInstanceId, event.sender)
-    if (!asyncCallbackMethods.has(method) && !asyncPromiseMethods.has(method)) {
-      throw new Error(`Invalid method: ${method}`)
-    }
-    if (hasCallback) {
-      guest[method](...args, resolve)
-    } else {
-      resolve(guest[method](...args))
-    }
-  }).then(result => {
-    return [null, result]
-  }, error => {
-    return [errorUtils.serialize(error)]
-  }).then(responseArgs => {
-    event._replyInternal(`ELECTRON_GUEST_VIEW_MANAGER_ASYNC_CALL_RESPONSE_${requestId}`, ...responseArgs)
-  })
-})
+const allMethods = new Set([
+  ...syncMethods,
+  ...asyncCallbackMethods,
+  ...asyncPromiseMethods
+])
 
-handleMessage('ELECTRON_GUEST_VIEW_MANAGER_SYNC_CALL', function (event, guestInstanceId, method, args) {
-  try {
-    const guest = getGuestForWebContents(guestInstanceId, event.sender)
-    if (!syncMethods.has(method)) {
-      throw new Error(`Invalid method: ${method}`)
-    }
-    event.returnValue = [null, guest[method](...args)]
-  } catch (error) {
-    event.returnValue = [errorUtils.serialize(error)]
+handleMessage('ELECTRON_GUEST_VIEW_MANAGER_CALL', function (event, guestInstanceId, method, args) {
+  const guest = getGuestForWebContents(guestInstanceId, event.sender)
+  if (!allMethods.has(method)) {
+    throw new Error(`Invalid method: ${method}`)
   }
+
+  return guest[method](...args)
 })
 
 // Returns WebContents from its guest id hosted in given webContents.

+ 6 - 9
lib/renderer/web-view/guest-view-internal.js

@@ -2,8 +2,7 @@
 
 const { webFrame } = require('electron')
 const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal')
-
-let requestId = 0
+const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils')
 
 const WEB_VIEW_EVENTS = {
   'load-commit': ['url', 'isMainFrame'],
@@ -87,22 +86,20 @@ module.exports = {
     ipcRendererInternal.removeAllListeners(`ELECTRON_GUEST_VIEW_INTERNAL_DISPATCH_EVENT-${viewInstanceId}`)
     ipcRendererInternal.removeAllListeners(`ELECTRON_GUEST_VIEW_INTERNAL_IPC_MESSAGE-${viewInstanceId}`)
   },
-  createGuest: function (params, callback) {
-    requestId++
-    ipcRendererInternal.send('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', params, requestId)
-    ipcRendererInternal.once(`ELECTRON_RESPONSE_${requestId}`, callback)
+  createGuest: function (params) {
+    return ipcRendererUtils.invoke('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', params)
   },
   createGuestSync: function (params) {
-    return ipcRendererInternal.sendSync('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST_SYNC', params)
+    return ipcRendererUtils.invokeSync('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', params)
   },
   destroyGuest: function (guestInstanceId) {
-    ipcRendererInternal.send('ELECTRON_GUEST_VIEW_MANAGER_DESTROY_GUEST', guestInstanceId)
+    ipcRendererUtils.invoke('ELECTRON_GUEST_VIEW_MANAGER_DESTROY_GUEST', guestInstanceId)
   },
   attachGuest: function (elementInstanceId, guestInstanceId, params, contentWindow) {
     const embedderFrameId = webFrame.getWebFrameId(contentWindow)
     if (embedderFrameId < 0) { // this error should not happen.
       throw new Error('Invalid embedder frame')
     }
-    ipcRendererInternal.send('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', embedderFrameId, elementInstanceId, guestInstanceId, params)
+    ipcRendererUtils.invoke('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', embedderFrameId, elementInstanceId, guestInstanceId, params)
   }
 }

+ 2 - 6
lib/renderer/web-view/web-view-attributes.js

@@ -1,9 +1,8 @@
 'use strict'
 
-const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal')
+const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils')
 const { WebViewImpl } = require('@electron/internal/renderer/web-view/web-view-impl')
 const webViewConstants = require('@electron/internal/renderer/web-view/web-view-constants')
-const errorUtils = require('@electron/internal/common/error-utils')
 
 // Helper function to resolve url set in attribute.
 const a = document.createElement('a')
@@ -186,10 +185,7 @@ class SrcAttribute extends WebViewAttribute {
     const method = 'loadURL'
     const args = [this.getValue(), opts]
 
-    const [error] = ipcRendererInternal.sendSync('ELECTRON_GUEST_VIEW_MANAGER_SYNC_CALL', guestInstanceId, method, args)
-    if (error) {
-      throw errorUtils.deserialize(error)
-    }
+    ipcRendererUtils.invokeSync('ELECTRON_GUEST_VIEW_MANAGER_CALL', guestInstanceId, method, args)
   }
 }
 

+ 6 - 38
lib/renderer/web-view/web-view-impl.js

@@ -3,10 +3,9 @@
 const { webFrame, deprecate } = require('electron')
 
 const v8Util = process.atomBinding('v8_util')
-const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal')
+const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils')
 const guestViewInternal = require('@electron/internal/renderer/web-view/guest-view-internal')
 const webViewConstants = require('@electron/internal/renderer/web-view/web-view-constants')
-const errorUtils = require('@electron/internal/common/error-utils')
 const {
   syncMethods,
   asyncCallbackMethods,
@@ -111,7 +110,7 @@ class WebViewImpl {
   }
 
   createGuest () {
-    return guestViewInternal.createGuest(this.buildParams(), (event, guestInstanceId) => {
+    guestViewInternal.createGuest(this.buildParams()).then(guestInstanceId => {
       this.attachGuestInstance(guestInstanceId)
     })
   }
@@ -232,12 +231,7 @@ const setupMethods = (WebViewElement) => {
   // Forward proto.foo* method calls to WebViewImpl.foo*.
   const createBlockHandler = function (method) {
     return function (...args) {
-      const [error, result] = ipcRendererInternal.sendSync('ELECTRON_GUEST_VIEW_MANAGER_SYNC_CALL', getGuestInstanceId(this), method, args)
-      if (error) {
-        throw errorUtils.deserialize(error)
-      } else {
-        return result
-      }
+      return ipcRendererUtils.invokeSync('ELECTRON_GUEST_VIEW_MANAGER_CALL', getGuestInstanceId(this), method, args)
     }
   }
   for (const method of syncMethods) {
@@ -246,16 +240,7 @@ const setupMethods = (WebViewElement) => {
 
   const createNonBlockHandler = function (method) {
     return function (...args) {
-      const callback = (typeof args[args.length - 1] === 'function') ? args.pop() : null
-      const requestId = getNextId()
-      ipcRendererInternal.once(`ELECTRON_GUEST_VIEW_MANAGER_ASYNC_CALL_RESPONSE_${requestId}`, function (event, error, result) {
-        if (error == null) {
-          if (callback) callback(result)
-        } else {
-          throw errorUtils.deserialize(error)
-        }
-      })
-      ipcRendererInternal.send('ELECTRON_GUEST_VIEW_MANAGER_ASYNC_CALL', requestId, getGuestInstanceId(this), method, args, callback != null)
+      ipcRendererUtils.invoke('ELECTRON_GUEST_VIEW_MANAGER_CALL', getGuestInstanceId(this), method, args)
     }
   }
 
@@ -265,30 +250,13 @@ const setupMethods = (WebViewElement) => {
 
   const createPromiseHandler = function (method) {
     return function (...args) {
-      return new Promise((resolve, reject) => {
-        const callback = (typeof args[args.length - 1] === 'function') ? args.pop() : null
-        const requestId = getNextId()
-
-        ipcRendererInternal.once(`ELECTRON_GUEST_VIEW_MANAGER_ASYNC_CALL_RESPONSE_${requestId}`, function (event, error, result) {
-          if (error == null) {
-            if (callback) {
-              callback(result)
-            }
-            resolve(result)
-          } else {
-            reject(errorUtils.deserialize(error))
-          }
-        })
-        ipcRendererInternal.send('ELECTRON_GUEST_VIEW_MANAGER_ASYNC_CALL', requestId, getGuestInstanceId(this), method, args, callback != null)
-      })
+      return ipcRendererUtils.invoke('ELECTRON_GUEST_VIEW_MANAGER_CALL', getGuestInstanceId(this), method, args)
     }
   }
 
   for (const method of asyncPromiseMethods) {
-    WebViewElement.prototype[method] = createPromiseHandler(method)
+    WebViewElement.prototype[method] = deprecate.promisify(createPromiseHandler(method))
   }
-
-  WebViewElement.prototype.printToPDF = deprecate.promisify(WebViewElement.prototype.printToPDF)
 }
 
 module.exports = { setupAttributes, setupMethods, guestViewInternal, webFrame, WebViewImpl }