fix: load window-setup in sandboxed renderer (#21416)

This commit is contained in:
Milan Burda 2020-01-06 22:23:03 +01:00 committed by Alexey Kuzmin
parent d56f67b7af
commit 31c93fec67
7 changed files with 89 additions and 61 deletions

View file

@ -75,8 +75,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
}

View file

@ -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,

View file

@ -177,7 +177,7 @@ class BrowserWindowProxy {
export const windowSetup = (
guestInstanceId: number, openerId: number, isHiddenPage: boolean, usesNativeWindowOpen: boolean
) => {
if (guestInstanceId == null) {
if (!process.sandboxed && guestInstanceId == null) {
// Override default window.close.
window.close = function () {
ipcRendererInternal.send('ELECTRON_BROWSER_WINDOW_CLOSE')
@ -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().
@ -208,43 +208,47 @@ export const windowSetup = (
throw new Error('prompt() is and will not be supported.')
}
ipcRendererInternal.on('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function (
_event, sourceId: number, message: any, sourceOrigin: string
) {
// Manually dispatch event instead of using postMessage because we also need to
// set event.source.
//
// Why any? We can't construct a MessageEvent and we can't
// use `as MessageEvent` because you're not supposed to override
// data, origin, and source
const event: any = document.createEvent('Event')
event.initEvent('message', false, false)
if (!usesNativeWindowOpen || openerId != null) {
ipcRendererInternal.on('ELECTRON_GUEST_WINDOW_POSTMESSAGE', function (
_event, sourceId: number, message: any, sourceOrigin: string
) {
// Manually dispatch event instead of using postMessage because we also need to
// set event.source.
//
// Why any? We can't construct a MessageEvent and we can't
// use `as MessageEvent` because you're not supposed to override
// data, origin, and source
const event: any = document.createEvent('Event')
event.initEvent('message', false, false)
event.data = message
event.origin = sourceOrigin
event.source = getOrCreateProxy(sourceId)
event.data = message
event.origin = sourceOrigin
event.source = getOrCreateProxy(sourceId)
window.dispatchEvent(event as MessageEvent)
})
window.history.back = function () {
ipcRendererInternal.send('ELECTRON_NAVIGATION_CONTROLLER_GO_BACK')
window.dispatchEvent(event as MessageEvent)
})
}
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')
},
set () {}
})
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')
},
set () {}
})
}
if (guestInstanceId != null) {
// Webview `document.visibilityState` tracks window visibility (and ignores

View file

@ -30,7 +30,13 @@ 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 +115,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 +138,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 +149,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:
//