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: register webview in main world when using contextIsolation #16067

Merged
merged 1 commit into from Dec 14, 2018
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
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