diff --git a/lib/browser/guest-view-manager.js b/lib/browser/guest-view-manager.js index ec59d47f8e90..2823a7f5887d 100644 --- a/lib/browser/guest-view-manager.js +++ b/lib/browser/guest-view-manager.js @@ -3,6 +3,7 @@ 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') // Doesn't exist in early initialization. let webViewManager = null @@ -319,29 +320,82 @@ const watchEmbedder = function (embedder) { }) } -ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', function (event, params, requestId) { +const isWebViewTagEnabledCache = new WeakMap() + +const isWebViewTagEnabled = function (contents) { + if (!isWebViewTagEnabledCache.has(contents)) { + const value = contents.getLastWebPreferences().webviewTag + isWebViewTagEnabledCache.set(contents, value) + } + + return isWebViewTagEnabledCache.get(contents) +} + +const handleMessage = function (channel, handler) { + ipcMain.on(channel, (event, ...args) => { + if (isWebViewTagEnabled(event.sender)) { + handler(event, ...args) + } else { + event.returnValue = null + } + }) +} + +handleMessage('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST', function (event, params, requestId) { event.sender._sendInternal(`ELECTRON_RESPONSE_${requestId}`, createGuest(event.sender, params)) }) -ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST_SYNC', function (event, params) { +handleMessage('ELECTRON_GUEST_VIEW_MANAGER_CREATE_GUEST_SYNC', function (event, params) { event.returnValue = createGuest(event.sender, params) }) -ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_DESTROY_GUEST', function (event, guestInstanceId) { +handleMessage('ELECTRON_GUEST_VIEW_MANAGER_DESTROY_GUEST', function (event, guestInstanceId) { const guest = getGuest(guestInstanceId) if (guest) { guest.destroy() } }) -ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', function (event, embedderFrameId, elementInstanceId, guestInstanceId, params) { +handleMessage('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', function (event, embedderFrameId, elementInstanceId, guestInstanceId, params) { attachGuest(event, embedderFrameId, elementInstanceId, guestInstanceId, params) }) -ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', function (event, focus, guestInstanceId) { +handleMessage('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', function (event, focus, guestInstanceId) { event.sender.emit('focus-change', {}, focus, guestInstanceId) }) +handleMessage('ELECTRON_GUEST_VIEW_MANAGER_ASYNC_CALL', function (event, requestId, guestInstanceId, method, args, hasCallback) { + new Promise(resolve => { + const guest = getGuest(guestInstanceId) + if (guest.hostWebContents !== event.sender) { + throw new Error('Access denied') + } + if (hasCallback) { + guest[method](...args, resolve) + } else { + resolve(guest[method](...args)) + } + }).then(result => { + return [null, result] + }, error => { + return [errorUtils.serialize(error)] + }).then(responseArgs => { + event.sender._sendInternal(`ELECTRON_GUEST_VIEW_MANAGER_ASYNC_CALL_RESPONSE_${requestId}`, ...responseArgs) + }) +}) + +handleMessage('ELECTRON_GUEST_VIEW_MANAGER_SYNC_CALL', function (event, guestInstanceId, method, args) { + try { + const guest = getGuest(guestInstanceId) + if (guest.hostWebContents !== event.sender) { + throw new Error('Access denied') + } + event.returnValue = [null, guest[method].apply(guest, args)] + } catch (error) { + event.returnValue = [errorUtils.serialize(error)] + } +}) + // Returns WebContents from its guest id. const getGuest = function (guestInstanceId) { const guestInstance = guestInstances[guestInstanceId] diff --git a/lib/browser/rpc-server.js b/lib/browser/rpc-server.js index a9ed670add1f..a75a78b01c63 100644 --- a/lib/browser/rpc-server.js +++ b/lib/browser/rpc-server.js @@ -413,40 +413,6 @@ handleRemoteCommand('ELECTRON_BROWSER_GUEST_WEB_CONTENTS', function (event, cont return valueToMeta(event.sender, contextId, guestViewManager.getGuest(guestInstanceId)) }) -ipcMain.on('ELECTRON_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', function (event, requestId, guestInstanceId, method, args, hasCallback) { - new Promise(resolve => { - const guestViewManager = require('@electron/internal/browser/guest-view-manager') - const guest = guestViewManager.getGuest(guestInstanceId) - if (guest.hostWebContents !== event.sender) { - throw new Error('Access denied') - } - if (hasCallback) { - guest[method](...args, resolve) - } else { - resolve(guest[method](...args)) - } - }).then(result => { - return [null, result] - }, error => { - return [errorUtils.serialize(error)] - }).then(responseArgs => { - event.sender._sendInternal(`ELECTRON_RENDERER_ASYNC_CALL_TO_GUEST_VIEW_RESPONSE_${requestId}`, ...responseArgs) - }) -}) - -ipcMain.on('ELECTRON_BROWSER_SYNC_CALL_TO_GUEST_VIEW', function (event, guestInstanceId, method, args) { - try { - const guestViewManager = require('@electron/internal/browser/guest-view-manager') - const guest = guestViewManager.getGuest(guestInstanceId) - if (guest.hostWebContents !== event.sender) { - throw new Error('Access denied') - } - event.returnValue = [null, guest[method].apply(guest, args)] - } catch (error) { - event.returnValue = [errorUtils.serialize(error)] - } -}) - // Implements window.close() ipcMain.on('ELECTRON_BROWSER_WINDOW_CLOSE', function (event) { const window = event.sender.getOwnerBrowserWindow() diff --git a/lib/renderer/web-view/web-view-attributes.js b/lib/renderer/web-view/web-view-attributes.js index 7a7c84e38286..e9a5d9b0952e 100644 --- a/lib/renderer/web-view/web-view-attributes.js +++ b/lib/renderer/web-view/web-view-attributes.js @@ -186,7 +186,7 @@ class SrcAttribute extends WebViewAttribute { const method = 'loadURL' const args = [this.getValue(), opts] - const [error] = ipcRenderer.sendSync('ELECTRON_BROWSER_SYNC_CALL_TO_GUEST_VIEW', guestInstanceId, method, args) + const [error] = ipcRenderer.sendSync('ELECTRON_GUEST_VIEW_MANAGER_SYNC_CALL', guestInstanceId, method, args) if (error) { throw errorUtils.deserialize(error) } diff --git a/lib/renderer/web-view/web-view.js b/lib/renderer/web-view/web-view.js index 99c737a1448d..cf07522fcfdb 100644 --- a/lib/renderer/web-view/web-view.js +++ b/lib/renderer/web-view/web-view.js @@ -306,7 +306,7 @@ const registerWebViewElement = function () { // Forward proto.foo* method calls to WebViewImpl.foo*. const createBlockHandler = function (method) { return function (...args) { - const [error, result] = ipcRenderer.sendSync('ELECTRON_BROWSER_SYNC_CALL_TO_GUEST_VIEW', getGuestInstanceId(this), method, args) + const [error, result] = ipcRenderer.sendSync('ELECTRON_GUEST_VIEW_MANAGER_SYNC_CALL', getGuestInstanceId(this), method, args) if (error) { throw errorUtils.deserialize(error) } else { @@ -322,14 +322,14 @@ const registerWebViewElement = function () { return function (...args) { const callback = (typeof args[args.length - 1] === 'function') ? args.pop() : null const requestId = getNextId() - ipcRenderer.once(`ELECTRON_RENDERER_ASYNC_CALL_TO_GUEST_VIEW_RESPONSE_${requestId}`, function (event, error, result) { + ipcRenderer.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) } }) - ipcRenderer.send('ELECTRON_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', requestId, getGuestInstanceId(this), method, args, callback != null) + ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_ASYNC_CALL', requestId, getGuestInstanceId(this), method, args, callback != null) } } for (const method of nonblockMethods) {