fix: <webview> not working with contextIsolation + sandbox (#16469)

This commit is contained in:
Milan Burda 2019-01-22 02:08:16 +01:00 committed by Cheng Zhao
parent a9ac75c1f9
commit b965e54efc
8 changed files with 164 additions and 82 deletions

View file

@ -2,11 +2,11 @@
/* global nodeProcess, isolatedWorld */
// Note: Don't use "process", as it will be replaced by browserify's one.
const v8Util = nodeProcess.atomBinding('v8_util')
const atomBinding = require('@electron/internal/common/atom-binding-setup')(nodeProcess.binding, 'renderer')
const isolatedWorldArgs = v8Util.getHiddenValue(isolatedWorld, 'isolated-world-args')
const { webViewImpl, ipcRenderer, guestInstanceId, isHiddenPage, openerId, usesNativeWindowOpen } = isolatedWorldArgs
const v8Util = atomBinding('v8_util')
const webViewImpl = v8Util.getHiddenValue(isolatedWorld, 'web-view-impl')
if (webViewImpl) {
// Must setup the WebView element in main world.
@ -14,4 +14,9 @@ if (webViewImpl) {
setupWebView(v8Util, webViewImpl)
}
require('@electron/internal/renderer/window-setup')(ipcRenderer, guestInstanceId, openerId, isHiddenPage, usesNativeWindowOpen)
const isolatedWorldArgs = v8Util.getHiddenValue(isolatedWorld, 'isolated-world-args')
if (isolatedWorldArgs) {
const { ipcRenderer, guestInstanceId, isHiddenPage, openerId, usesNativeWindowOpen } = isolatedWorldArgs
require('@electron/internal/renderer/window-setup')(ipcRenderer, guestInstanceId, openerId, isHiddenPage, usesNativeWindowOpen)
}

View file

@ -58,33 +58,29 @@ if (preloadScript) {
preloadScripts.push(preloadScript)
}
if (window.location.protocol === 'chrome-devtools:') {
// Override some inspector APIs.
require('@electron/internal/renderer/inspector')
} else if (window.location.protocol === 'chrome-extension:') {
// Add implementations of chrome API.
require('@electron/internal/renderer/chrome-api').injectTo(window.location.hostname, isBackgroundPage, window)
} else if (window.location.protocol === 'chrome:') {
// Disable node integration for chrome UI scheme.
} else {
// Override default web functions.
require('@electron/internal/renderer/window-setup')(ipcRenderer, guestInstanceId, openerId, isHiddenPage, usesNativeWindowOpen)
switch (window.location.protocol) {
case 'chrome-devtools:': {
// Override some inspector APIs.
require('@electron/internal/renderer/inspector')
break
}
case 'chrome-extension:': {
// Inject the chrome.* APIs that chrome extensions require
require('@electron/internal/renderer/chrome-api').injectTo(window.location.hostname, isBackgroundPage, window)
break
}
default: {
// Override default web functions.
require('@electron/internal/renderer/window-setup')(ipcRenderer, guestInstanceId, openerId, isHiddenPage, usesNativeWindowOpen)
// Inject content scripts.
require('@electron/internal/renderer/content-scripts-injector')
// Load webview tag implementation.
if (webviewTag && guestInstanceId == null) {
const webViewImpl = require('@electron/internal/renderer/web-view/web-view-impl')
if (contextIsolation) {
Object.assign(isolatedWorldArgs, { webViewImpl })
} else {
const { setupWebView } = require('@electron/internal/renderer/web-view/web-view-element')
setupWebView(v8Util, webViewImpl)
}
// Inject content scripts.
require('@electron/internal/renderer/content-scripts-injector')
}
}
// Load webview tag implementation.
require('@electron/internal/renderer/web-view/web-view-init')(contextIsolation, webviewTag, guestInstanceId)
// Pass the arguments to isolatedWorld.
if (contextIsolation) {
v8Util.setHiddenValue(global, 'isolated-world-args', isolatedWorldArgs)
@ -163,15 +159,3 @@ for (const preloadScript of preloadScripts) {
// Warn about security issues
require('@electron/internal/renderer/security-warnings')(nodeIntegration)
// Report focus/blur events of webview to browser.
// Note that while Chromium content APIs have observer for focus/blur, they
// unfortunately do not work for webview.
if (guestInstanceId) {
window.addEventListener('focus', () => {
ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', true, guestInstanceId)
})
window.addEventListener('blur', () => {
ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', false, guestInstanceId)
})
}

View file

@ -0,0 +1,35 @@
'use strict'
const ipcRenderer = require('@electron/internal/renderer/ipc-renderer-internal')
const v8Util = process.atomBinding('v8_util')
function handleFocusBlur (guestInstanceId) {
// Note that while Chromium content APIs have observer for focus/blur, they
// unfortunately do not work for webview.
window.addEventListener('focus', () => {
ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', true, guestInstanceId)
})
window.addEventListener('blur', () => {
ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', false, guestInstanceId)
})
}
module.exports = function (contextIsolation, webviewTag, guestInstanceId) {
// Load webview tag implementation.
if (webviewTag && guestInstanceId == null) {
const webViewImpl = require('@electron/internal/renderer/web-view/web-view-impl')
if (contextIsolation) {
v8Util.setHiddenValue(window, 'web-view-impl', webViewImpl)
} else {
const { setupWebView } = require('@electron/internal/renderer/web-view/web-view-element')
setupWebView(v8Util, webViewImpl)
}
}
if (guestInstanceId) {
// Report focus/blur events of webview to browser.
handleFocusBlur(guestInstanceId)
}
}

View file

@ -105,8 +105,12 @@ function preloadRequire (module) {
throw new Error('module not found')
}
// Process command line arguments.
const { hasSwitch } = process.atomBinding('command_line')
const isBackgroundPage = hasSwitch('background-page')
const contextIsolation = hasSwitch('context-isolation')
switch (window.location.protocol) {
case 'chrome-devtools:': {
// Override some inspector APIs.
@ -115,22 +119,15 @@ switch (window.location.protocol) {
}
case 'chrome-extension:': {
// Inject the chrome.* APIs that chrome extensions require
const isBackgroundPage = hasSwitch('background-page')
require('@electron/internal/renderer/chrome-api').injectTo(window.location.hostname, isBackgroundPage, window)
break
}
}
if (binding.guestInstanceId) {
process.guestInstanceId = parseInt(binding.guestInstanceId)
}
const guestInstanceId = binding.guestInstanceId && parseInt(binding.guestInstanceId)
// Don't allow recursive `<webview>`.
if (!process.guestInstanceId && isWebViewTagEnabled) {
const webViewImpl = require('@electron/internal/renderer/web-view/web-view-impl')
const { setupWebView } = require('@electron/internal/renderer/web-view/web-view-element')
setupWebView(v8Util, webViewImpl)
}
// Load webview tag implementation.
require('@electron/internal/renderer/web-view/web-view-init')(contextIsolation, isWebViewTagEnabled, guestInstanceId)
const errorUtils = require('@electron/internal/common/error-utils')