fix: window.open doesn't work correctly in child window (#25080)

If speculative render view host is deleted during naviagation to
page we try to open with call to window.open window is destroyed
right after it is created. It may happen when naviagation triggers
redirect from http to https. To void that we should emit event
current-render-view-deleted only when render view host which was
destroyed is the current webcontent's rvh.
This commit is contained in:
CezaryKulakowski 2020-10-08 01:11:19 +02:00 committed by GitHub
parent 3e627f7700
commit 73adeef877
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 26 additions and 16 deletions

View file

@ -1156,6 +1156,10 @@ describe('webContents module', () => {
res.end();
} else if (req.url === '/redirected') {
res.end('<html><script>window.localStorage</script></html>');
} else if (req.url === '/first-window-open') {
res.end(`<html><script>window.open('${serverUrl}/second-window-open', 'first child');</script></html>`);
} else if (req.url === '/second-window-open') {
res.end('<html><script>window.open(\'wrong://url\', \'second child\');</script></html>');
} else {
res.end();
}
@ -1192,6 +1196,27 @@ describe('webContents module', () => {
expect(currentRenderViewDeletedEmitted).to.be.false('current-render-view-deleted was emitted');
});
it('does not emit current-render-view-deleted when speculative RVHs are deleted and nativeWindowOpen is set to true', async () => {
const parentWindow = new BrowserWindow({ show: false, webPreferences: { nativeWindowOpen: true } });
let currentRenderViewDeletedEmitted = false;
let childWindow:BrowserWindow;
const destroyed = emittedOnce(parentWindow.webContents, 'destroyed');
const renderViewDeletedHandler = () => {
currentRenderViewDeletedEmitted = true;
};
app.once('browser-window-created', (event, window) => {
childWindow = window;
window.webContents.on('current-render-view-deleted' as any, renderViewDeletedHandler);
});
parentWindow.loadURL(`${serverUrl}/first-window-open`);
setTimeout(() => {
childWindow.webContents.removeListener('current-render-view-deleted' as any, renderViewDeletedHandler);
parentWindow.close();
}, 500);
await destroyed;
expect(currentRenderViewDeletedEmitted).to.be.false('child window was destroyed');
});
it('emits current-render-view-deleted if the current RVHs are deleted', async () => {
const w = new BrowserWindow({ show: false });
let currentRenderViewDeletedEmitted = false;