fix: register webview in main world when using contextIsolation (#16067)

This commit is contained in:
Cheng Zhao 2018-12-14 15:38:35 +09:00 committed by GitHub
parent dbda1a1b05
commit 8584c2f14b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 56 additions and 20 deletions

View file

@ -75,6 +75,9 @@ npm_action("atom_browserify_sandbox") {
]
inputs = [
# FIXME(zcbenz): The dependencies of these files are not listed here, so
# the generated file will be out-dated when dependencies are modified.
# Use a script to generate all dependencies and put them here.
"lib/sandboxed_renderer/init.js",
"lib/sandboxed_renderer/api/exports/electron.js",
"lib/sandboxed_renderer/api/exports/fs.js",

View file

@ -189,8 +189,10 @@ void WebFrame::SetLayoutZoomLevelLimits(double min_level, double max_level) {
}
v8::Local<v8::Value> WebFrame::RegisterEmbedderCustomElement(
v8::Local<v8::Object> context,
const base::string16& name,
v8::Local<v8::Object> options) {
v8::Context::Scope context_scope(context->CreationContext());
return web_frame_->GetDocument().RegisterEmbedderCustomElement(
blink::WebString::FromUTF16(name), options);
}

View file

@ -51,6 +51,7 @@ class WebFrame : public mate::Wrappable<WebFrame> {
void SetLayoutZoomLevelLimits(double min_level, double max_level);
v8::Local<v8::Value> RegisterEmbedderCustomElement(
v8::Local<v8::Object> context,
const base::string16& name,
v8::Local<v8::Object> options);
int GetWebFrameId(v8::Local<v8::Value> content_window);

View file

@ -2,9 +2,16 @@
/* global nodeProcess, isolatedWorld */
window.isolatedWorld = isolatedWorld
// Note: Don't use "process", as it will be replaced by browserify's one.
const v8Util = nodeProcess.atomBinding('v8_util')
const setupWebView = v8Util.getHiddenValue(isolatedWorld, 'setup-webview')
if (setupWebView) {
setupWebView(window)
}
const isolatedWorldArgs = v8Util.getHiddenValue(isolatedWorld, 'isolated-world-args')
const { ipcRenderer, guestInstanceId, hiddenPage, openerId, usesNativeWindowOpen } = isolatedWorldArgs

View file

@ -98,8 +98,12 @@ if (window.location.protocol === 'chrome-devtools:') {
// Load webview tag implementation.
if (webviewTag && guestInstanceId == null) {
require('@electron/internal/renderer/web-view/web-view')
require('@electron/internal/renderer/web-view/web-view-attributes')
const { setupWebView } = require('@electron/internal/renderer/web-view/web-view')
if (contextIsolation) {
v8Util.setHiddenValue(window, 'setup-webview', setupWebView)
} else {
setupWebView(window)
}
}
}

View file

@ -1,7 +1,7 @@
'use strict'
const ipcRenderer = require('@electron/internal/renderer/ipc-renderer-internal')
const WebViewImpl = require('@electron/internal/renderer/web-view/web-view')
const { WebViewImpl } = require('@electron/internal/renderer/web-view/web-view')
const webViewConstants = require('@electron/internal/renderer/web-view/web-view-constants')
const errorUtils = require('@electron/internal/common/error-utils')
@ -86,13 +86,13 @@ class PartitionAttribute extends WebViewAttribute {
// The partition cannot change if the webview has already navigated.
if (!this.webViewImpl.beforeFirstNavigation) {
window.console.error(webViewConstants.ERROR_MSG_ALREADY_NAVIGATED)
console.error(webViewConstants.ERROR_MSG_ALREADY_NAVIGATED)
this.setValueIgnoreMutation(oldValue)
return
}
if (newValue === 'persist:') {
this.validPartitionId = false
window.console.error(webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE)
console.error(webViewConstants.ERROR_MSG_INVALID_PARTITION_ATTRIBUTE)
}
}
}

View file

@ -198,8 +198,8 @@ class WebViewImpl {
}
// Registers <webview> custom element.
const registerWebViewElement = function () {
const proto = Object.create(HTMLObjectElement.prototype)
const registerWebViewElement = (window) => {
const proto = Object.create(window.HTMLObjectElement.prototype)
proto.createdCallback = function () {
return new WebViewImpl(this)
}
@ -288,7 +288,7 @@ const registerWebViewElement = function () {
this.contentWindow.focus()
}
window.WebView = webFrame.registerEmbedderCustomElement('webview', {
window.WebView = webFrame.registerEmbedderCustomElement(window, 'webview', {
prototype: proto
})
@ -300,16 +300,17 @@ const registerWebViewElement = function () {
delete proto.attributeChangedCallback
}
const useCapture = true
const setupWebView = (window) => {
require('@electron/internal/renderer/web-view/web-view-attributes')
const listener = function (event) {
if (document.readyState === 'loading') {
return
}
registerWebViewElement()
window.removeEventListener(event.type, listener, useCapture)
const useCapture = true
window.addEventListener('readystatechange', function listener (event) {
if (document.readyState === 'loading') {
return
}
registerWebViewElement(window)
window.removeEventListener(event.type, listener, useCapture)
}, useCapture)
}
window.addEventListener('readystatechange', listener, true)
module.exports = WebViewImpl
module.exports = { setupWebView, WebViewImpl }

View file

@ -122,8 +122,7 @@ if (binding.guestInstanceId) {
if (!process.guestInstanceId && preloadProcess.argv.includes('--webview-tag=true')) {
// don't allow recursive `<webview>`
require('@electron/internal/renderer/web-view/web-view')
require('@electron/internal/renderer/web-view/web-view-attributes')
require('@electron/internal/renderer/web-view/web-view').setupWebView(window)
}
// Wrap the script into a function executed in global scope. It won't have

2
spec/fixtures/module/isolated-ping.js vendored Normal file
View file

@ -0,0 +1,2 @@
const { ipcRenderer } = require('electron')
ipcRenderer.send('pong')

View file

@ -0,0 +1,5 @@
<html>
<body>
<webview preload="../module/isolated-ping.js" src="about:blank"/>
</body>
</html>

View file

@ -70,6 +70,18 @@ describe('<webview> tag', function () {
await emittedOnce(ipcMain, 'pong')
})
it('works with contextIsolation', async () => {
const w = await openTheWindow({
show: false,
webPreferences: {
webviewTag: true,
contextIsolation: true
}
})
w.loadFile(path.join(fixtures, 'pages', 'webview-isolated.html'))
await emittedOnce(ipcMain, 'pong')
})
it('is disabled when nodeIntegration is disabled', async () => {
const w = await openTheWindow({
show: false,