diff --git a/lib/browser/guest-view-manager.js b/lib/browser/guest-view-manager.js index b5d88ab4518ce..b3299477c1d8f 100644 --- a/lib/browser/guest-view-manager.js +++ b/lib/browser/guest-view-manager.js @@ -4,7 +4,11 @@ const { webContents } = require('electron') const ipcMain = require('@electron/internal/browser/ipc-main-internal') const parseFeaturesString = require('@electron/internal/common/parse-features-string') const errorUtils = require('@electron/internal/common/error-utils') -const { syncMethods, asyncMethods } = require('@electron/internal/common/web-view-methods') +const { + syncMethods, + asyncCallbackMethods, + asyncPromiseMethods +} = require('@electron/internal/common/web-view-methods') // Doesn't exist in early initialization. let webViewManager = null @@ -391,7 +395,7 @@ ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', function (event, focus, g handleMessage('ELECTRON_GUEST_VIEW_MANAGER_ASYNC_CALL', function (event, requestId, guestInstanceId, method, args, hasCallback) { new Promise(resolve => { const guest = getGuestForWebContents(guestInstanceId, event.sender) - if (!asyncMethods.has(method)) { + if (!asyncCallbackMethods.has(method) && !asyncPromiseMethods.has(method)) { throw new Error(`Invalid method: ${method}`) } if (hasCallback) { diff --git a/lib/common/web-view-methods.js b/lib/common/web-view-methods.js index 8e40c9ede995f..860eab00474da 100644 --- a/lib/common/web-view-methods.js +++ b/lib/common/web-view-methods.js @@ -50,18 +50,20 @@ exports.syncMethods = new Set([ 'setZoomLevel' ]) -exports.asyncMethods = new Set([ +exports.asyncCallbackMethods = new Set([ 'insertCSS', 'insertText', 'send', 'sendInputEvent', 'setLayoutZoomLevelLimits', 'setVisualZoomLevelLimits', - // with callback - 'capturePage', - 'executeJavaScript', 'getZoomFactor', 'getZoomLevel', 'print', 'printToPDF' ]) + +exports.asyncPromiseMethods = new Set([ + 'capturePage', + 'executeJavaScript' +]) diff --git a/lib/renderer/web-view/web-view.js b/lib/renderer/web-view/web-view.js index 425e838d3efdb..560c7284bdfc7 100644 --- a/lib/renderer/web-view/web-view.js +++ b/lib/renderer/web-view/web-view.js @@ -7,7 +7,11 @@ const ipcRenderer = require('@electron/internal/renderer/ipc-renderer-internal') 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, asyncMethods } = require('@electron/internal/common/web-view-methods') +const { + syncMethods, + asyncCallbackMethods, + asyncPromiseMethods +} = require('@electron/internal/common/web-view-methods') // ID generator. let nextId = 0 @@ -268,10 +272,36 @@ const registerWebViewElement = (window) => { ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_ASYNC_CALL', requestId, getGuestInstanceId(this), method, args, callback != null) } } - for (const method of asyncMethods) { + + for (const method of asyncCallbackMethods) { proto[method] = createNonBlockHandler(method) } + 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() + + ipcRenderer.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)) + } + }) + ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_ASYNC_CALL', requestId, getGuestInstanceId(this), method, args, callback != null) + }) + } + } + + for (const method of asyncPromiseMethods) { + proto[method] = createPromiseHandler(method) + } + // WebContents associated with this webview. proto.getWebContents = function () { const { getRemoteForUsage } = require('@electron/internal/renderer/remote')