feat: add WebContents.opener and webContents.fromFrame() (#35140)

* feat: add WebContents.opener

* feat: add webContents.fromFrame(frame)

* fix: unknown type name

* test: fix and add more fromFrame cases

* docs: clarified terminology
This commit is contained in:
Samuel Maddock 2022-09-26 12:37:08 -04:00 committed by GitHub
parent 697a219bcb
commit c09c94fc98
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 104 additions and 1 deletions

View file

@ -6,7 +6,7 @@ import * as http from 'http';
import { BrowserWindow, ipcMain, webContents, session, WebContents, app, BrowserView } from 'electron/main';
import { emittedOnce } from './events-helpers';
import { closeAllWindows } from './window-helpers';
import { ifdescribe, delay, defer } from './spec-helpers';
import { ifdescribe, delay, defer, waitUntil } from './spec-helpers';
const pdfjs = require('pdfjs-dist');
const fixturesPath = path.resolve(__dirname, 'fixtures');
@ -46,6 +46,28 @@ describe('webContents module', () => {
});
});
describe('fromFrame()', () => {
it('returns WebContents for mainFrame', () => {
const contents = (webContents as any).create() as WebContents;
expect(webContents.fromFrame(contents.mainFrame)).to.equal(contents);
});
it('returns undefined for disposed frame', async () => {
const contents = (webContents as any).create() as WebContents;
const { mainFrame } = contents;
contents.destroy();
await waitUntil(() => typeof webContents.fromFrame(mainFrame) === 'undefined');
});
it('throws when passing invalid argument', async () => {
let errored = false;
try {
webContents.fromFrame({} as any);
} catch {
errored = true;
}
expect(errored).to.be.true();
});
});
describe('fromDevToolsTargetId()', () => {
it('returns WebContents for attached DevTools target', async () => {
const w = new BrowserWindow({ show: false });
@ -1281,6 +1303,54 @@ describe('webContents module', () => {
});
});
describe('opener api', () => {
afterEach(closeAllWindows);
it('can get opener with window.open()', async () => {
const w = new BrowserWindow({ show: false, webPreferences: { sandbox: true } });
await w.loadURL('about:blank');
const childPromise = emittedOnce(w.webContents, 'did-create-window');
w.webContents.executeJavaScript('window.open("about:blank")', true);
const [childWindow] = await childPromise;
expect(childWindow.webContents.opener).to.equal(w.webContents.mainFrame);
});
it('has no opener when using "noopener"', async () => {
const w = new BrowserWindow({ show: false, webPreferences: { sandbox: true } });
await w.loadURL('about:blank');
const childPromise = emittedOnce(w.webContents, 'did-create-window');
w.webContents.executeJavaScript('window.open("about:blank", undefined, "noopener")', true);
const [childWindow] = await childPromise;
expect(childWindow.webContents.opener).to.be.null();
});
it('can get opener with a[target=_blank][rel=opener]', async () => {
const w = new BrowserWindow({ show: false, webPreferences: { sandbox: true } });
await w.loadURL('about:blank');
const childPromise = emittedOnce(w.webContents, 'did-create-window');
w.webContents.executeJavaScript(`(function() {
const a = document.createElement('a');
a.target = '_blank';
a.rel = 'opener';
a.href = 'about:blank';
a.click();
}())`, true);
const [childWindow] = await childPromise;
expect(childWindow.webContents.opener).to.equal(w.webContents.mainFrame);
});
it('has no opener with a[target=_blank][rel=noopener]', async () => {
const w = new BrowserWindow({ show: false, webPreferences: { sandbox: true } });
await w.loadURL('about:blank');
const childPromise = emittedOnce(w.webContents, 'did-create-window');
w.webContents.executeJavaScript(`(function() {
const a = document.createElement('a');
a.target = '_blank';
a.rel = 'noopener';
a.href = 'about:blank';
a.click();
}())`, true);
const [childWindow] = await childPromise;
expect(childWindow.webContents.opener).to.be.null();
});
});
describe('render view deleted events', () => {
let server: http.Server;
let serverUrl: string;