diff --git a/lib/runner.js b/lib/runner.js index 4a822d6e..016b4429 100644 --- a/lib/runner.js +++ b/lib/runner.js @@ -12,11 +12,14 @@ var renderer = require('electron').ipcMain var app = require('electron').app var urlFormat = require('url') var FrameManager = require('./frame-manager') - +var EventEmitter = require('events'); // URL protocols that don't need to be checked for validity const KNOWN_PROTOCOLS = ['http', 'https', 'file', 'about', 'javascript'] // Property for tracking whether a window is ready for interaction const IS_READY = Symbol('isReady') +// Used to register multiple listeners on WebRequest targets that only +// support one listener +const WebRequestEventTarget = new EventEmitter(); /** * Handle uncaught exceptions in the main electron process @@ -134,6 +137,40 @@ app.on('ready', function() { win.webContents.setUserAgent(options.userAgent) } + /** + * Set up the WebRequest listeners. + * Electron only serves one at a time, so we need to create + * "master" listeners if we'd like to subscribe multiple listeners. + */ + + win.webContents.session.webRequest.onBeforeRedirect(function(details) { + WebRequestEventTarget.emit("BeforeRedirect", details) + }) + win.webContents.session.webRequest.onBeforeRequest(function(details, cb) { + WebRequestEventTarget.emit("BeforeRequest", details) + cb({}) + }) + win.webContents.session.webRequest.onBeforeSendHeaders(function(details, cb) { + WebRequestEventTarget.emit("BeforeSendHeaders", details) + cb({}) + }) + win.webContents.session.webRequest.onCompleted(function(details) { + WebRequestEventTarget.emit("Completed", details) + }) + win.webContents.session.webRequest.onErrorOccurred(function(details) { + WebRequestEventTarget.emit("ErrorOccurred", details) + }) + win.webContents.session.webRequest.onHeadersReceived(function(details, cb) { + WebRequestEventTarget.emit("HeadersReceived", details) + cb({}) + }) + win.webContents.session.webRequest.onResponseStarted(function(details) { + WebRequestEventTarget.emit("ResponseStarted", details) + }) + win.webContents.session.webRequest.onSendHeaders(function(details) { + WebRequestEventTarget.emit("SendHeaders", details) + }) + /** * Pass along web content events */ @@ -158,14 +195,8 @@ app.on('ready', function() { ) win.webContents.on('did-start-loading', forward('did-start-loading')) win.webContents.on('did-stop-loading', forward('did-stop-loading')) - win.webContents.on( - 'did-get-response-details', - forward('did-get-response-details') - ) - win.webContents.on( - 'did-get-redirect-request', - forward('did-get-redirect-request') - ) + WebRequestEventTarget.on('ResponseStarted', forward('did-get-response-details')) + WebRequestEventTarget.on('BeforeRedirect', forward('did-get-redirect-request')) win.webContents.on('dom-ready', forward('dom-ready')) win.webContents.on('page-favicon-updated', forward('page-favicon-updated')) win.webContents.on('new-window', forward('new-window')) @@ -262,24 +293,22 @@ app.on('ready', function() { } } - function handleDetails( - event, - status, - newUrl, - oldUrl, + function handleDetails({ + url, statusCode, method, referrer, - headers, + responseHeaders, resourceType - ) { + }) { + parent.emit('log', new Error().stack.match(/runner.js:[0-9]+:[0-9]+/)[0]) if (resourceType === 'mainFrame') { responseData = { - url: newUrl, + url, code: statusCode, - method: method, - referrer: referrer, - headers: headers + method, + referrer, + headers: responseHeaders } } } @@ -300,8 +329,8 @@ app.on('ready', function() { 'did-fail-provisional-load', handleFailure ) - win.webContents.removeListener( - 'did-get-response-details', + WebRequestEventTarget.removeListener( + 'ResponseStarted', handleDetails ) win.webContents.removeListener('dom-ready', handleDomReady) @@ -318,7 +347,7 @@ app.on('ready', function() { if (!protocol || KNOWN_PROTOCOLS.includes(protocol)) { return callback(true) } - electron.protocol.isProtocolHandled(protocol, callback) + callback(electron.protocol.isProtocolRegistered(protocol)) } function startLoading() { @@ -333,7 +362,7 @@ app.on('ready', function() { win.webContents.on('did-fail-load', handleFailure) win.webContents.on('did-fail-provisional-load', handleFailure) - win.webContents.on('did-get-response-details', handleDetails) + WebRequestEventTarget.addListener('ResponseStarted', handleDetails) win.webContents.on('dom-ready', handleDomReady) win.webContents.on('did-finish-load', handleFinish) win.webContents.loadURL(url, loadUrlOptions) @@ -479,15 +508,10 @@ app.on('ready', function() { */ parent.respondTo('screenshot', function(path, clip, done) { - // https://gist.github.com/twolfson/0d374d9d7f26eefe7d38 - var args = [ - function handleCapture(img) { - done(null, img.toPNG()) - } - ] - if (clip) args.unshift(clip) frameManager.requestFrame(function() { - win.capturePage.apply(win, args) + win.capturePage(clip) + .then(img => done(null, img.toPNG())) + .catch(done) }) }) @@ -498,9 +522,9 @@ app.on('ready', function() { parent.respondTo('html', function(path, saveType, done) { // https://github.com/atom/electron/blob/master/docs/api/web-contents.md#webcontentssavepagefullpath-savetype-callback saveType = saveType || 'HTMLComplete' - win.webContents.savePage(path, saveType, function(err) { - done(err) - }) + win.webContents.savePage(path, saveType) + .then(done) + .catch(done) }) /** @@ -516,10 +540,9 @@ app.on('ready', function() { landscape: false }) - win.webContents.printToPDF(options, function(err, data) { - if (err) return done(err) - done(null, data) - }) + win.webContents.printToPDF(options) + .then(data => done(null, data)) + .catch(done) }) /** @@ -535,10 +558,11 @@ app.on('ready', function() { ) parent.emit('log', 'getting cookie: ' + JSON.stringify(details)) - win.webContents.session.cookies.get(details, function(err, cookies) { - if (err) return done(err) - done(null, details.name ? cookies[0] : cookies) - }) + win.webContents.session.cookies.get(details) + .then(function(cookies) { + done(null, details.name ? cookies[0] : cookies) + }) + .catch(done) }) /** @@ -557,10 +581,11 @@ app.on('ready', function() { ) parent.emit('log', 'setting cookie: ' + JSON.stringify(details)) - win.webContents.session.cookies.set(details, function(err) { - if (err) done(err) - else if (!--pending) done() - }) + win.webContents.session.cookies.set(details) + .then(function() { + done() + }) + .catch(done) } }) @@ -574,9 +599,9 @@ app.on('ready', function() { if (cookies.length == 0) { getCookies = cb => - win.webContents.session.cookies.get({ url: url }, (error, cookies) => { - cb(error, cookies.map(cookie => cookie.name)) - }) + win.webContents.session.cookies.get({ url: url }) + .then( cookies => cb(null, cookies.map(cookie => cookie.name))) + .catch(cb) } getCookies((error, cookies) => { @@ -590,10 +615,9 @@ app.on('ready', function() { //for each cookie name in cookies, for (var i = 0, cookie; (cookie = cookies[i]); i++) { //remove the cookie from the url - win.webContents.session.cookies.remove(url, cookie, function(err) { - if (err) done(err) - else if (!--pending) done() - }) + win.webContents.session.cookies.remove(url, cookie) + .then(done) + .catch(done) } }) }) @@ -606,12 +630,9 @@ app.on('ready', function() { win.webContents.session.clearStorageData( { storages: ['cookies'] - }, - function(err) { - if (err) return done(err) - return done() - } - ) + }) + .then(done) + .catch(done) }) /** diff --git a/test/index.js b/test/index.js index b6193236..e6e4d49b 100644 --- a/test/index.js +++ b/test/index.js @@ -1392,7 +1392,7 @@ describe('Nightmare', function() { }) assert.fail("shouldn't have got here") } catch (e) { - assert.equal(e.message, 'Setting cookie failed') + assert.equal(e.message, 'Failed to parse cookie') } }) })