feat: enable nativeWindowOpen by default (#28552)
* feat: enable nativeWindowOpen by default * set nativeWindowOpen: false on spec/ main window * update snapshots * fix tests * fix test * fix webview test missing allowpopups * fix other test * update default
This commit is contained in:
parent
dba4df9326
commit
f8bdef5349
9 changed files with 90 additions and 95 deletions
|
@ -349,9 +349,8 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||||
context in the dev tools by selecting the 'Electron Isolated Context'
|
context in the dev tools by selecting the 'Electron Isolated Context'
|
||||||
entry in the combo box at the top of the Console tab.
|
entry in the combo box at the top of the Console tab.
|
||||||
* `nativeWindowOpen` Boolean (optional) - Whether to use native
|
* `nativeWindowOpen` Boolean (optional) - Whether to use native
|
||||||
`window.open()`. Defaults to `false`. Child windows will always have node
|
`window.open()`. Defaults to `true`. Child windows will always have node
|
||||||
integration disabled unless `nodeIntegrationInSubFrames` is true. **Note:** This option is currently
|
integration disabled unless `nodeIntegrationInSubFrames` is true.
|
||||||
experimental.
|
|
||||||
* `webviewTag` Boolean (optional) - Whether to enable the [`<webview>` tag](webview-tag.md).
|
* `webviewTag` Boolean (optional) - Whether to enable the [`<webview>` tag](webview-tag.md).
|
||||||
Defaults to `false`. **Note:** The
|
Defaults to `false`. **Note:** The
|
||||||
`preload` script configured for the `<webview>` will have node integration
|
`preload` script configured for the `<webview>` will have node integration
|
||||||
|
|
|
@ -6,16 +6,15 @@ untrusted content within a renderer. Windows can be created from the renderer in
|
||||||
* clicking on links or submitting forms adorned with `target=_blank`
|
* clicking on links or submitting forms adorned with `target=_blank`
|
||||||
* JavaScript calling `window.open()`
|
* JavaScript calling `window.open()`
|
||||||
|
|
||||||
In non-sandboxed renderers, or when `nativeWindowOpen` is false (the default), this results in the creation of a
|
For same-origin content, the new window is created within the same process,
|
||||||
[`BrowserWindowProxy`](browser-window-proxy.md), a light wrapper around
|
enabling the parent to access the child window directly. This can be very
|
||||||
`BrowserWindow`.
|
useful for app sub-windows that act as preference panels, or similar, as the
|
||||||
|
parent can render to the sub-window directly, as if it were a `div` in the
|
||||||
|
parent. This is the same behavior as in the browser.
|
||||||
|
|
||||||
However, when the `sandbox` (or directly, `nativeWindowOpen`) option is set, a
|
When `nativeWindowOpen` is set to false, `window.open` instead results in the
|
||||||
`Window` instance is created, as you'd expect in the browser. For same-origin
|
creation of a [`BrowserWindowProxy`](browser-window-proxy.md), a light wrapper
|
||||||
content, the new window is created within the same process, enabling the parent
|
around `BrowserWindow`.
|
||||||
to access the child window directly. This can be very useful for app sub-windows that act
|
|
||||||
as preference panels, or similar, as the parent can render to the sub-window
|
|
||||||
directly, as if it were a `div` in the parent.
|
|
||||||
|
|
||||||
Electron pairs this native Chrome `Window` with a BrowserWindow under the hood.
|
Electron pairs this native Chrome `Window` with a BrowserWindow under the hood.
|
||||||
You can take advantage of all the customization available when creating a
|
You can take advantage of all the customization available when creating a
|
||||||
|
@ -69,49 +68,18 @@ window.open('https://github.com', '_blank', 'top=500,left=200,frame=false,nodeIn
|
||||||
|
|
||||||
To customize or cancel the creation of the window, you can optionally set an
|
To customize or cancel the creation of the window, you can optionally set an
|
||||||
override handler with `webContents.setWindowOpenHandler()` from the main
|
override handler with `webContents.setWindowOpenHandler()` from the main
|
||||||
process. Returning `false` cancels the window, while returning an object sets
|
process. Returning `{ action: 'deny' }` cancels the window. Returning `{
|
||||||
the `BrowserWindowConstructorOptions` used when creating the window. Note that
|
action: 'allow', overrideBrowserWindowOptions: { ... } }` will allow opening
|
||||||
this is more powerful than passing options through the feature string, as the
|
the window and setting the `BrowserWindowConstructorOptions` to be used when
|
||||||
renderer has more limited privileges in deciding security preferences than the
|
creating the window. Note that this is more powerful than passing options
|
||||||
main process.
|
through the feature string, as the renderer has more limited privileges in
|
||||||
|
deciding security preferences than the main process.
|
||||||
### `BrowserWindowProxy` example
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
|
|
||||||
// main.js
|
|
||||||
const mainWindow = new BrowserWindow()
|
|
||||||
|
|
||||||
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
|
||||||
if (url.startsWith('https://github.com/')) {
|
|
||||||
return { action: 'allow' }
|
|
||||||
}
|
|
||||||
return { action: 'deny' }
|
|
||||||
})
|
|
||||||
|
|
||||||
mainWindow.webContents.on('did-create-window', (childWindow) => {
|
|
||||||
// For example...
|
|
||||||
childWindow.webContents.on('will-navigate', (e) => {
|
|
||||||
e.preventDefault()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
// renderer.js
|
|
||||||
const windowProxy = window.open('https://github.com/', null, 'minimizable=false')
|
|
||||||
windowProxy.postMessage('hi', '*')
|
|
||||||
```
|
|
||||||
|
|
||||||
### Native `Window` example
|
### Native `Window` example
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// main.js
|
// main.js
|
||||||
const mainWindow = new BrowserWindow({
|
const mainWindow = new BrowserWindow()
|
||||||
webPreferences: {
|
|
||||||
nativeWindowOpen: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// In this example, only windows with the `about:blank` url will be created.
|
// In this example, only windows with the `about:blank` url will be created.
|
||||||
// All other urls will be blocked.
|
// All other urls will be blocked.
|
||||||
|
@ -135,3 +103,33 @@ mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||||
const childWindow = window.open('', 'modal')
|
const childWindow = window.open('', 'modal')
|
||||||
childWindow.document.write('<h1>Hello</h1>')
|
childWindow.document.write('<h1>Hello</h1>')
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### `BrowserWindowProxy` example
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
|
||||||
|
// main.js
|
||||||
|
const mainWindow = new BrowserWindow({
|
||||||
|
webPreferences: { nativeWindowOpen: false }
|
||||||
|
})
|
||||||
|
|
||||||
|
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
||||||
|
if (url.startsWith('https://github.com/')) {
|
||||||
|
return { action: 'allow' }
|
||||||
|
}
|
||||||
|
return { action: 'deny' }
|
||||||
|
})
|
||||||
|
|
||||||
|
mainWindow.webContents.on('did-create-window', (childWindow) => {
|
||||||
|
// For example...
|
||||||
|
childWindow.webContents.on('will-navigate', (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// renderer.js
|
||||||
|
const windowProxy = window.open('https://github.com/', null, 'minimizable=false')
|
||||||
|
windowProxy.postMessage('hi', '*')
|
||||||
|
```
|
||||||
|
|
|
@ -28,6 +28,16 @@ ensure your code works with this property enabled. It has been enabled by defau
|
||||||
|
|
||||||
You will be affected by this change if you use either `webFrame.executeJavaScript` or `webFrame.executeJavaScriptInIsolatedWorld`. You will need to ensure that values returned by either of those methods are supported by the [Context Bridge API](api/context-bridge.md#parameter--error--return-type-support) as these methods use the same value passing semantics.
|
You will be affected by this change if you use either `webFrame.executeJavaScript` or `webFrame.executeJavaScriptInIsolatedWorld`. You will need to ensure that values returned by either of those methods are supported by the [Context Bridge API](api/context-bridge.md#parameter--error--return-type-support) as these methods use the same value passing semantics.
|
||||||
|
|
||||||
|
### Default Changed: `nativeWindowOpen` defaults to `true`
|
||||||
|
|
||||||
|
Prior to Electron 14, `window.open` was by default shimmed to use
|
||||||
|
`BrowserWindowProxy`. This meant that `window.open('about:blank')` did not work
|
||||||
|
to open synchronously scriptable child windows, among other incompatibilities.
|
||||||
|
`nativeWindowOpen` is no longer experimental, and is now the default.
|
||||||
|
|
||||||
|
See the documentation for [window.open in Electron](api/window-open.md)
|
||||||
|
for more details.
|
||||||
|
|
||||||
## Planned Breaking API Changes (13.0)
|
## Planned Breaking API Changes (13.0)
|
||||||
|
|
||||||
### API Changed: `session.setPermissionCheckHandler(handler)`
|
### API Changed: `session.setPermissionCheckHandler(handler)`
|
||||||
|
|
|
@ -141,7 +141,7 @@ WebContentsPreferences::WebContentsPreferences(
|
||||||
SetDefaultBoolIfUndefined(options::kDisableHtmlFullscreenWindowResize, false);
|
SetDefaultBoolIfUndefined(options::kDisableHtmlFullscreenWindowResize, false);
|
||||||
SetDefaultBoolIfUndefined(options::kWebviewTag, false);
|
SetDefaultBoolIfUndefined(options::kWebviewTag, false);
|
||||||
SetDefaultBoolIfUndefined(options::kSandbox, false);
|
SetDefaultBoolIfUndefined(options::kSandbox, false);
|
||||||
SetDefaultBoolIfUndefined(options::kNativeWindowOpen, false);
|
SetDefaultBoolIfUndefined(options::kNativeWindowOpen, true);
|
||||||
SetDefaultBoolIfUndefined(options::kContextIsolation, true);
|
SetDefaultBoolIfUndefined(options::kContextIsolation, true);
|
||||||
SetDefaultBoolIfUndefined(options::kJavaScript, true);
|
SetDefaultBoolIfUndefined(options::kJavaScript, true);
|
||||||
SetDefaultBoolIfUndefined(options::kImages, true);
|
SetDefaultBoolIfUndefined(options::kImages, true);
|
||||||
|
@ -474,7 +474,7 @@ void WebContentsPreferences::OverrideWebkitPrefs(
|
||||||
GetPreloadPath(&prefs->preload);
|
GetPreloadPath(&prefs->preload);
|
||||||
|
|
||||||
// Check if nativeWindowOpen is enabled.
|
// Check if nativeWindowOpen is enabled.
|
||||||
prefs->native_window_open = IsEnabled(options::kNativeWindowOpen);
|
prefs->native_window_open = IsEnabled(options::kNativeWindowOpen, true);
|
||||||
|
|
||||||
// Check if we have node integration specified.
|
// Check if we have node integration specified.
|
||||||
prefs->node_integration = IsEnabled(options::kNodeIntegration);
|
prefs->node_integration = IsEnabled(options::kNodeIntegration);
|
||||||
|
|
|
@ -3075,19 +3075,7 @@ describe('BrowserWindow module', () => {
|
||||||
expect(url).to.equal('http://example.com/test');
|
expect(url).to.equal('http://example.com/test');
|
||||||
expect(frameName).to.equal('');
|
expect(frameName).to.equal('');
|
||||||
expect(disposition).to.equal('foreground-tab');
|
expect(disposition).to.equal('foreground-tab');
|
||||||
expect(options).to.deep.equal({
|
expect(options).to.be.an('object').not.null();
|
||||||
show: true,
|
|
||||||
width: 800,
|
|
||||||
height: 600,
|
|
||||||
webPreferences: {
|
|
||||||
contextIsolation: true,
|
|
||||||
nodeIntegration: false,
|
|
||||||
webviewTag: false,
|
|
||||||
nodeIntegrationInSubFrames: false,
|
|
||||||
openerId: options.webPreferences!.openerId
|
|
||||||
},
|
|
||||||
webContents: undefined
|
|
||||||
});
|
|
||||||
expect(referrer.policy).to.equal('strict-origin-when-cross-origin');
|
expect(referrer.policy).to.equal('strict-origin-when-cross-origin');
|
||||||
expect(referrer.url).to.equal('');
|
expect(referrer.url).to.equal('');
|
||||||
expect(additionalFeatures).to.deep.equal([]);
|
expect(additionalFeatures).to.deep.equal([]);
|
||||||
|
|
|
@ -744,7 +744,9 @@ describe('chromium features', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
it('disables node integration when it is disabled on the parent window for chrome devtools URLs', async () => {
|
it('disables node integration when it is disabled on the parent window for chrome devtools URLs', async () => {
|
||||||
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } });
|
// NB. webSecurity is disabled because native window.open() is not
|
||||||
|
// allowed to load devtools:// URLs.
|
||||||
|
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true, webSecurity: false } });
|
||||||
w.loadURL('about:blank');
|
w.loadURL('about:blank');
|
||||||
w.webContents.executeJavaScript(`
|
w.webContents.executeJavaScript(`
|
||||||
{ b = window.open('devtools://devtools/bundled/inspector.html', '', 'nodeIntegration=no,show=no'); null }
|
{ b = window.open('devtools://devtools/bundled/inspector.html', '', 'nodeIntegration=no,show=no'); null }
|
||||||
|
@ -755,8 +757,8 @@ describe('chromium features', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('disables JavaScript when it is disabled on the parent window', async () => {
|
it('disables JavaScript when it is disabled on the parent window', async () => {
|
||||||
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } });
|
const w = new BrowserWindow({ show: true, webPreferences: { nodeIntegration: true } });
|
||||||
w.webContents.loadURL('about:blank');
|
w.webContents.loadFile(path.resolve(__dirname, 'fixtures', 'blank.html'));
|
||||||
const windowUrl = require('url').format({
|
const windowUrl = require('url').format({
|
||||||
pathname: `${fixturesPath}/pages/window-no-javascript.html`,
|
pathname: `${fixturesPath}/pages/window-no-javascript.html`,
|
||||||
protocol: 'file',
|
protocol: 'file',
|
||||||
|
@ -783,7 +785,7 @@ describe('chromium features', () => {
|
||||||
targetURL = `file://${fixturesPath}/pages/base-page.html`;
|
targetURL = `file://${fixturesPath}/pages/base-page.html`;
|
||||||
}
|
}
|
||||||
const w = new BrowserWindow({ show: false });
|
const w = new BrowserWindow({ show: false });
|
||||||
w.loadURL('about:blank');
|
w.webContents.loadFile(path.resolve(__dirname, 'fixtures', 'blank.html'));
|
||||||
w.webContents.executeJavaScript(`{ b = window.open(${JSON.stringify(targetURL)}); null }`);
|
w.webContents.executeJavaScript(`{ b = window.open(${JSON.stringify(targetURL)}); null }`);
|
||||||
const [, window] = await emittedOnce(app, 'browser-window-created');
|
const [, window] = await emittedOnce(app, 'browser-window-created');
|
||||||
await emittedOnce(window.webContents, 'did-finish-load');
|
await emittedOnce(window.webContents, 'did-finish-load');
|
||||||
|
@ -792,7 +794,7 @@ describe('chromium features', () => {
|
||||||
|
|
||||||
it('defines a window.location setter', async () => {
|
it('defines a window.location setter', async () => {
|
||||||
const w = new BrowserWindow({ show: false });
|
const w = new BrowserWindow({ show: false });
|
||||||
w.loadURL('about:blank');
|
w.webContents.loadFile(path.resolve(__dirname, 'fixtures', 'blank.html'));
|
||||||
w.webContents.executeJavaScript('{ b = window.open("about:blank"); null }');
|
w.webContents.executeJavaScript('{ b = window.open("about:blank"); null }');
|
||||||
const [, { webContents }] = await emittedOnce(app, 'browser-window-created');
|
const [, { webContents }] = await emittedOnce(app, 'browser-window-created');
|
||||||
await emittedOnce(webContents, 'did-finish-load');
|
await emittedOnce(webContents, 'did-finish-load');
|
||||||
|
@ -803,7 +805,7 @@ describe('chromium features', () => {
|
||||||
|
|
||||||
it('defines a window.location.href setter', async () => {
|
it('defines a window.location.href setter', async () => {
|
||||||
const w = new BrowserWindow({ show: false });
|
const w = new BrowserWindow({ show: false });
|
||||||
w.loadURL('about:blank');
|
w.webContents.loadFile(path.resolve(__dirname, 'fixtures', 'blank.html'));
|
||||||
w.webContents.executeJavaScript('{ b = window.open("about:blank"); null }');
|
w.webContents.executeJavaScript('{ b = window.open("about:blank"); null }');
|
||||||
const [, { webContents }] = await emittedOnce(app, 'browser-window-created');
|
const [, { webContents }] = await emittedOnce(app, 'browser-window-created');
|
||||||
await emittedOnce(webContents, 'did-finish-load');
|
await emittedOnce(webContents, 'did-finish-load');
|
||||||
|
@ -1035,7 +1037,7 @@ describe('chromium features', () => {
|
||||||
// We are testing whether context (3) can access context (2) under various conditions.
|
// We are testing whether context (3) can access context (2) under various conditions.
|
||||||
|
|
||||||
// This is context (1), the base window for the test.
|
// This is context (1), the base window for the test.
|
||||||
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true, webviewTag: true, contextIsolation: false } });
|
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true, webviewTag: true, contextIsolation: false, nativeWindowOpen: false } });
|
||||||
await w.loadURL('about:blank');
|
await w.loadURL('about:blank');
|
||||||
|
|
||||||
const parentCode = `new Promise((resolve) => {
|
const parentCode = `new Promise((resolve) => {
|
||||||
|
|
|
@ -2,9 +2,7 @@
|
||||||
[
|
[
|
||||||
"top=5,left=10,resizable=no",
|
"top=5,left=10,resizable=no",
|
||||||
{
|
{
|
||||||
"sender": "[WebContents]",
|
"sender": "[WebContents]"
|
||||||
"frameId": 1,
|
|
||||||
"processId": "placeholder-process-id"
|
|
||||||
},
|
},
|
||||||
"about:blank",
|
"about:blank",
|
||||||
"frame-name",
|
"frame-name",
|
||||||
|
@ -20,10 +18,11 @@
|
||||||
"y": 5,
|
"y": 5,
|
||||||
"webPreferences": {
|
"webPreferences": {
|
||||||
"contextIsolation": true,
|
"contextIsolation": true,
|
||||||
|
"nativeWindowOpen": true,
|
||||||
"nodeIntegration": false,
|
"nodeIntegration": false,
|
||||||
"webviewTag": false,
|
"webviewTag": false,
|
||||||
"nodeIntegrationInSubFrames": false,
|
"nodeIntegrationInSubFrames": false,
|
||||||
"openerId": "placeholder-opener-id"
|
"openerId": null
|
||||||
},
|
},
|
||||||
"webContents": "[WebContents]"
|
"webContents": "[WebContents]"
|
||||||
},
|
},
|
||||||
|
@ -37,9 +36,7 @@
|
||||||
[
|
[
|
||||||
"zoomFactor=2,resizable=0,x=0,y=10",
|
"zoomFactor=2,resizable=0,x=0,y=10",
|
||||||
{
|
{
|
||||||
"sender": "[WebContents]",
|
"sender": "[WebContents]"
|
||||||
"frameId": 1,
|
|
||||||
"processId": "placeholder-process-id"
|
|
||||||
},
|
},
|
||||||
"about:blank",
|
"about:blank",
|
||||||
"frame-name",
|
"frame-name",
|
||||||
|
@ -54,10 +51,11 @@
|
||||||
"webPreferences": {
|
"webPreferences": {
|
||||||
"zoomFactor": "2",
|
"zoomFactor": "2",
|
||||||
"contextIsolation": true,
|
"contextIsolation": true,
|
||||||
|
"nativeWindowOpen": true,
|
||||||
"nodeIntegration": false,
|
"nodeIntegration": false,
|
||||||
"webviewTag": false,
|
"webviewTag": false,
|
||||||
"nodeIntegrationInSubFrames": false,
|
"nodeIntegrationInSubFrames": false,
|
||||||
"openerId": "placeholder-opener-id"
|
"openerId": null
|
||||||
},
|
},
|
||||||
"webContents": "[WebContents]"
|
"webContents": "[WebContents]"
|
||||||
},
|
},
|
||||||
|
@ -71,9 +69,7 @@
|
||||||
[
|
[
|
||||||
"backgroundColor=gray,webPreferences=0,x=100,y=100",
|
"backgroundColor=gray,webPreferences=0,x=100,y=100",
|
||||||
{
|
{
|
||||||
"sender": "[WebContents]",
|
"sender": "[WebContents]"
|
||||||
"frameId": 1,
|
|
||||||
"processId": "placeholder-process-id"
|
|
||||||
},
|
},
|
||||||
"about:blank",
|
"about:blank",
|
||||||
"frame-name",
|
"frame-name",
|
||||||
|
@ -85,10 +81,11 @@
|
||||||
"backgroundColor": "gray",
|
"backgroundColor": "gray",
|
||||||
"webPreferences": {
|
"webPreferences": {
|
||||||
"contextIsolation": true,
|
"contextIsolation": true,
|
||||||
|
"nativeWindowOpen": true,
|
||||||
"nodeIntegration": false,
|
"nodeIntegration": false,
|
||||||
"webviewTag": false,
|
"webviewTag": false,
|
||||||
"nodeIntegrationInSubFrames": false,
|
"nodeIntegrationInSubFrames": false,
|
||||||
"openerId": "placeholder-opener-id",
|
"openerId": null,
|
||||||
"backgroundColor": "gray"
|
"backgroundColor": "gray"
|
||||||
},
|
},
|
||||||
"x": 100,
|
"x": 100,
|
||||||
|
@ -105,9 +102,7 @@
|
||||||
[
|
[
|
||||||
"x=50,y=20,title=sup",
|
"x=50,y=20,title=sup",
|
||||||
{
|
{
|
||||||
"sender": "[WebContents]",
|
"sender": "[WebContents]"
|
||||||
"frameId": 1,
|
|
||||||
"processId": "placeholder-process-id"
|
|
||||||
},
|
},
|
||||||
"about:blank",
|
"about:blank",
|
||||||
"frame-name",
|
"frame-name",
|
||||||
|
@ -121,10 +116,11 @@
|
||||||
"title": "sup",
|
"title": "sup",
|
||||||
"webPreferences": {
|
"webPreferences": {
|
||||||
"contextIsolation": true,
|
"contextIsolation": true,
|
||||||
|
"nativeWindowOpen": true,
|
||||||
"nodeIntegration": false,
|
"nodeIntegration": false,
|
||||||
"webviewTag": false,
|
"webviewTag": false,
|
||||||
"nodeIntegrationInSubFrames": false,
|
"nodeIntegrationInSubFrames": false,
|
||||||
"openerId": "placeholder-opener-id"
|
"openerId": null
|
||||||
},
|
},
|
||||||
"webContents": "[WebContents]"
|
"webContents": "[WebContents]"
|
||||||
},
|
},
|
||||||
|
@ -138,9 +134,7 @@
|
||||||
[
|
[
|
||||||
"show=false,top=1,left=1",
|
"show=false,top=1,left=1",
|
||||||
{
|
{
|
||||||
"sender": "[WebContents]",
|
"sender": "[WebContents]"
|
||||||
"frameId": 1,
|
|
||||||
"processId": "placeholder-process-id"
|
|
||||||
},
|
},
|
||||||
"about:blank",
|
"about:blank",
|
||||||
"frame-name",
|
"frame-name",
|
||||||
|
@ -155,10 +149,11 @@
|
||||||
"y": 1,
|
"y": 1,
|
||||||
"webPreferences": {
|
"webPreferences": {
|
||||||
"contextIsolation": true,
|
"contextIsolation": true,
|
||||||
|
"nativeWindowOpen": true,
|
||||||
"nodeIntegration": false,
|
"nodeIntegration": false,
|
||||||
"webviewTag": false,
|
"webviewTag": false,
|
||||||
"nodeIntegrationInSubFrames": false,
|
"nodeIntegrationInSubFrames": false,
|
||||||
"openerId": "placeholder-opener-id"
|
"openerId": null
|
||||||
},
|
},
|
||||||
"webContents": "[WebContents]"
|
"webContents": "[WebContents]"
|
||||||
},
|
},
|
||||||
|
|
|
@ -109,7 +109,8 @@ app.whenReady().then(async function () {
|
||||||
backgroundThrottling: false,
|
backgroundThrottling: false,
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
webviewTag: true,
|
webviewTag: true,
|
||||||
contextIsolation: false
|
contextIsolation: false,
|
||||||
|
nativeWindowOpen: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
window.loadFile('static/index.html', {
|
window.loadFile('static/index.html', {
|
||||||
|
|
|
@ -501,7 +501,8 @@ describe('<webview> tag', function () {
|
||||||
describe('new-window event', () => {
|
describe('new-window event', () => {
|
||||||
it('emits when window.open is called', async () => {
|
it('emits when window.open is called', async () => {
|
||||||
loadWebView(webview, {
|
loadWebView(webview, {
|
||||||
src: `file://${fixtures}/pages/window-open.html`
|
src: `file://${fixtures}/pages/window-open.html`,
|
||||||
|
allowpopups: true
|
||||||
});
|
});
|
||||||
const { url, frameName } = await waitForEvent(webview, 'new-window');
|
const { url, frameName } = await waitForEvent(webview, 'new-window');
|
||||||
|
|
||||||
|
@ -511,7 +512,8 @@ describe('<webview> tag', function () {
|
||||||
|
|
||||||
it('emits when link with target is called', async () => {
|
it('emits when link with target is called', async () => {
|
||||||
loadWebView(webview, {
|
loadWebView(webview, {
|
||||||
src: `file://${fixtures}/pages/target-name.html`
|
src: `file://${fixtures}/pages/target-name.html`,
|
||||||
|
allowpopups: true
|
||||||
});
|
});
|
||||||
const { url, frameName } = await waitForEvent(webview, 'new-window');
|
const { url, frameName } = await waitForEvent(webview, 'new-window');
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue