Skip to content

Commit

Permalink
fix: load window-setup in sandboxed renderer (#21696)
Browse files Browse the repository at this point in the history
  • Loading branch information
miniak authored and zcbenz committed Jan 13, 2020
1 parent 7b1117e commit cbf499b
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 46 deletions.
1 change: 1 addition & 0 deletions filenames.auto.gni
Expand Up @@ -166,6 +166,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.js",
"lib/sandboxed_renderer/api/module-list.js",
"lib/sandboxed_renderer/init.js",
Expand Down
6 changes: 4 additions & 2 deletions lib/browser/guest-window-manager.js
Expand Up @@ -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
}
Expand Down
3 changes: 3 additions & 0 deletions lib/browser/rpc-server.js
Expand Up @@ -529,12 +529,15 @@ ipcMainUtils.handle('ELECTRON_GET_CONTENT_SCRIPTS', () => getContentScripts())

ipcMainUtils.handle('ELECTRON_BROWSER_SANDBOX_LOAD', async function (event) {
const preloadPaths = event.sender._getPreloadPaths()
const webPreferences = event.sender.getLastWebPreferences() || {}

return {
contentScripts: getContentScripts(),
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,
Expand Down
74 changes: 39 additions & 35 deletions lib/renderer/window-setup.ts
Expand Up @@ -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.sendSync('ELECTRON_BROWSER_WINDOW_CLOSE')
Expand All @@ -197,53 +197,57 @@ 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().
window.prompt = function () {
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)

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')
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)

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')
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
Expand Down
24 changes: 21 additions & 3 deletions lib/sandboxed_renderer/init.js
Expand Up @@ -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
Expand Down Expand Up @@ -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:': {
Expand All @@ -125,19 +136,26 @@ 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.
require('@electron/internal/renderer/content-scripts-injector')(contentScripts)
}
}

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)
}

const errorUtils = require('@electron/internal/common/error-utils')

// Wrap the script into a function executed in global scope. It won't have
Expand Down
6 changes: 0 additions & 6 deletions shell/renderer/atom_sandboxed_renderer_client.cc
Expand Up @@ -144,12 +144,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(
Expand Down

0 comments on commit cbf499b

Please sign in to comment.