130 lines
3.4 KiB
JavaScript
130 lines
3.4 KiB
JavaScript
// Karme IE Launcher
|
|
// =================
|
|
|
|
// Dependencies
|
|
// ------------
|
|
|
|
var path = require('path')
|
|
var fs = require('fs')
|
|
var urlparse = require('url').parse
|
|
var urlformat = require('url').format
|
|
var exec = require('child_process').exec
|
|
var _ = require('lodash')
|
|
|
|
// Constants
|
|
// ---------
|
|
|
|
var PROCESS_NAME = 'iexplore.exe'
|
|
|
|
// Find the ie executable
|
|
function getInternetExplorerExe () {
|
|
var suffix = path.join('Internet Explorer', PROCESS_NAME)
|
|
var locations = _.map(_.compact([
|
|
process.env['PROGRAMW6432'],
|
|
process.env['PROGRAMFILES(X86)'],
|
|
process.env['PROGRAMFILES']
|
|
]), function (prefix) {
|
|
return path.join(prefix, suffix)
|
|
})
|
|
|
|
return _.find(locations, function (location) {
|
|
return fs.existsSync(location)
|
|
})
|
|
}
|
|
|
|
// Constructor
|
|
function IEBrowser (baseBrowserDecorator, logger, args) {
|
|
baseBrowserDecorator(this)
|
|
|
|
var log = logger.create('launcher')
|
|
var flags = args.flags || []
|
|
|
|
// Handle x-ua-compatible option:
|
|
//
|
|
// Usage :
|
|
// customLaunchers: {
|
|
// IE9: {
|
|
// base: 'IE',
|
|
// 'x-ua-compatible': 'IE=EmulateIE9'
|
|
// }
|
|
// }
|
|
//
|
|
// This is done by passing the option on the url, in response the Karma server will
|
|
// set the following meta in the page.
|
|
// <meta http-equiv="X-UA-Compatible" content="[VALUE]"/>
|
|
function handleXUaCompatible (args, urlObj) {
|
|
if (args['x-ua-compatible']) {
|
|
urlObj.query['x-ua-compatible'] = args['x-ua-compatible']
|
|
}
|
|
}
|
|
|
|
// Spawning iexplore.exe spawns two processes (IE does that). The way karma kills the
|
|
// browser process (hard kill) leaves the other process in memory.
|
|
//
|
|
// The second process is created using command-line args like this:
|
|
// "C:\Program Files\Internet Explorer\iexplore.exe" SCODEF:2632 CREDAT:275457 /prefetch:2
|
|
// Where the SCODEF value is the pid of the 'original' process created by this launcher.
|
|
//
|
|
// This function kills any iexplore.exe process who's command line args match 'SCODEF:pid'.
|
|
// On IE11 this will kill the extra process. On older versions, no process will be found.
|
|
function killExtraIEProcess (pid, cb) {
|
|
var scodef = 'SCODEF:' + pid
|
|
|
|
// wmic.exe : http://msdn.microsoft.com/en-us/library/aa394531(v=vs.85).aspx
|
|
var wmic = 'wmic.exe Path win32_Process ' +
|
|
'where "Name=\'' + PROCESS_NAME + "' and " +
|
|
"CommandLine Like '%" + scodef + '%\'" call Terminate'
|
|
|
|
exec(wmic, function (err) {
|
|
if (err) {
|
|
log.error('Killing extra IE process failed. ' + err)
|
|
} else {
|
|
log.debug('Killed extra IE process ' + pid)
|
|
}
|
|
cb()
|
|
})
|
|
}
|
|
|
|
this._getOptions = function (url) {
|
|
var urlObj = urlparse(url, true)
|
|
|
|
handleXUaCompatible(args, urlObj)
|
|
|
|
// url.format does not want search attribute
|
|
delete urlObj.search
|
|
url = urlformat(urlObj)
|
|
|
|
return flags.concat(url)
|
|
}
|
|
|
|
var baseOnProcessExit = this._onProcessExit
|
|
this._onProcessExit = function (code, errorOutput) {
|
|
var pid = this._process.pid
|
|
killExtraIEProcess(pid, function () {
|
|
if (baseOnProcessExit) {
|
|
baseOnProcessExit(code, errorOutput)
|
|
}
|
|
})
|
|
}
|
|
|
|
// this is to expose the function for unit testing
|
|
this._getInternetExplorerExe = getInternetExplorerExe
|
|
}
|
|
|
|
IEBrowser.prototype = {
|
|
name: 'IE',
|
|
DEFAULT_CMD: {
|
|
win32: getInternetExplorerExe()
|
|
},
|
|
ENV_CMD: 'IE_BIN'
|
|
}
|
|
|
|
IEBrowser.$inject = ['baseBrowserDecorator', 'logger', 'args']
|
|
|
|
// Publish di module
|
|
// -----------------
|
|
|
|
module.exports = {
|
|
'launcher:IE': ['type', IEBrowser]
|
|
}
|