Skip to content

Commit

Permalink
fix: register webview in main world when using contextIsolation (#16067)
Browse files Browse the repository at this point in the history
  • Loading branch information
Cheng Zhao committed Dec 14, 2018
1 parent dbda1a1 commit 8584c2f
Show file tree
Hide file tree
Showing 11 changed files with 56 additions and 20 deletions.
3 changes: 3 additions & 0 deletions BUILD.gn
Expand Up @@ -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",
Expand Down
2 changes: 2 additions & 0 deletions atom/renderer/api/atom_api_web_frame.cc
Expand Up @@ -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);
}
Expand Down
1 change: 1 addition & 0 deletions atom/renderer/api/atom_api_web_frame.h
Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions lib/isolated_renderer/init.js
Expand Up @@ -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

Expand Down
8 changes: 6 additions & 2 deletions lib/renderer/init.js
Expand Up @@ -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)
}
}
}

Expand Down
6 changes: 3 additions & 3 deletions lib/renderer/web-view/web-view-attributes.js
@@ -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')

Expand Down Expand Up @@ -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)
}
}
}
Expand Down
27 changes: 14 additions & 13 deletions lib/renderer/web-view/web-view.js
Expand Up @@ -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)
}
Expand Down Expand Up @@ -288,7 +288,7 @@ const registerWebViewElement = function () {
this.contentWindow.focus()
}

window.WebView = webFrame.registerEmbedderCustomElement('webview', {
window.WebView = webFrame.registerEmbedderCustomElement(window, 'webview', {
prototype: proto
})

Expand All @@ -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 }
3 changes: 1 addition & 2 deletions lib/sandboxed_renderer/init.js
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions spec/fixtures/module/isolated-ping.js
@@ -0,0 +1,2 @@
const { ipcRenderer } = require('electron')
ipcRenderer.send('pong')
5 changes: 5 additions & 0 deletions spec/fixtures/pages/webview-isolated.html
@@ -0,0 +1,5 @@
<html>
<body>
<webview preload="../module/isolated-ping.js" src="about:blank"/>
</body>
</html>
12 changes: 12 additions & 0 deletions spec/webview-spec.js
Expand Up @@ -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,
Expand Down

0 comments on commit 8584c2f

Please sign in to comment.