Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: load window-setup in sandboxed renderer #21696

Merged
merged 1 commit into from Jan 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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