diff --git a/atom/renderer/atom_sandboxed_renderer_client.cc b/atom/renderer/atom_sandboxed_renderer_client.cc index ca66298fce10..042a89bf839d 100644 --- a/atom/renderer/atom_sandboxed_renderer_client.cc +++ b/atom/renderer/atom_sandboxed_renderer_client.cc @@ -92,6 +92,12 @@ void InitializeBindings(v8::Local binding, b.SetMethod("getHeapStatistics", &AtomBindings::GetHeapStatistics); b.SetMethod("getProcessMemoryInfo", &AtomBindings::GetProcessMemoryInfo); b.SetMethod("getSystemMemoryInfo", &AtomBindings::GetSystemMemoryInfo); + + // Pass in CLI flags needed to setup the renderer + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kGuestInstanceID)) + b.Set(options::kGuestInstanceID, + command_line->GetSwitchValueASCII(switches::kGuestInstanceID)); } class AtomSandboxedRenderFrameObserver : public AtomRenderFrameObserver { diff --git a/lib/browser/guest-view-manager.js b/lib/browser/guest-view-manager.js index 28f1f4894b6e..da2663e6060a 100644 --- a/lib/browser/guest-view-manager.js +++ b/lib/browser/guest-view-manager.js @@ -240,6 +240,23 @@ const attachGuest = function (event, elementInstanceId, guestInstanceId, params) webPreferences.disablePopups = true } + // Security options that guest will always inherit from embedder + const inheritedWebPreferences = new Map([ + ['contextIsolation', true], + ['javascript', false], + ['nativeWindowOpen', true], + ['nodeIntegration', false], + ['sandbox', true] + ]) + + // Inherit certain option values from embedder + const lastWebPreferences = embedder.getLastWebPreferences() + for (const [name, value] of inheritedWebPreferences) { + if (lastWebPreferences[name] === value) { + webPreferences[name] = value + } + } + embedder.emit('will-attach-webview', event, webPreferences, params) if (event.defaultPrevented) { if (guest.viewInstanceId == null) guest.viewInstanceId = params.instanceId diff --git a/lib/sandboxed_renderer/init.js b/lib/sandboxed_renderer/init.js index dcb1357d30ee..d4d63cf2fca5 100644 --- a/lib/sandboxed_renderer/init.js +++ b/lib/sandboxed_renderer/init.js @@ -78,6 +78,16 @@ if (window.location.protocol === 'chrome-devtools:') { require('../renderer/inspector') } +if (binding.guestInstanceId) { + process.guestInstanceId = parseInt(binding.guestInstanceId) +} + +if (!process.guestInstanceId && preloadProcess.argv.indexOf('--webview-tag=true') !== -1) { + // don't allow recursive `` + require('../renderer/web-view/web-view') + require('../renderer/web-view/web-view-attributes') +} + // Wrap the script into a function executed in global scope. It won't have // access to the current scope, so we'll expose a few objects as arguments: // diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index 4c4f8c681610..36b98f5ff742 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -8,7 +8,7 @@ const os = require('os') const qs = require('querystring') const http = require('http') const {closeWindow} = require('./window-helpers') - +const {emittedOnce} = require('./events-helpers') const {ipcRenderer, remote, screen} = require('electron') const {app, ipcMain, BrowserWindow, BrowserView, protocol, session, webContents} = remote @@ -1581,6 +1581,23 @@ describe('BrowserWindow module', () => { }) w.loadURL('file://' + path.join(fixtures, 'api', 'preload.html')) }) + + it('webview in sandbox renderer', async () => { + w.destroy() + w = new BrowserWindow({ + show: false, + webPreferences: { + sandbox: true, + preload: preload, + webviewTag: true + } + }) + w.loadURL(`file://${fixtures}/pages/webview-did-attach-event.html`) + + const [, webContents] = await emittedOnce(w.webContents, 'did-attach-webview') + const [, id] = await emittedOnce(ipcMain, 'webview-dom-ready') + expect(webContents.id).to.equal(id) + }) }) describe('nativeWindowOpen option', () => {