feat: add webPreferences.enableRemoteModule option (#13028)

This commit is contained in:
Milan Burda 2018-10-13 19:50:07 +02:00 committed by Alexey Kuzmin
parent 72db5ed7cb
commit d3efc52745
36 changed files with 303 additions and 45 deletions

View file

@ -209,6 +209,7 @@ const attachGuest = function (event, embedderFrameId, elementInstanceId, guestIn
const webPreferences = {
guestInstanceId: guestInstanceId,
nodeIntegration: params.nodeintegration != null ? params.nodeintegration : false,
enableRemoteModule: params.enableremotemodule,
plugins: params.plugins,
zoomFactor: embedder._getZoomFactor(),
webSecurity: !params.disablewebsecurity,
@ -243,6 +244,7 @@ const attachGuest = function (event, embedderFrameId, elementInstanceId, guestIn
['javascript', false],
['nativeWindowOpen', true],
['nodeIntegration', false],
['enableRemoteModule', false],
['sandbox', true]
])

View file

@ -14,6 +14,7 @@ const inheritedWebPreferences = new Map([
['javascript', false],
['nativeWindowOpen', true],
['nodeIntegration', false],
['enableRemoteModule', false],
['sandbox', true],
['webviewTag', false]
])
@ -195,7 +196,7 @@ ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_WINDOW_OPEN', (event, url, frameName,
const options = {}
const ints = ['x', 'y', 'width', 'height', 'minWidth', 'maxWidth', 'minHeight', 'maxHeight', 'zoomFactor']
const webPreferences = ['zoomFactor', 'nodeIntegration', 'preload', 'javascript', 'contextIsolation', 'webviewTag']
const webPreferences = ['zoomFactor', 'nodeIntegration', 'enableRemoteModule', 'preload', 'javascript', 'contextIsolation', 'webviewTag']
const disposition = 'new-window'
// Used to store additional features

View file

@ -263,11 +263,17 @@ const callFunction = function (event, contextId, func, caller, args) {
const handleRemoteCommand = function (channel, handler) {
ipcMain.on(channel, (event, contextId, ...args) => {
let returnValue
if (!event.sender._isRemoteModuleEnabled()) {
event.returnValue = null
return
}
try {
returnValue = handler(event, contextId, ...args)
} catch (error) {
returnValue = exceptionToMeta(event.sender, contextId, error)
}
if (returnValue !== undefined) {
event.returnValue = returnValue
}
@ -453,12 +459,28 @@ const crashReporterInit = function (options) {
}
}
ipcMain.on('ELECTRON_CRASH_REPORTER_INIT', function (event, options) {
const setReturnValue = function (event, getValue) {
try {
event.returnValue = [null, crashReporterInit(options)]
event.returnValue = [null, getValue()]
} catch (error) {
event.returnValue = [errorUtils.serialize(error)]
}
}
ipcMain.on('ELECTRON_CRASH_REPORTER_INIT', function (event, options) {
setReturnValue(event, () => crashReporterInit(options))
})
ipcMain.on('ELECTRON_BROWSER_GET_LAST_WEB_PREFERENCES', function (event) {
setReturnValue(event, () => event.sender.getLastWebPreferences())
})
ipcMain.on('ELECTRON_BROWSER_CLIPBOARD_READ_FIND_TEXT', function (event) {
setReturnValue(event, () => electron.clipboard.readFindText())
})
ipcMain.on('ELECTRON_BROWSER_CLIPBOARD_WRITE_FIND_TEXT', function (event, text) {
setReturnValue(event, () => electron.clipboard.writeFindText(text))
})
ipcMain.on('ELECTRON_BROWSER_SANDBOX_LOAD', function (event) {
@ -475,6 +497,7 @@ ipcMain.on('ELECTRON_BROWSER_SANDBOX_LOAD', function (event) {
event.returnValue = {
preloadSrc,
preloadError,
isRemoteModuleEnabled: event.sender._isRemoteModuleEnabled(),
process: {
arch: process.arch,
platform: process.platform,
@ -484,11 +507,3 @@ ipcMain.on('ELECTRON_BROWSER_SANDBOX_LOAD', function (event) {
}
}
})
ipcMain.on('ELECTRON_BROWSER_GET_LAST_WEB_PREFERENCES', function (event) {
try {
event.returnValue = [null, event.sender.getLastWebPreferences()]
} catch (error) {
event.returnValue = [errorUtils.serialize(error)]
}
})

View file

@ -2,15 +2,29 @@
if (process.platform === 'linux' && process.type === 'renderer') {
// On Linux we could not access clipboard in renderer process.
module.exports = require('electron').remote.clipboard
const { getRemoteForUsage } = require('@electron/internal/renderer/remote')
module.exports = getRemoteForUsage('clipboard').clipboard
} else {
const clipboard = process.atomBinding('clipboard')
// Read/write to find pasteboard over IPC since only main process is notified
// of changes
if (process.platform === 'darwin' && process.type === 'renderer') {
clipboard.readFindText = require('electron').remote.clipboard.readFindText
clipboard.writeFindText = require('electron').remote.clipboard.writeFindText
const ipcRenderer = require('@electron/internal/renderer/ipc-renderer-internal')
const errorUtils = require('@electron/internal/common/error-utils')
const invoke = function (command, ...args) {
const [ error, result ] = ipcRenderer.sendSync(command, ...args)
if (error) {
throw errorUtils.deserialize(error)
} else {
return result
}
}
clipboard.readFindText = (...args) => invoke('ELECTRON_BROWSER_CLIPBOARD_READ_FIND_TEXT', ...args)
clipboard.writeFindText = (...args) => invoke('ELECTRON_BROWSER_CLIPBOARD_WRITE_FIND_TEXT', ...args)
}
module.exports = clipboard

View file

@ -1,6 +1,9 @@
'use strict'
const features = process.atomBinding('features')
const v8Util = process.atomBinding('v8_util')
const enableRemoteModule = v8Util.getHiddenValue(global, 'enableRemoteModule')
// Renderer side modules, please sort alphabetically.
// A module is `enabled` if there is no explicit condition defined.
@ -11,8 +14,8 @@ module.exports = [
file: 'desktop-capturer',
enabled: features.isDesktopCapturerEnabled()
},
{ name: 'ipcRenderer', file: 'ipc-renderer', enabled: true },
{ name: 'remote', file: 'remote', enabled: true },
{ name: 'screen', file: 'screen', enabled: true },
{ name: 'webFrame', file: 'web-frame', enabled: true }
{ name: 'ipcRenderer', file: 'ipc-renderer' },
{ name: 'remote', file: 'remote', enabled: enableRemoteModule },
{ name: 'screen', file: 'screen' },
{ name: 'webFrame', file: 'web-frame' }
]

View file

@ -1,3 +1,4 @@
'use strict'
module.exports = require('electron').remote.screen
const { getRemoteForUsage } = require('@electron/internal/renderer/remote')
module.exports = getRemoteForUsage('screen').screen

10
lib/renderer/remote.js Normal file
View file

@ -0,0 +1,10 @@
'use strict'
const { remote } = require('electron')
exports.getRemoteForUsage = function (usage) {
if (!remote) {
throw new Error(`${usage} requires remote, which is not enabled`)
}
return remote
}

View file

@ -248,6 +248,20 @@ class WebPreferencesAttribute extends WebViewAttribute {
}
}
class EnableRemoteModuleAttribute extends WebViewAttribute {
constructor (webViewImpl) {
super(webViewConstants.ATTRIBUTE_ENABLEREMOTEMODULE, webViewImpl)
}
getValue () {
return this.webViewImpl.webviewNode.getAttribute(this.name) !== 'false'
}
setValue (value) {
this.webViewImpl.webviewNode.setAttribute(this.name, value ? 'true' : 'false')
}
}
// Sets up all of the webview attributes.
WebViewImpl.prototype.setupWebViewAttributes = function () {
this.attributes = {}
@ -259,6 +273,7 @@ WebViewImpl.prototype.setupWebViewAttributes = function () {
this.attributes[webViewConstants.ATTRIBUTE_PLUGINS] = new BooleanAttribute(webViewConstants.ATTRIBUTE_PLUGINS, this)
this.attributes[webViewConstants.ATTRIBUTE_DISABLEWEBSECURITY] = new BooleanAttribute(webViewConstants.ATTRIBUTE_DISABLEWEBSECURITY, this)
this.attributes[webViewConstants.ATTRIBUTE_ALLOWPOPUPS] = new BooleanAttribute(webViewConstants.ATTRIBUTE_ALLOWPOPUPS, this)
this.attributes[webViewConstants.ATTRIBUTE_ENABLEREMOTEMODULE] = new EnableRemoteModuleAttribute(this)
this.attributes[webViewConstants.ATTRIBUTE_PRELOAD] = new PreloadAttribute(this)
this.attributes[webViewConstants.ATTRIBUTE_BLINKFEATURES] = new BlinkFeaturesAttribute(this)
this.attributes[webViewConstants.ATTRIBUTE_DISABLEBLINKFEATURES] = new DisableBlinkFeaturesAttribute(this)

View file

@ -7,6 +7,7 @@ module.exports = {
ATTRIBUTE_SRC: 'src',
ATTRIBUTE_HTTPREFERRER: 'httpreferrer',
ATTRIBUTE_NODEINTEGRATION: 'nodeintegration',
ATTRIBUTE_ENABLEREMOTEMODULE: 'enableremotemodule',
ATTRIBUTE_PLUGINS: 'plugins',
ATTRIBUTE_DISABLEWEBSECURITY: 'disablewebsecurity',
ATTRIBUTE_ALLOWPOPUPS: 'allowpopups',

View file

@ -1,6 +1,6 @@
'use strict'
const { remote, webFrame } = require('electron')
const { webFrame } = require('electron')
const v8Util = process.atomBinding('v8_util')
const ipcRenderer = require('@electron/internal/renderer/ipc-renderer-internal')
@ -337,6 +337,8 @@ const registerWebViewElement = function () {
// WebContents associated with this webview.
proto.getWebContents = function () {
const { getRemoteForUsage } = require('@electron/internal/renderer/remote')
const remote = getRemoteForUsage('getWebContents()')
const internal = v8Util.getHiddenValue(this, 'internal')
if (!internal.guestInstanceId) {
internal.createGuestSync()

View file

@ -1,3 +1,4 @@
'use strict'
module.exports = require('electron').remote.require('child_process')
const { getRemoteForUsage } = require('@electron/internal/renderer/remote')
module.exports = getRemoteForUsage('child_process').require('child_process')

View file

@ -6,6 +6,7 @@ for (const {
name,
load,
enabled = true,
configurable = false,
private: isPrivate = false
} of moduleList) {
if (!enabled) {
@ -13,6 +14,7 @@ for (const {
}
Object.defineProperty(exports, name, {
configurable,
enumerable: !isPrivate,
get: load
})

View file

@ -1,3 +1,4 @@
'use strict'
module.exports = require('electron').remote.require('fs')
const { getRemoteForUsage } = require('@electron/internal/renderer/remote')
module.exports = getRemoteForUsage('fs').require('fs')

View file

@ -1,3 +1,4 @@
'use strict'
module.exports = require('electron').remote.require('os')
const { getRemoteForUsage } = require('@electron/internal/renderer/remote')
module.exports = getRemoteForUsage('os').require('os')

View file

@ -1,3 +1,4 @@
'use strict'
module.exports = require('electron').remote.require('path')
const { getRemoteForUsage } = require('@electron/internal/renderer/remote')
module.exports = getRemoteForUsage('path').require('path')

View file

@ -16,21 +16,28 @@ module.exports = [
name: 'ipcRenderer',
load: () => require('@electron/internal/renderer/api/ipc-renderer')
},
{
name: 'isPromise',
load: () => require('@electron/internal/common/api/is-promise'),
private: true
},
{
name: 'nativeImage',
load: () => require('@electron/internal/common/api/native-image')
},
{
name: 'remote',
configurable: true, // will be configured in init.js
load: () => require('@electron/internal/renderer/api/remote')
},
{
name: 'webFrame',
load: () => require('@electron/internal/renderer/api/web-frame')
},
// The internal modules, invisible unless you know their names.
{
name: 'deprecate',
load: () => require('@electron/internal/common/api/deprecate'),
private: true
},
{
name: 'isPromise',
load: () => require('@electron/internal/common/api/is-promise'),
private: true
}
]

View file

@ -63,9 +63,21 @@ ipcNative.onExit = function () {
}
const {
preloadSrc, preloadError, process: processProps
preloadSrc, preloadError, isRemoteModuleEnabled, process: processProps
} = ipcRenderer.sendSync('ELECTRON_BROWSER_SANDBOX_LOAD')
const makePropertyNonConfigurable = function (object, name) {
const descriptor = Object.getOwnPropertyDescriptor(electron, name)
descriptor.configurable = false
Object.defineProperty(electron, name, descriptor)
}
if (isRemoteModuleEnabled) {
makePropertyNonConfigurable(electron, 'remote')
} else {
delete electron.remote
}
require('@electron/internal/renderer/web-frame-init')()
// Pass different process object to the preload script(which should not have