diff --git a/filenames.auto.gni b/filenames.auto.gni index 1eee5335546ea..27af484c8c02f 100644 --- a/filenames.auto.gni +++ b/filenames.auto.gni @@ -165,6 +165,7 @@ auto_filenames = { "lib/renderer/web-view/web-view-element.ts", "lib/renderer/web-view/web-view-impl.ts", "lib/renderer/web-view/web-view-init.ts", + "lib/renderer/window-setup.ts", "lib/sandboxed_renderer/api/exports/electron.ts", "lib/sandboxed_renderer/api/module-list.ts", "lib/sandboxed_renderer/init.js", diff --git a/lib/browser/guest-window-manager.js b/lib/browser/guest-window-manager.js index 66861a55c389a..12acfb2cc233e 100644 --- a/lib/browser/guest-window-manager.js +++ b/lib/browser/guest-window-manager.js @@ -74,8 +74,10 @@ const mergeBrowserWindowOptions = function (embedder, options) { } } - // Sets correct openerId here to give correct options to 'new-window' event handler - options.webPreferences.openerId = embedder.id + if (!webPreferences.nativeWindowOpen) { + // Sets correct openerId here to give correct options to 'new-window' event handler + options.webPreferences.openerId = embedder.id + } return options } diff --git a/lib/browser/rpc-server.js b/lib/browser/rpc-server.js index cfcbaa09926cb..f2514df63e194 100644 --- a/lib/browser/rpc-server.js +++ b/lib/browser/rpc-server.js @@ -112,11 +112,15 @@ ipcMainUtils.handleSync('ELECTRON_BROWSER_SANDBOX_LOAD', async function (event) contentScripts = getContentScripts() } + const webPreferences = event.sender.getLastWebPreferences() || {} + return { contentScripts, preloadScripts: await Promise.all(preloadPaths.map(path => getPreloadScript(path))), isRemoteModuleEnabled: isRemoteModuleEnabled(event.sender), isWebViewTagEnabled: guestViewManager.isWebViewTagEnabled(event.sender), + guestInstanceId: webPreferences.guestInstanceId, + openerId: webPreferences.openerId, process: { arch: process.arch, platform: process.platform, diff --git a/lib/renderer/window-setup.ts b/lib/renderer/window-setup.ts index 813ecc5e31370..205e4d524c9ec 100644 --- a/lib/renderer/window-setup.ts +++ b/lib/renderer/window-setup.ts @@ -197,10 +197,10 @@ export const windowSetup = ( return null } } + } - if (openerId != null) { - window.opener = getOrCreateProxy(openerId) - } + if (openerId != null) { + window.opener = getOrCreateProxy(openerId) } // But we do not support prompt(). @@ -227,23 +227,25 @@ export const windowSetup = ( window.dispatchEvent(event as MessageEvent) }) - window.history.back = function () { - ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_BACK') - } - - window.history.forward = function () { - ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_FORWARD') - } + if (!process.sandboxed) { + window.history.back = function () { + ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_BACK') + } - window.history.go = function (offset: number) { - ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_TO_OFFSET', +offset) - } + window.history.forward = function () { + ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_FORWARD') + } - Object.defineProperty(window.history, 'length', { - get: function () { - return ipcRendererInternal.sendSync('ELECTRON_NAVIGATION_CONTROLLER_LENGTH') + window.history.go = function (offset: number) { + ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_TO_OFFSET', +offset) } - }) + + Object.defineProperty(window.history, 'length', { + get: function () { + return ipcRendererInternal.sendSync('ELECTRON_NAVIGATION_CONTROLLER_LENGTH') + } + }) + } if (guestInstanceId != null) { // Webview `document.visibilityState` tracks window visibility (and ignores diff --git a/lib/sandboxed_renderer/init.js b/lib/sandboxed_renderer/init.js index 9bdd726992c6f..c1fde8ca464f3 100644 --- a/lib/sandboxed_renderer/init.js +++ b/lib/sandboxed_renderer/init.js @@ -30,7 +30,7 @@ const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-rendere const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils') const { - contentScripts, preloadScripts, isRemoteModuleEnabled, isWebViewTagEnabled, process: processProps + contentScripts, preloadScripts, isRemoteModuleEnabled, isWebViewTagEnabled, guestInstanceId, openerId, process: processProps } = ipcRendererUtils.invokeSync('ELECTRON_BROWSER_SANDBOX_LOAD') process.isRemoteModuleEnabled = isRemoteModuleEnabled @@ -109,6 +109,11 @@ function preloadRequire (module) { const { hasSwitch } = process.electronBinding('command_line') const contextIsolation = hasSwitch('context-isolation') +const isHiddenPage = hasSwitch('hidden-page') +const usesNativeWindowOpen = true + +// The arguments to be passed to isolated world. +const isolatedWorldArgs = { ipcRendererInternal, guestInstanceId, isHiddenPage, openerId, usesNativeWindowOpen } switch (window.location.protocol) { case 'devtools:': { @@ -127,6 +132,10 @@ switch (window.location.protocol) { break } default: { + // Override default web functions. + const { windowSetup } = require('@electron/internal/renderer/window-setup') + windowSetup(guestInstanceId, openerId, isHiddenPage, usesNativeWindowOpen) + // Inject content scripts. if (!process.electronBinding('features').isExtensionsEnabled()) { require('@electron/internal/renderer/content-scripts-injector')(contentScripts) @@ -134,14 +143,17 @@ switch (window.location.protocol) { } } -const guestInstanceId = binding.guestInstanceId && parseInt(binding.guestInstanceId) - // Load webview tag implementation. if (process.isMainFrame) { const { webViewInit } = require('@electron/internal/renderer/web-view/web-view-init') webViewInit(contextIsolation, isWebViewTagEnabled, guestInstanceId) } +// Pass the arguments to isolatedWorld. +if (contextIsolation) { + v8Util.setHiddenValue(global, 'isolated-world-args', isolatedWorldArgs) +} + // 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/shell/renderer/atom_sandboxed_renderer_client.cc b/shell/renderer/atom_sandboxed_renderer_client.cc index 58efed622b096..a781b17103331 100644 --- a/shell/renderer/atom_sandboxed_renderer_client.cc +++ b/shell/renderer/atom_sandboxed_renderer_client.cc @@ -141,12 +141,6 @@ void AtomSandboxedRendererClient::InitializeBindings( process.SetReadOnly("sandboxed", true); process.SetReadOnly("type", "renderer"); process.SetReadOnly("isMainFrame", is_main_frame); - - // 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)); } void AtomSandboxedRendererClient::RenderFrameCreated( diff --git a/spec-main/chromium-spec.ts b/spec-main/chromium-spec.ts index b85e0c2a5fc87..c70b53704c24a 100644 --- a/spec-main/chromium-spec.ts +++ b/spec-main/chromium-spec.ts @@ -687,22 +687,27 @@ describe('chromium features', () => { describe('when opened from main window', () => { for (const { parent, child, nodeIntegration, nativeWindowOpen, openerAccessible } of table) { - const description = `when parent=${s(parent)} opens child=${s(child)} with nodeIntegration=${nodeIntegration} nativeWindowOpen=${nativeWindowOpen}, child should ${openerAccessible ? '' : 'not '}be able to access opener` - it(description, async () => { - const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true, nativeWindowOpen } }) - await w.loadURL(parent) - const childOpenerLocation = await w.webContents.executeJavaScript(`new Promise(resolve => { - window.addEventListener('message', function f(e) { - resolve(e.data) + for (const sandboxPopup of [false, true]) { + const description = `when parent=${s(parent)} opens child=${s(child)} with nodeIntegration=${nodeIntegration} nativeWindowOpen=${nativeWindowOpen} sandboxPopup=${sandboxPopup}, child should ${openerAccessible ? '' : 'not '}be able to access opener` + it(description, async () => { + const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true, nativeWindowOpen } }) + w.webContents.once('new-window', (e, url, frameName, disposition, options) => { + options!.webPreferences!.sandbox = sandboxPopup }) - window.open(${JSON.stringify(child)}, "", "show=no,nodeIntegration=${nodeIntegration ? 'yes' : 'no'}") - })`) - if (openerAccessible) { - expect(childOpenerLocation).to.be.a('string') - } else { - expect(childOpenerLocation).to.be.null() - } - }) + await w.loadURL(parent) + const childOpenerLocation = await w.webContents.executeJavaScript(`new Promise(resolve => { + window.addEventListener('message', function f(e) { + resolve(e.data) + }) + window.open(${JSON.stringify(child)}, "", "show=no,nodeIntegration=${nodeIntegration ? 'yes' : 'no'}") + })`) + if (openerAccessible) { + expect(childOpenerLocation).to.be.a('string') + } else { + expect(childOpenerLocation).to.be.null() + } + }) + } } })