From d67f25ce43645804b6c1ed78eff42d3f11d9ae44 Mon Sep 17 00:00:00 2001 From: Jeremy Apthorp Date: Mon, 14 Oct 2019 09:00:34 -0700 Subject: [PATCH] test: expand window.opener test and move to main process (#20549) --- spec-main/chromium-spec.ts | 69 +++++++++++++++++++++++++++++++++++++- spec/chromium-spec.js | 47 -------------------------- 2 files changed, 68 insertions(+), 48 deletions(-) diff --git a/spec-main/chromium-spec.ts b/spec-main/chromium-spec.ts index c545531b8b83..659db32f7bed 100644 --- a/spec-main/chromium-spec.ts +++ b/spec-main/chromium-spec.ts @@ -1,7 +1,7 @@ import * as chai from 'chai' import { expect } from 'chai' import * as chaiAsPromised from 'chai-as-promised' -import { BrowserWindow, WebContents, session, ipcMain, app } from 'electron' +import { BrowserWindow, WebContents, session, ipcMain, app, protocol } from 'electron' import { emittedOnce } from './events-helpers' import { closeAllWindows } from './window-helpers' import * as https from 'https' @@ -11,6 +11,7 @@ import * as fs from 'fs' import * as url from 'url' import * as ChildProcess from 'child_process' import { EventEmitter } from 'events' +import { promisify } from 'util' const features = process.electronBinding('features') @@ -632,4 +633,70 @@ describe('chromium features', () => { expect(firstDeviceIds).to.not.deep.equal(secondDeviceIds) }) }) + + describe('window.opener access', () => { + const scheme = 'app' + + const fileUrl = `file://${fixturesPath}/pages/window-opener-location.html` + const httpUrl1 = `${scheme}://origin1` + const httpUrl2 = `${scheme}://origin2` + + const table = [ + {parent: fileUrl, child: httpUrl1, nodeIntegration: false, nativeWindowOpen: false, openerAccessible: false}, + {parent: fileUrl, child: httpUrl1, nodeIntegration: false, nativeWindowOpen: true, openerAccessible: false}, + {parent: fileUrl, child: httpUrl1, nodeIntegration: true, nativeWindowOpen: false, openerAccessible: true}, + {parent: fileUrl, child: httpUrl1, nodeIntegration: true, nativeWindowOpen: true, openerAccessible: false}, + + {parent: httpUrl1, child: fileUrl, nodeIntegration: false, nativeWindowOpen: false, openerAccessible: false}, + //{parent: httpUrl1, child: fileUrl, nodeIntegration: false, nativeWindowOpen: true, openerAccessible: false}, // can't window.open() + {parent: httpUrl1, child: fileUrl, nodeIntegration: true, nativeWindowOpen: false, openerAccessible: true}, + //{parent: httpUrl1, child: fileUrl, nodeIntegration: true, nativeWindowOpen: true, openerAccessible: false}, // can't window.open() + + // NB. this is different from Chrome's behavior, which isolates file: urls from each other + {parent: fileUrl, child: fileUrl, nodeIntegration: false, nativeWindowOpen: false, openerAccessible: true}, + {parent: fileUrl, child: fileUrl, nodeIntegration: false, nativeWindowOpen: true, openerAccessible: true}, + {parent: fileUrl, child: fileUrl, nodeIntegration: true, nativeWindowOpen: false, openerAccessible: true}, + {parent: fileUrl, child: fileUrl, nodeIntegration: true, nativeWindowOpen: true, openerAccessible: true}, + + {parent: httpUrl1, child: httpUrl1, nodeIntegration: false, nativeWindowOpen: false, openerAccessible: true}, + {parent: httpUrl1, child: httpUrl1, nodeIntegration: false, nativeWindowOpen: true, openerAccessible: true}, + {parent: httpUrl1, child: httpUrl1, nodeIntegration: true, nativeWindowOpen: false, openerAccessible: true}, + {parent: httpUrl1, child: httpUrl1, nodeIntegration: true, nativeWindowOpen: true, openerAccessible: true}, + + {parent: httpUrl1, child: httpUrl2, nodeIntegration: false, nativeWindowOpen: false, openerAccessible: false}, + {parent: httpUrl1, child: httpUrl2, nodeIntegration: false, nativeWindowOpen: true, openerAccessible: false}, + {parent: httpUrl1, child: httpUrl2, nodeIntegration: true, nativeWindowOpen: false, openerAccessible: true}, + {parent: httpUrl1, child: httpUrl2, nodeIntegration: true, nativeWindowOpen: true, openerAccessible: false}, + ] + + before(async () => { + await promisify(protocol.registerFileProtocol)(scheme, (request, callback) => { + callback(`${fixturesPath}/pages/window-opener-location.html`) + }) + }) + after(async () => { + await promisify(protocol.unregisterProtocol)(scheme) + }) + afterEach(closeAllWindows) + + for (const {parent, child, nodeIntegration, nativeWindowOpen, openerAccessible} of table) { + const s = (url: string) => url.startsWith('file') ? 'file://...' : url + const description = `when parent=${s(parent)} opens child=${s(child)} with nodeIntegration=${nodeIntegration} nativeWindowOpen=${nativeWindowOpen}, child should ${openerAccessible ? '' : 'not '}be able to access opener` + it(description, async () => { + const w = new BrowserWindow({show: false, webPreferences: { nodeIntegration: true, nativeWindowOpen }}) + await w.loadURL(parent) + const childOpenerLocation = await w.webContents.executeJavaScript(`new Promise(resolve => { + window.addEventListener('message', function f(e) { + resolve(e.data) + }) + window.open(${JSON.stringify(child)}, "", "show=no,nodeIntegration=${nodeIntegration ? "yes" : "no"}") + })`) + if (openerAccessible) { + expect(childOpenerLocation).to.be.a('string') + } else { + expect(childOpenerLocation).to.be.null() + } + }) + } + }) }) diff --git a/spec/chromium-spec.js b/spec/chromium-spec.js index da54d593cfe8..708bd32e78ba 100644 --- a/spec/chromium-spec.js +++ b/spec/chromium-spec.js @@ -195,53 +195,6 @@ describe('chromium feature', () => { }) }) - describe('window.opener access from BrowserWindow', () => { - const scheme = 'other' - const url = `${scheme}://${fixtures}/pages/window-opener-location.html` - let w = null - - before((done) => { - protocol.registerFileProtocol(scheme, (request, callback) => { - callback(`${fixtures}/pages/window-opener-location.html`) - }, (error) => done(error)) - }) - - after(() => { - protocol.unregisterProtocol(scheme) - }) - - afterEach(() => { - w.close() - }) - - it('fails when origin of current window does not match opener', (done) => { - listener = (event) => { - expect(event.data).to.equal(null) - done() - } - window.addEventListener('message', listener) - w = window.open(url, '', 'show=no,nodeIntegration=no') - }) - - it('works when origin matches', (done) => { - listener = (event) => { - expect(event.data).to.equal(location.href) - done() - } - window.addEventListener('message', listener) - w = window.open(`file://${fixtures}/pages/window-opener-location.html`, '', 'show=no,nodeIntegration=no') - }) - - it('works when origin does not match opener but has node integration', (done) => { - listener = (event) => { - expect(event.data).to.equal(location.href) - done() - } - window.addEventListener('message', listener) - w = window.open(url, '', 'show=no,nodeIntegration=yes') - }) - }) - describe('window.opener access from ', () => { const scheme = 'other' const srcPath = `${fixtures}/pages/webview-opener-postMessage.html`