Merge pull request #9568 from electron/webview-native-window-open
Support nativeWindowOpen from <webview> tags
This commit is contained in:
commit
8ae36c250c
17 changed files with 222 additions and 13 deletions
|
@ -147,6 +147,12 @@ bool AtomBrowserClient::RendererUsesNativeWindowOpen(int process_id) {
|
||||||
return it != process_preferences_.end() && it->second.native_window_open;
|
return it != process_preferences_.end() && it->second.native_window_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AtomBrowserClient::RendererDisablesPopups(int process_id) {
|
||||||
|
base::AutoLock auto_lock(process_preferences_lock_);
|
||||||
|
auto it = process_preferences_.find(process_id);
|
||||||
|
return it != process_preferences_.end() && it->second.disable_popups;
|
||||||
|
}
|
||||||
|
|
||||||
void AtomBrowserClient::RenderProcessWillLaunch(
|
void AtomBrowserClient::RenderProcessWillLaunch(
|
||||||
content::RenderProcessHost* host) {
|
content::RenderProcessHost* host) {
|
||||||
int process_id = host->GetID();
|
int process_id = host->GetID();
|
||||||
|
@ -160,6 +166,8 @@ void AtomBrowserClient::RenderProcessWillLaunch(
|
||||||
process_prefs.sandbox = WebContentsPreferences::IsSandboxed(web_contents);
|
process_prefs.sandbox = WebContentsPreferences::IsSandboxed(web_contents);
|
||||||
process_prefs.native_window_open
|
process_prefs.native_window_open
|
||||||
= WebContentsPreferences::UsesNativeWindowOpen(web_contents);
|
= WebContentsPreferences::UsesNativeWindowOpen(web_contents);
|
||||||
|
process_prefs.disable_popups
|
||||||
|
= WebContentsPreferences::DisablePopups(web_contents);
|
||||||
AddProcessPreferences(host->GetID(), process_prefs);
|
AddProcessPreferences(host->GetID(), process_prefs);
|
||||||
// ensure the ProcessPreferences is removed later
|
// ensure the ProcessPreferences is removed later
|
||||||
host->AddObserver(this);
|
host->AddObserver(this);
|
||||||
|
@ -341,12 +349,22 @@ bool AtomBrowserClient::CanCreateWindow(
|
||||||
bool* no_javascript_access) {
|
bool* no_javascript_access) {
|
||||||
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
|
||||||
|
|
||||||
if (IsRendererSandboxed(opener_render_process_id)
|
if (IsRendererSandboxed(opener_render_process_id)) {
|
||||||
|| RendererUsesNativeWindowOpen(opener_render_process_id)) {
|
|
||||||
*no_javascript_access = false;
|
*no_javascript_access = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (RendererUsesNativeWindowOpen(opener_render_process_id)) {
|
||||||
|
if (RendererDisablesPopups(opener_render_process_id)) {
|
||||||
|
// <webview> without allowpopups attribute should return
|
||||||
|
// null from window.open calls
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
*no_javascript_access = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (delegate_) {
|
if (delegate_) {
|
||||||
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
|
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
|
||||||
base::Bind(&api::App::OnCreateWindow,
|
base::Bind(&api::App::OnCreateWindow,
|
||||||
|
|
|
@ -122,11 +122,13 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
||||||
struct ProcessPreferences {
|
struct ProcessPreferences {
|
||||||
bool sandbox;
|
bool sandbox;
|
||||||
bool native_window_open;
|
bool native_window_open;
|
||||||
|
bool disable_popups;
|
||||||
};
|
};
|
||||||
void AddProcessPreferences(int process_id, ProcessPreferences prefs);
|
void AddProcessPreferences(int process_id, ProcessPreferences prefs);
|
||||||
void RemoveProcessPreferences(int process_id);
|
void RemoveProcessPreferences(int process_id);
|
||||||
bool IsRendererSandboxed(int process_id);
|
bool IsRendererSandboxed(int process_id);
|
||||||
bool RendererUsesNativeWindowOpen(int process_id);
|
bool RendererUsesNativeWindowOpen(int process_id);
|
||||||
|
bool RendererDisablesPopups(int process_id);
|
||||||
|
|
||||||
// pending_render_process => current_render_process.
|
// pending_render_process => current_render_process.
|
||||||
std::map<int, int> pending_processes_;
|
std::map<int, int> pending_processes_;
|
||||||
|
|
|
@ -237,6 +237,11 @@ bool WebContentsPreferences::IsPluginsEnabled(
|
||||||
return IsPreferenceEnabled("plugins", web_contents);
|
return IsPreferenceEnabled("plugins", web_contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WebContentsPreferences::DisablePopups(
|
||||||
|
content::WebContents* web_contents) {
|
||||||
|
return IsPreferenceEnabled("disablePopups", web_contents);
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
void WebContentsPreferences::OverrideWebkitPrefs(
|
void WebContentsPreferences::OverrideWebkitPrefs(
|
||||||
content::WebContents* web_contents, content::WebPreferences* prefs) {
|
content::WebContents* web_contents, content::WebPreferences* prefs) {
|
||||||
|
|
|
@ -41,6 +41,7 @@ class WebContentsPreferences
|
||||||
content::WebContents* web_contents);
|
content::WebContents* web_contents);
|
||||||
static bool IsSandboxed(content::WebContents* web_contents);
|
static bool IsSandboxed(content::WebContents* web_contents);
|
||||||
static bool UsesNativeWindowOpen(content::WebContents* web_contents);
|
static bool UsesNativeWindowOpen(content::WebContents* web_contents);
|
||||||
|
static bool DisablePopups(content::WebContents* web_contents);
|
||||||
static bool IsPluginsEnabled(content::WebContents* web_contents);
|
static bool IsPluginsEnabled(content::WebContents* web_contents);
|
||||||
|
|
||||||
// Modify the WebPreferences according to |web_contents|'s preferences.
|
// Modify the WebPreferences according to |web_contents|'s preferences.
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include "atom/browser/api/atom_api_web_contents.h"
|
#include "atom/browser/api/atom_api_web_contents.h"
|
||||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||||
|
#include "content/browser/web_contents/web_contents_impl.h"
|
||||||
#include "content/public/browser/guest_host.h"
|
#include "content/public/browser/guest_host.h"
|
||||||
#include "content/public/browser/navigation_handle.h"
|
#include "content/public/browser/navigation_handle.h"
|
||||||
#include "content/public/browser/render_frame_host.h"
|
#include "content/public/browser/render_frame_host.h"
|
||||||
|
@ -188,4 +189,21 @@ content::SiteInstance* WebViewGuestDelegate::GetOwnerSiteInstance() {
|
||||||
return embedder_web_contents_->GetSiteInstance();
|
return embedder_web_contents_->GetSiteInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
content::WebContents* WebViewGuestDelegate::CreateNewGuestWindow(
|
||||||
|
const content::WebContents::CreateParams& create_params) {
|
||||||
|
// Code below mirrors what content::WebContentsImpl::CreateNewWindow
|
||||||
|
// does for non-guest sources
|
||||||
|
content::WebContents::CreateParams guest_params(create_params);
|
||||||
|
guest_params.initial_size =
|
||||||
|
embedder_web_contents_->GetContainerBounds().size();
|
||||||
|
guest_params.context = embedder_web_contents_->GetNativeView();
|
||||||
|
auto guest_contents = content::WebContents::Create(guest_params);
|
||||||
|
auto guest_contents_impl =
|
||||||
|
static_cast<content::WebContentsImpl*>(guest_contents);
|
||||||
|
guest_contents_impl->GetView()->CreateViewForWidget(
|
||||||
|
guest_contents->GetRenderViewHost()->GetWidget(), false);
|
||||||
|
|
||||||
|
return guest_contents;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace atom
|
} // namespace atom
|
||||||
|
|
|
@ -64,6 +64,8 @@ class WebViewGuestDelegate : public content::BrowserPluginGuestDelegate,
|
||||||
bool CanBeEmbeddedInsideCrossProcessFrames() override;
|
bool CanBeEmbeddedInsideCrossProcessFrames() override;
|
||||||
content::RenderWidgetHost* GetOwnerRenderWidgetHost() override;
|
content::RenderWidgetHost* GetOwnerRenderWidgetHost() override;
|
||||||
content::SiteInstance* GetOwnerSiteInstance() override;
|
content::SiteInstance* GetOwnerSiteInstance() override;
|
||||||
|
content::WebContents* CreateNewGuestWindow(
|
||||||
|
const content::WebContents::CreateParams& create_params) override;
|
||||||
|
|
||||||
// WebContentsZoomController::Observer:
|
// WebContentsZoomController::Observer:
|
||||||
void OnZoomLevelChanged(content::WebContents* web_contents,
|
void OnZoomLevelChanged(content::WebContents* web_contents,
|
||||||
|
|
|
@ -46,12 +46,22 @@ has to be a field of `BrowserWindow`'s options.
|
||||||
Sends a message to the parent window with the specified origin or `*` for no
|
Sends a message to the parent window with the specified origin or `*` for no
|
||||||
origin preference.
|
origin preference.
|
||||||
|
|
||||||
### Use Native `window.open()`
|
### Using Chrome's `window.open()` implementation
|
||||||
|
|
||||||
If you want to use native `window.open()` implementation, pass `useNativeWindowOpen: true` in `webPreferences` option.
|
If you want to use Chrome's built-in `window.open()` implementation, set
|
||||||
Native `window.open()` allows synchronous access to opened windows so it is convenient choice if you need to open a dialog or a preferences window.
|
`nativeWindowOpen` to `true` in the `webPreferences` options object.
|
||||||
|
|
||||||
The creation of the `BrowserWindow` is customizable in `WebContents`'s `new-window` event.
|
Native `window.open()` allows synchronous access to opened windows so it is
|
||||||
|
convenient choice if you need to open a dialog or a preferences window.
|
||||||
|
|
||||||
|
This option can also be set on `<webview>` tags as well:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<webview webpreferences="nativeWindowOpen=yes"></webview>
|
||||||
|
```
|
||||||
|
|
||||||
|
The creation of the `BrowserWindow` is customizable via `WebContents`'s
|
||||||
|
`new-window` event.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// main process
|
// main process
|
||||||
|
|
|
@ -36,8 +36,9 @@ BrowserWindow.prototype._init = function () {
|
||||||
frameName) => {
|
frameName) => {
|
||||||
v8Util.setHiddenValue(webContents, 'url-framename', {url, frameName})
|
v8Util.setHiddenValue(webContents, 'url-framename', {url, frameName})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create a new browser window for the native implementation of
|
// Create a new browser window for the native implementation of
|
||||||
// "window.open"(sandbox mode only)
|
// "window.open", used in sandbox and nativeWindowOpen mode
|
||||||
this.webContents.on('-add-new-contents', (event, webContents, disposition,
|
this.webContents.on('-add-new-contents', (event, webContents, disposition,
|
||||||
userGesture, left, top, width,
|
userGesture, left, top, width,
|
||||||
height) => {
|
height) => {
|
||||||
|
|
|
@ -143,6 +143,25 @@ const createGuest = function (embedder, params) {
|
||||||
sendToEmbedder('ELECTRON_GUEST_VIEW_INTERNAL_SIZE_CHANGED', ...args)
|
sendToEmbedder('ELECTRON_GUEST_VIEW_INTERNAL_SIZE_CHANGED', ...args)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Forward internal web contents event to embedder to handle
|
||||||
|
// native window.open setup
|
||||||
|
guest.on('-add-new-contents', (...args) => {
|
||||||
|
if (guest.getWebPreferences().nativeWindowOpen === true) {
|
||||||
|
const embedder = getEmbedder(guestInstanceId)
|
||||||
|
if (embedder != null) {
|
||||||
|
embedder.emit('-add-new-contents', ...args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
guest.on('-web-contents-created', (...args) => {
|
||||||
|
if (guest.getWebPreferences().nativeWindowOpen === true) {
|
||||||
|
const embedder = getEmbedder(guestInstanceId)
|
||||||
|
if (embedder != null) {
|
||||||
|
embedder.emit('-web-contents-created', ...args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return guestInstanceId
|
return guestInstanceId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,6 +225,11 @@ const attachGuest = function (event, elementInstanceId, guestInstanceId, params)
|
||||||
webPreferences.preloadURL = params.preload
|
webPreferences.preloadURL = params.preload
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return null from native window.open if allowpopups is unset
|
||||||
|
if (webPreferences.nativeWindowOpen === true && !params.allowpopups) {
|
||||||
|
webPreferences.disablePopups = true
|
||||||
|
}
|
||||||
|
|
||||||
embedder.emit('will-attach-webview', event, webPreferences, params)
|
embedder.emit('will-attach-webview', event, webPreferences, params)
|
||||||
if (event.defaultPrevented) {
|
if (event.defaultPrevented) {
|
||||||
if (guest.viewInstanceId == null) guest.viewInstanceId = params.instanceId
|
if (guest.viewInstanceId == null) guest.viewInstanceId = params.instanceId
|
||||||
|
|
|
@ -47,7 +47,7 @@ const mergeBrowserWindowOptions = function (embedder, options) {
|
||||||
// Inherit the original options if it is a BrowserWindow.
|
// Inherit the original options if it is a BrowserWindow.
|
||||||
mergeOptions(options, embedder.browserWindowOptions)
|
mergeOptions(options, embedder.browserWindowOptions)
|
||||||
} else {
|
} else {
|
||||||
// Or only inherit web-preferences if it is a webview.
|
// Or only inherit webPreferences if it is a webview.
|
||||||
mergeOptions(options.webPreferences, embedder.getWebPreferences())
|
mergeOptions(options.webPreferences, embedder.getWebPreferences())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,9 +252,9 @@ ipcMain.on('ELECTRON_GUEST_WINDOW_MANAGER_INTERNAL_WINDOW_OPEN', function (event
|
||||||
additionalFeatures, postData) {
|
additionalFeatures, postData) {
|
||||||
options = mergeBrowserWindowOptions(event.sender, options)
|
options = mergeBrowserWindowOptions(event.sender, options)
|
||||||
event.sender.emit('new-window', event, url, frameName, disposition, options, additionalFeatures)
|
event.sender.emit('new-window', event, url, frameName, disposition, options, additionalFeatures)
|
||||||
const newGuest = event.newGuest
|
const {newGuest} = event
|
||||||
if ((event.sender.isGuest() && !event.sender.allowPopups) || event.defaultPrevented) {
|
if ((event.sender.isGuest() && !event.sender.allowPopups) || event.defaultPrevented) {
|
||||||
if (newGuest !== undefined && newGuest !== null) {
|
if (newGuest != null) {
|
||||||
if (options.webContents === newGuest.webContents) {
|
if (options.webContents === newGuest.webContents) {
|
||||||
// the webContents is not changed, so set defaultPrevented to false to
|
// the webContents is not changed, so set defaultPrevented to false to
|
||||||
// stop the callers of this event from destroying the webContents.
|
// stop the callers of this event from destroying the webContents.
|
||||||
|
|
|
@ -550,7 +550,7 @@ describe('app module', function () {
|
||||||
assert.equal(typeof cpu.idleWakeupsPerSecond, 'number')
|
assert.equal(typeof cpu.idleWakeupsPerSecond, 'number')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.platform !== 'linux') {
|
if (process.platform === 'darwin') {
|
||||||
assert.ok(types.includes('GPU'))
|
assert.ok(types.includes('GPU'))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -854,7 +854,7 @@ describe('BrowserWindow module', function () {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('"web-preferences" option', function () {
|
describe('"webPreferences" option', function () {
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
ipcMain.removeAllListeners('answer')
|
ipcMain.removeAllListeners('answer')
|
||||||
})
|
})
|
||||||
|
@ -1285,6 +1285,22 @@ describe('BrowserWindow module', function () {
|
||||||
w.loadURL('file://' + path.join(fixtures, 'api', 'native-window-open-file.html'))
|
w.loadURL('file://' + path.join(fixtures, 'api', 'native-window-open-file.html'))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('blocks accessing cross-origin frames', (done) => {
|
||||||
|
ipcMain.once('answer', (event, content) => {
|
||||||
|
assert.equal(content, 'Blocked a frame with origin "file://" from accessing a cross-origin frame.')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
w.loadURL('file://' + path.join(fixtures, 'api', 'native-window-open-cross-origin.html'))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('opens window from <iframe> tags', (done) => {
|
||||||
|
ipcMain.once('answer', (event, content) => {
|
||||||
|
assert.equal(content, 'Hello')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
w.loadURL('file://' + path.join(fixtures, 'api', 'native-window-open-iframe.html'))
|
||||||
|
})
|
||||||
|
|
||||||
if (process.platform !== 'win32' || process.execPath.toLowerCase().indexOf('\\out\\d\\') === -1) {
|
if (process.platform !== 'win32' || process.execPath.toLowerCase().indexOf('\\out\\d\\') === -1) {
|
||||||
it('loads native addons correctly after reload', (done) => {
|
it('loads native addons correctly after reload', (done) => {
|
||||||
ipcMain.once('answer', (event, content) => {
|
ipcMain.once('answer', (event, content) => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<script type="text/javascript" charset="utf-8">
|
<script type="text/javascript" charset="utf-8">
|
||||||
const {ipcRenderer} = require('electron')
|
const {ipcRenderer} = window.top != null ? window.top.require('electron') : require('electron')
|
||||||
const popup = window.open()
|
const popup = window.open()
|
||||||
popup.document.write('<h1>Hello</h1>')
|
popup.document.write('<h1>Hello</h1>')
|
||||||
const content = popup.document.querySelector('h1').innerText
|
const content = popup.document.querySelector('h1').innerText
|
||||||
|
|
19
spec/fixtures/api/native-window-open-cross-origin.html
vendored
Normal file
19
spec/fixtures/api/native-window-open-cross-origin.html
vendored
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
const {ipcRenderer} = require('electron')
|
||||||
|
const popup = window.open('http://host')
|
||||||
|
const intervalID = setInterval(function () {
|
||||||
|
try {
|
||||||
|
if (popup.location.toString() !== 'about:blank') {
|
||||||
|
clearInterval(intervalID)
|
||||||
|
ipcRenderer.send('answer', `Did not throw error accessing location: ${popup.location}`)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
clearInterval(intervalID)
|
||||||
|
ipcRenderer.send('answer', error.message)
|
||||||
|
}
|
||||||
|
}, 10)
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
10
spec/fixtures/api/native-window-open-iframe.html
vendored
Normal file
10
spec/fixtures/api/native-window-open-iframe.html
vendored
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title></title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<iframe src="./native-window-open-blank.html"></iframe>
|
||||||
|
</body>
|
||||||
|
</html>
|
9
spec/fixtures/api/native-window-open-no-allowpopups.html
vendored
Normal file
9
spec/fixtures/api/native-window-open-no-allowpopups.html
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
const {ipcRenderer} = require('electron')
|
||||||
|
const popup = window.open()
|
||||||
|
ipcRenderer.send('answer', {windowOpenReturnedNull: popup == null})
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1650,4 +1650,78 @@ describe('<webview> tag', function () {
|
||||||
w.loadURL(`file://${fixtures}/pages/webview-origin-zoom-level.html`)
|
w.loadURL(`file://${fixtures}/pages/webview-origin-zoom-level.html`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('nativeWindowOpen option', () => {
|
||||||
|
beforeEach(function () {
|
||||||
|
webview.setAttribute('allowpopups', 'on')
|
||||||
|
webview.setAttribute('nodeintegration', 'on')
|
||||||
|
webview.setAttribute('webpreferences', 'nativeWindowOpen=1')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('opens window of about:blank with cross-scripting enabled', (done) => {
|
||||||
|
ipcMain.once('answer', (event, content) => {
|
||||||
|
assert.equal(content, 'Hello')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
webview.src = 'file://' + path.join(fixtures, 'api', 'native-window-open-blank.html')
|
||||||
|
document.body.appendChild(webview)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('opens window of same domain with cross-scripting enabled', (done) => {
|
||||||
|
ipcMain.once('answer', (event, content) => {
|
||||||
|
assert.equal(content, 'Hello')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
webview.src = 'file://' + path.join(fixtures, 'api', 'native-window-open-file.html')
|
||||||
|
document.body.appendChild(webview)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('returns null from window.open when allowpopups is not set', (done) => {
|
||||||
|
webview.removeAttribute('allowpopups')
|
||||||
|
ipcMain.once('answer', (event, {windowOpenReturnedNull}) => {
|
||||||
|
assert.equal(windowOpenReturnedNull, true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
webview.src = 'file://' + path.join(fixtures, 'api', 'native-window-open-no-allowpopups.html')
|
||||||
|
document.body.appendChild(webview)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('blocks accessing cross-origin frames', (done) => {
|
||||||
|
ipcMain.once('answer', (event, content) => {
|
||||||
|
assert.equal(content, 'Blocked a frame with origin "file://" from accessing a cross-origin frame.')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
webview.src = 'file://' + path.join(fixtures, 'api', 'native-window-open-cross-origin.html')
|
||||||
|
document.body.appendChild(webview)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('emits a new-window event', (done) => {
|
||||||
|
webview.addEventListener('new-window', function (e) {
|
||||||
|
assert.equal(e.url, 'http://host/')
|
||||||
|
assert.equal(e.frameName, 'host')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
webview.src = 'file://' + fixtures + '/pages/window-open.html'
|
||||||
|
document.body.appendChild(webview)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('emits a browser-window-created event', (done) => {
|
||||||
|
app.once('browser-window-created', () => {
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
webview.src = 'file://' + fixtures + '/pages/window-open.html'
|
||||||
|
document.body.appendChild(webview)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('emits a web-contents-created event', (done) => {
|
||||||
|
app.on('web-contents-created', function listener (event, contents) {
|
||||||
|
if (contents.getType() === 'window') {
|
||||||
|
app.removeListener('web-contents-created', listener)
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
webview.src = 'file://' + fixtures + '/pages/window-open.html'
|
||||||
|
document.body.appendChild(webview)
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue