fix: invoke the window open handler for _blank links (#28498)
* fix: invoke the window open handler for _blank links * add test
This commit is contained in:
parent
3ed8da0931
commit
62b38812b6
3 changed files with 80 additions and 24 deletions
|
@ -433,7 +433,11 @@ WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event,
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return null;
|
return null;
|
||||||
} else if (response.action === 'allow') {
|
} else if (response.action === 'allow') {
|
||||||
if (typeof response.overrideBrowserWindowOptions === 'object' && response.overrideBrowserWindowOptions !== null) { return response.overrideBrowserWindowOptions; } else { return {}; }
|
if (typeof response.overrideBrowserWindowOptions === 'object' && response.overrideBrowserWindowOptions !== null) {
|
||||||
|
return response.overrideBrowserWindowOptions;
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
console.error('The window open handler response must be an object with an \'action\' property of \'allow\' or \'deny\'.');
|
console.error('The window open handler response must be an object with an \'action\' property of \'allow\' or \'deny\'.');
|
||||||
|
@ -565,19 +569,22 @@ WebContents.prototype._init = function () {
|
||||||
// Make new windows requested by links behave like "window.open".
|
// Make new windows requested by links behave like "window.open".
|
||||||
this.on('-new-window' as any, (event: ElectronInternal.Event, url: string, frameName: string, disposition: string,
|
this.on('-new-window' as any, (event: ElectronInternal.Event, url: string, frameName: string, disposition: string,
|
||||||
rawFeatures: string, referrer: Electron.Referrer, postData: PostData) => {
|
rawFeatures: string, referrer: Electron.Referrer, postData: PostData) => {
|
||||||
openGuestWindow({
|
const options = this._callWindowOpenHandler(event, url, frameName, rawFeatures);
|
||||||
event,
|
if (!event.defaultPrevented) {
|
||||||
embedder: event.sender,
|
openGuestWindow({
|
||||||
disposition,
|
event,
|
||||||
referrer,
|
embedder: event.sender,
|
||||||
postData,
|
disposition,
|
||||||
overrideBrowserWindowOptions: {},
|
referrer,
|
||||||
windowOpenArgs: {
|
postData,
|
||||||
url,
|
overrideBrowserWindowOptions: options || {},
|
||||||
frameName,
|
windowOpenArgs: {
|
||||||
features: rawFeatures
|
url,
|
||||||
}
|
frameName,
|
||||||
});
|
features: rawFeatures
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let windowOpenOverriddenOptions: BrowserWindowConstructorOptions | null = null;
|
let windowOpenOverriddenOptions: BrowserWindowConstructorOptions | null = null;
|
||||||
|
|
|
@ -42,7 +42,6 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition
|
||||||
windowOpenArgs: WindowOpenArgs,
|
windowOpenArgs: WindowOpenArgs,
|
||||||
}): BrowserWindow | undefined {
|
}): BrowserWindow | undefined {
|
||||||
const { url, frameName, features } = windowOpenArgs;
|
const { url, frameName, features } = windowOpenArgs;
|
||||||
const isNativeWindowOpen = !!guest;
|
|
||||||
const { options: browserWindowOptions, additionalFeatures } = makeBrowserWindowOptions({
|
const { options: browserWindowOptions, additionalFeatures } = makeBrowserWindowOptions({
|
||||||
embedder,
|
embedder,
|
||||||
features,
|
features,
|
||||||
|
@ -74,11 +73,14 @@ export function openGuestWindow ({ event, embedder, guest, referrer, disposition
|
||||||
webContents: guest,
|
webContents: guest,
|
||||||
...browserWindowOptions
|
...browserWindowOptions
|
||||||
});
|
});
|
||||||
if (!isNativeWindowOpen) {
|
if (!guest) {
|
||||||
// We should only call `loadURL` if the webContents was constructed by us in
|
// We should only call `loadURL` if the webContents was constructed by us in
|
||||||
// the case of BrowserWindowProxy (non-sandboxed, nativeWindowOpen: false),
|
// the case of BrowserWindowProxy (non-sandboxed, nativeWindowOpen: false),
|
||||||
// as navigating to the url when creating the window from an existing
|
// as navigating to the url when creating the window from an existing
|
||||||
// webContents is not necessary (it will navigate there anyway).
|
// webContents is not necessary (it will navigate there anyway).
|
||||||
|
// This can also happen if we enter this function from OpenURLFromTab, in
|
||||||
|
// which case the browser process is responsible for initiating navigation
|
||||||
|
// in the new window.
|
||||||
window.loadURL(url, {
|
window.loadURL(url, {
|
||||||
httpReferrer: referrer,
|
httpReferrer: referrer,
|
||||||
...(postData && {
|
...(postData && {
|
||||||
|
|
|
@ -112,16 +112,21 @@ describe('webContents.setWindowOpenHandler', () => {
|
||||||
const { browserWindowOptions } = testConfig[testName];
|
const { browserWindowOptions } = testConfig[testName];
|
||||||
|
|
||||||
describe(testName, () => {
|
describe(testName, () => {
|
||||||
beforeEach((done) => {
|
beforeEach(async () => {
|
||||||
browserWindow = new BrowserWindow(browserWindowOptions);
|
browserWindow = new BrowserWindow(browserWindowOptions);
|
||||||
browserWindow.loadURL('about:blank');
|
await browserWindow.loadURL('about:blank');
|
||||||
browserWindow.on('ready-to-show', () => { browserWindow.show(); done(); });
|
browserWindow.show();
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(closeAllWindows);
|
afterEach(closeAllWindows);
|
||||||
|
|
||||||
it('does not fire window creation events if an override returns action: deny', (done) => {
|
it('does not fire window creation events if an override returns action: deny', async () => {
|
||||||
browserWindow.webContents.setWindowOpenHandler(() => ({ action: 'deny' }));
|
const denied = new Promise((resolve) => {
|
||||||
|
browserWindow.webContents.setWindowOpenHandler(() => {
|
||||||
|
setTimeout(resolve);
|
||||||
|
return { action: 'deny' };
|
||||||
|
});
|
||||||
|
});
|
||||||
browserWindow.webContents.on('new-window', () => {
|
browserWindow.webContents.on('new-window', () => {
|
||||||
assert.fail('new-window should not to be called with an overridden window.open');
|
assert.fail('new-window should not to be called with an overridden window.open');
|
||||||
});
|
});
|
||||||
|
@ -132,9 +137,51 @@ describe('webContents.setWindowOpenHandler', () => {
|
||||||
|
|
||||||
browserWindow.webContents.executeJavaScript("window.open('about:blank') && true");
|
browserWindow.webContents.executeJavaScript("window.open('about:blank') && true");
|
||||||
|
|
||||||
setTimeout(() => {
|
await denied;
|
||||||
done();
|
});
|
||||||
}, 500);
|
|
||||||
|
it('is called when clicking on a target=_blank link', async () => {
|
||||||
|
const denied = new Promise((resolve) => {
|
||||||
|
browserWindow.webContents.setWindowOpenHandler(() => {
|
||||||
|
setTimeout(resolve);
|
||||||
|
return { action: 'deny' };
|
||||||
|
});
|
||||||
|
});
|
||||||
|
browserWindow.webContents.on('new-window', () => {
|
||||||
|
assert.fail('new-window should not to be called with an overridden window.open');
|
||||||
|
});
|
||||||
|
|
||||||
|
browserWindow.webContents.on('did-create-window', () => {
|
||||||
|
assert.fail('did-create-window should not to be called with an overridden window.open');
|
||||||
|
});
|
||||||
|
|
||||||
|
await browserWindow.webContents.loadURL('data:text/html,<a target="_blank" href="http://example.com" style="display: block; width: 100%; height: 100%; position: fixed; left: 0; top: 0;">link</a>');
|
||||||
|
browserWindow.webContents.sendInputEvent({ type: 'mouseDown', x: 10, y: 10, button: 'left', clickCount: 1 });
|
||||||
|
browserWindow.webContents.sendInputEvent({ type: 'mouseUp', x: 10, y: 10, button: 'left', clickCount: 1 });
|
||||||
|
|
||||||
|
await denied;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('is called when shift-clicking on a link', async () => {
|
||||||
|
const denied = new Promise((resolve) => {
|
||||||
|
browserWindow.webContents.setWindowOpenHandler(() => {
|
||||||
|
setTimeout(resolve);
|
||||||
|
return { action: 'deny' };
|
||||||
|
});
|
||||||
|
});
|
||||||
|
browserWindow.webContents.on('new-window', () => {
|
||||||
|
assert.fail('new-window should not to be called with an overridden window.open');
|
||||||
|
});
|
||||||
|
|
||||||
|
browserWindow.webContents.on('did-create-window', () => {
|
||||||
|
assert.fail('did-create-window should not to be called with an overridden window.open');
|
||||||
|
});
|
||||||
|
|
||||||
|
await browserWindow.webContents.loadURL('data:text/html,<a href="http://example.com" style="display: block; width: 100%; height: 100%; position: fixed; left: 0; top: 0;">link</a>');
|
||||||
|
browserWindow.webContents.sendInputEvent({ type: 'mouseDown', x: 10, y: 10, button: 'left', clickCount: 1, modifiers: ['shift'] });
|
||||||
|
browserWindow.webContents.sendInputEvent({ type: 'mouseUp', x: 10, y: 10, button: 'left', clickCount: 1, modifiers: ['shift'] });
|
||||||
|
|
||||||
|
await denied;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fires handler with correct params', (done) => {
|
it('fires handler with correct params', (done) => {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue