Add some tests for "sandbox" option

This commit is contained in:
Thiago de Arruda 2016-09-26 17:40:45 -03:00
parent a64978b812
commit 47fd41715f
3 changed files with 282 additions and 0 deletions

View file

@ -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: `<html><body><h1>${request.url}</h1></body></html>`
})
}
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, '<h1>scripting from opener</h1>')
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, '<h1>http://www.google.com/#q=electron</h1>')
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 () {

76
spec/fixtures/api/sandbox.html vendored Normal file
View file

@ -0,0 +1,76 @@
<html>
<script type="text/javascript" charset="utf-8">
if (window.opener) {
window.callback = function() {
opener.require('electron').ipcRenderer.send('answer', document.body.innerHTML)
};
} else {
const {ipcRenderer} = require('electron')
const tests = {
'window-events': () => {
document.title = 'changed'
},
'webcontents-stop': () => {
stop()
},
'webcontents-events': () => {
addEventListener('load', () => {
location.hash = 'in-page-navigate'
setTimeout(() => {
location.reload()
}, 50)
})
},
'exit-event': () => {
process.on('exit', () => {
ipcRenderer.send('answer', location.href)
})
location.assign('http://www.google.com')
},
'window-open': () => {
addEventListener('load', () => {
popup = open(window.location.href, 'popup!', 'top=60,left=50,width=500,height=600')
popup.addEventListener('DOMContentLoaded', () => {
popup.document.write('<h1>scripting from opener</h1>')
popup.callback()
}, false)
})
},
'window-open-external': () => {
addEventListener('load', () => {
ipcRenderer.once('child-loaded', (e) => {
try {
let childDoc = popup.document
} catch (e) {
ipcRenderer.send('answer', e.message)
}
})
popup = open('http://www.google.com/#q=electron', '', 'top=65,left=55,width=505,height=605')
})
},
'verify-ipc-sender': () => {
popup = open()
ipcRenderer.once('verified', () => {
ipcRenderer.send('parent-answer')
})
popup.ipcRenderer.once('verified', () => {
popup.ipcRenderer.send('child-answer')
})
setTimeout(() => {
ipcRenderer.send('parent-ready')
popup.ipcRenderer.send('child-ready')
}, 50)
}
}
addEventListener('unload', () => {
if (window.popup)
popup.close()
}, false)
let [,test] = window.location.href.split('?')
if (tests.hasOwnProperty(test))
tests[test]()
}
</script>
</html>

13
spec/fixtures/module/preload-sandbox.js vendored Normal file
View file

@ -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)
}
})()