diff --git a/lib/browser/rpc-server.js b/lib/browser/rpc-server.js index 19e3e7edb7d1..5784d2fd31e9 100644 --- a/lib/browser/rpc-server.js +++ b/lib/browser/rpc-server.js @@ -3,6 +3,7 @@ const {Buffer} = require('buffer') const electron = require('electron') const {EventEmitter} = require('events') +const fs = require('fs') const v8Util = process.atomBinding('v8_util') const {ipcMain, isPromise, webContents} = electron @@ -448,3 +449,23 @@ ipcMain.on('ELECTRON_BROWSER_WINDOW_CLOSE', function (event) { } event.returnValue = null }) + +ipcMain.on('ELECTRON_BROWSER_SANDBOX_LOAD', function (event, preloadPath) { + let preloadSrc = null + let preloadError = null + if (preloadPath) { + try { + preloadSrc = fs.readFileSync(preloadPath).toString() + } catch (err) { + preloadError = {stack: err ? err.stack : (new Error(`Failed to load "${preloadPath}"`)).stack} + } + } + event.returnValue = { + preloadSrc: preloadSrc, + preloadError: preloadError, + webContentsId: event.sender.getId(), + platform: process.platform, + execPath: process.execPath, + env: process.env + } +}) diff --git a/lib/renderer/api/remote.js b/lib/renderer/api/remote.js index 15928d836c9e..e1f7156f1ce0 100644 --- a/lib/renderer/api/remote.js +++ b/lib/renderer/api/remote.js @@ -306,10 +306,13 @@ exports.getCurrentWebContents = () => { const CONTEXT_ARG = '--context-id=' let initialContext = process.argv.find(arg => arg.startsWith(CONTEXT_ARG)) -if (initialContext) { +if (process.webContentsId) { + // set by sandbox renderer init script + initialContext = process.webContentsId +} else if (initialContext) { initialContext = parseInt(initialContext.substr(CONTEXT_ARG.length), 10) } else { - // In sandbox we need to pull this from remote + // if not available, pull from remote initialContext = exports.getCurrentWebContents().getId() } diff --git a/lib/sandboxed_renderer/init.js b/lib/sandboxed_renderer/init.js index 8a1e6a9477c3..55426db12252 100644 --- a/lib/sandboxed_renderer/init.js +++ b/lib/sandboxed_renderer/init.js @@ -1,6 +1,7 @@ /* eslint no-eval: "off" */ /* global binding, preloadPath, Buffer */ const events = require('events') +const electron = require('electron') process.atomBinding = require('../common/atom-binding-setup')(binding.get, 'renderer') @@ -20,19 +21,30 @@ for (let prop of Object.keys(events.EventEmitter.prototype)) { } Object.setPrototypeOf(process, events.EventEmitter.prototype) -const electron = require('electron') -const fs = require('fs') -const preloadModules = new Map([ - ['child_process', require('child_process')], +const remoteModules = new Set([ + 'child_process', + 'fs', + 'os', + 'path' +]) + +const loadedModules = new Map([ ['electron', electron], ['events', events], - ['fs', fs], - ['os', require('os')], - ['path', require('path')], - ['url', require('url')], - ['timers', require('timers')] + ['timers', require('timers')], + ['url', require('url')] ]) +const { + preloadSrc, preloadError, webContentsId, platform, execPath, env +} = electron.ipcRenderer.sendSync('ELECTRON_BROWSER_SANDBOX_LOAD', preloadPath) + +Object.defineProperty(process, 'webContentsId', { + configurable: false, + writable: false, + value: webContentsId +}) + require('../renderer/web-frame-init')() // Pass different process object to the preload script(which should not have @@ -43,15 +55,19 @@ preloadProcess.hang = () => binding.hang() preloadProcess.getProcessMemoryInfo = () => binding.getProcessMemoryInfo() preloadProcess.getSystemMemoryInfo = () => binding.getSystemMemoryInfo() preloadProcess.argv = binding.getArgv() -process.platform = preloadProcess.platform = electron.remote.process.platform -process.execPath = preloadProcess.execPath = electron.remote.process.execPath -process.env = preloadProcess.env = electron.remote.process.env +preloadProcess.platform = process.platform = platform +preloadProcess.execPath = process.execPath = execPath +preloadProcess.env = process.env = env + process.on('exit', () => preloadProcess.emit('exit')) // This is the `require` function that will be visible to the preload script function preloadRequire (module) { - if (preloadModules.has(module)) { - return preloadModules.get(module) + if (loadedModules.has(module)) { + return loadedModules.get(module) + } + if (remoteModules.has(module)) { + return require(module) } throw new Error('module not found') } @@ -80,9 +96,8 @@ if (window.location.protocol === 'chrome-devtools:') { // and any `require('electron')` calls in `preload.js` will work as expected // since browserify won't try to include `electron` in the bundle, falling back // to the `preloadRequire` function above. -if (preloadPath) { - const preloadSrc = fs.readFileSync(preloadPath).toString() - const preloadWrapperSrc = `(function(require, process, Buffer, global, setImmediate) { +if (preloadSrc) { + const preloadWrapperSrc = `(function(require, process, Buffer, global, setImmediate, clearImmediate) { ${preloadSrc} })` @@ -90,6 +105,8 @@ if (preloadPath) { // http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.2 const geval = eval const preloadFn = geval(preloadWrapperSrc) - const {setImmediate} = require('timers') - preloadFn(preloadRequire, preloadProcess, Buffer, global, setImmediate) + const {setImmediate, clearImmediate} = require('timers') + preloadFn(preloadRequire, preloadProcess, Buffer, global, setImmediate, clearImmediate) +} else if (preloadError) { + console.error(preloadError.stack) }