From 47fd41715f2e8ac60429f798092348178418fd3a Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Mon, 26 Sep 2016 17:40:45 -0300 Subject: [PATCH] Add some tests for "sandbox" option --- spec/api-browser-window-spec.js | 193 ++++++++++++++++++++++++ spec/fixtures/api/sandbox.html | 76 ++++++++++ spec/fixtures/module/preload-sandbox.js | 13 ++ 3 files changed, 282 insertions(+) create mode 100644 spec/fixtures/api/sandbox.html create mode 100644 spec/fixtures/module/preload-sandbox.js diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index f7d30098b5f4..23c426aa9eb1 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -16,6 +16,7 @@ const ipcRenderer = require('electron').ipcRenderer const BrowserWindow = remote.require('electron').BrowserWindow const isCI = remote.getGlobal('isCi') +const {protocol} = remote describe('browser-window module', function () { var fixtures = path.resolve(__dirname, 'fixtures') @@ -572,6 +573,198 @@ describe('browser-window module', function () { w.loadURL('file://' + path.join(fixtures, 'api', 'blank.html')) }) }) + + describe('"sandbox" option', function () { + function waitForEvents (emitter, events, callback) { + let count = events.length + for (let event of events) { + emitter.once(event, () => { + if (!--count) callback() + }) + } + } + + const preload = path.join(fixtures, 'module', 'preload-sandbox.js') + + // http protocol to simulate accessing a another domain. this is required + // because the code paths for cross domain popups is different. + function crossDomainHandler (request, callback) { + callback({ + mimeType: 'text/html', + data: `

${request.url}

` + }) + } + + before(function (done) { + protocol.interceptStringProtocol('http', crossDomainHandler, function () { + done() + }) + }) + + after(function (done) { + protocol.uninterceptProtocol('http', function () { + done() + }) + }) + + it('exposes ipcRenderer to preload script', function (done) { + ipcMain.once('answer', function (event, test) { + assert.equal(test, 'preload') + done() + }) + w.destroy() + w = new BrowserWindow({ + show: false, + webPreferences: { + sandbox: true, + preload: preload + } + }) + w.loadURL('file://' + path.join(fixtures, 'api', 'preload.html')) + }) + + it('exposes "exit" event to preload script', function (done) { + w.destroy() + w = new BrowserWindow({ + show: false, + webPreferences: { + sandbox: true, + preload: preload + } + }) + let htmlPath = path.join(fixtures, 'api', 'sandbox.html?exit-event') + const pageUrl = 'file://' + htmlPath + w.loadURL(pageUrl) + ipcMain.once('answer', function (event, url) { + let expectedUrl = pageUrl + if (process.platform === 'win32') { + expectedUrl = 'file:///' + htmlPath.replace(/\\/g, '/') + } + assert.equal(url, expectedUrl) + done() + }) + }) + + it('should open windows in same domain with cross-scripting enabled', function (done) { + w.destroy() + w = new BrowserWindow({ + show: false, + webPreferences: { + sandbox: true, + preload: preload + } + }) + let htmlPath = path.join(fixtures, 'api', 'sandbox.html?window-open') + const pageUrl = 'file://' + htmlPath + w.loadURL(pageUrl) + w.webContents.once('new-window', (e, url, frameName, disposition, options) => { + let expectedUrl = pageUrl + if (process.platform === 'win32') { + expectedUrl = 'file:///' + htmlPath.replace(/\\/g, '/') + } + assert.equal(url, expectedUrl) + assert.equal(frameName, 'popup!') + assert.equal(options.x, 50) + assert.equal(options.y, 60) + assert.equal(options.width, 500) + assert.equal(options.height, 600) + ipcMain.once('answer', function (event, html) { + assert.equal(html, '

scripting from opener

') + done() + }) + }) + }) + + it('should open windows in another domain with cross-scripting disabled', function (done) { + w.destroy() + w = new BrowserWindow({ + show: false, + webPreferences: { + sandbox: true, + preload: preload + } + }) + let htmlPath = path.join(fixtures, 'api', 'sandbox.html?window-open-external') + const pageUrl = 'file://' + htmlPath + w.loadURL(pageUrl) + w.webContents.once('new-window', (e, url, frameName, disposition, options) => { + assert.equal(url, 'http://www.google.com/#q=electron') + assert.equal(options.x, 55) + assert.equal(options.y, 65) + assert.equal(options.width, 505) + assert.equal(options.height, 605) + ipcMain.once('child-loaded', function (event, openerIsNull, html) { + assert(openerIsNull) + assert.equal(html, '

http://www.google.com/#q=electron

') + ipcMain.once('answer', function (event, exceptionMessage) { + assert(/Blocked a frame with origin/.test(exceptionMessage)) + done() + }) + w.webContents.send('child-loaded') + }) + }) + }) + + it('should set ipc event sender correctly', function (done) { + w.destroy() + w = new BrowserWindow({ + show: false, + webPreferences: { + sandbox: true, + preload: preload + } + }) + let htmlPath = path.join(fixtures, 'api', 'sandbox.html?verify-ipc-sender') + const pageUrl = 'file://' + htmlPath + w.loadURL(pageUrl) + w.webContents.once('new-window', (e, url, frameName, disposition, options) => { + let parentWc = w.webContents + let childWc = options.webContents + assert.notEqual(parentWc, childWc) + ipcMain.once('parent-ready', function (event) { + assert.equal(parentWc, event.sender) + parentWc.send('verified') + }) + ipcMain.once('child-ready', function (event) { + assert.equal(childWc, event.sender) + childWc.send('verified') + }) + waitForEvents(ipcMain, [ + 'parent-answer', + 'child-answer' + ], done) + }) + }) + + describe('event handling', function () { + it('works for window events', function (done) { + waitForEvents(w, [ + 'page-title-updated' + ], done) + w.loadURL('file://' + path.join(fixtures, 'api', 'sandbox.html?window-events')) + }) + + it('works for web contents events', function (done) { + waitForEvents(w.webContents, [ + 'did-navigate', + 'did-fail-load', + 'did-stop-loading' + ], done) + w.loadURL('file://' + path.join(fixtures, 'api', 'sandbox.html?webcontents-stop')) + waitForEvents(w.webContents, [ + 'did-finish-load', + 'did-frame-finish-load', + 'did-navigate-in-page', + 'will-navigate', + 'did-start-loading', + 'did-stop-loading', + 'did-frame-finish-load', + 'dom-ready' + ], done) + w.loadURL('file://' + path.join(fixtures, 'api', 'sandbox.html?webcontents-events')) + }) + }) + }) }) describe('beforeunload handler', function () { diff --git a/spec/fixtures/api/sandbox.html b/spec/fixtures/api/sandbox.html new file mode 100644 index 000000000000..a684664a9665 --- /dev/null +++ b/spec/fixtures/api/sandbox.html @@ -0,0 +1,76 @@ + + + diff --git a/spec/fixtures/module/preload-sandbox.js b/spec/fixtures/module/preload-sandbox.js new file mode 100644 index 000000000000..39a8704e1329 --- /dev/null +++ b/spec/fixtures/module/preload-sandbox.js @@ -0,0 +1,13 @@ +(function () { + const {ipcRenderer} = require('electron') + window.ipcRenderer = ipcRenderer + if (location.protocol === 'file:') { + window.test = 'preload' + window.require = require + window.process = process + } else if (location.href !== 'about:blank') { + addEventListener('DOMContentLoaded', () => { + ipcRenderer.send('child-loaded', window.opener == null, document.body.innerHTML) + }, false) + } +})()