| const KarmaEventEmitter = require('../events').EventEmitter | |
| const EventEmitter = require('events').EventEmitter | |
| const Promise = require('bluebird') | |
| const log = require('../logger').create('launcher') | |
| const helper = require('../helper') | |
| const BEING_CAPTURED = 'BEING_CAPTURED' | |
| const CAPTURED = 'CAPTURED' | |
| const BEING_KILLED = 'BEING_KILLED' | |
| const FINISHED = 'FINISHED' | |
| const RESTARTING = 'RESTARTING' | |
| const BEING_FORCE_KILLED = 'BEING_FORCE_KILLED' | |
| /** | |
| * Base launcher that any custom launcher extends. | |
| */ | |
| function BaseLauncher (id, emitter) { | |
| if (this.start) { | |
| return | |
| } | |
| // TODO(vojta): figure out how to do inheritance with DI | |
| Object.keys(EventEmitter.prototype).forEach(function (method) { | |
| this[method] = EventEmitter.prototype[method] | |
| }, this) | |
| this.bind = KarmaEventEmitter.prototype.bind.bind(this) | |
| this.emitAsync = KarmaEventEmitter.prototype.emitAsync.bind(this) | |
| this.id = id | |
| this._state = null | |
| Object.defineProperty(this, 'state', { | |
| get: () => { | |
| return this._state | |
| }, | |
| set: (toState) => { | |
| log.debug(`${this._state} -> ${toState}`) | |
| this._state = toState | |
| } | |
| }) | |
| this.error = null | |
| let killingPromise | |
| let previousUrl | |
| this.start = function (url) { | |
| previousUrl = url | |
| this.error = null | |
| this.state = BEING_CAPTURED | |
| this.emit('start', url + '?id=' + this.id + (helper.isDefined(this.displayName) ? '&displayName=' + encodeURIComponent(this.displayName) : '')) | |
| } | |
| this.kill = function () { | |
| // Already killed, or being killed. | |
| if (killingPromise) { | |
| return killingPromise | |
| } | |
| killingPromise = this.emitAsync('kill').then(() => { | |
| this.state = FINISHED | |
| }) | |
| this.state = BEING_KILLED | |
| return killingPromise | |
| } | |
| this.forceKill = function () { | |
| this.kill() | |
| this.state = BEING_FORCE_KILLED | |
| return killingPromise | |
| } | |
| this.restart = function () { | |
| if (this.state === BEING_FORCE_KILLED) { | |
| return | |
| } | |
| if (!killingPromise) { | |
| killingPromise = this.emitAsync('kill') | |
| } | |
| killingPromise.then(() => { | |
| if (this.state === BEING_FORCE_KILLED) { | |
| this.state = FINISHED | |
| } else { | |
| killingPromise = null | |
| log.debug(`Restarting ${this.name}`) | |
| this.start(previousUrl) | |
| } | |
| }) | |
| this.state = RESTARTING | |
| } | |
| this.markCaptured = function () { | |
| if (this.state === BEING_CAPTURED) { | |
| this.state = CAPTURED | |
| } | |
| } | |
| this.isCaptured = function () { | |
| return this.state === CAPTURED | |
| } | |
| this.toString = function () { | |
| return this.name | |
| } | |
| this._done = function (error) { | |
| killingPromise = killingPromise || Promise.resolve() | |
| this.error = this.error || error | |
| this.emit('done') | |
| if (this.error && this.state !== BEING_FORCE_KILLED && this.state !== RESTARTING) { | |
| emitter.emit('browser_process_failure', this) | |
| } | |
| this.state = FINISHED | |
| } | |
| this.STATE_BEING_CAPTURED = BEING_CAPTURED | |
| this.STATE_CAPTURED = CAPTURED | |
| this.STATE_BEING_KILLED = BEING_KILLED | |
| this.STATE_FINISHED = FINISHED | |
| this.STATE_RESTARTING = RESTARTING | |
| this.STATE_BEING_FORCE_KILLED = BEING_FORCE_KILLED | |
| } | |
| BaseLauncher.decoratorFactory = function (id, emitter) { | |
| return function (launcher) { | |
| BaseLauncher.call(launcher, id, emitter) | |
| } | |
| } | |
| module.exports = BaseLauncher |