UNPKG

7.56 kBJavaScriptView Raw
1'use strict'
2
3var AdmZip = require('adm-zip')
4var cp = require('child_process')
5var fs = require('fs')
6var helper = require('./lib/iedriver')
7var http = require('https')
8var kew = require('kew')
9var npmconf = require('npmconf')
10var mkdirp = require('mkdirp')
11var path = require('path')
12var rimraf = require('rimraf').sync
13var url = require('url')
14var util = require('util')
15var md5file = require('md5-file')
16
17var libPath = path.join(__dirname, 'lib', 'iedriver')
18var libPath64 = path.join(__dirname, 'lib', 'iedriver64')
19var downloadUrl = 'https://selenium-release.storage.googleapis.com/%s/IEDriverServer_Win32_%s.zip'
20var downloadUrl64 = 'https://selenium-release.storage.googleapis.com/%s/IEDriverServer_x64_%s.zip'
21
22downloadUrl = util.format(downloadUrl, helper.version, helper.binaryversion);
23downloadUrl64 = util.format(downloadUrl64, helper.version, helper.binaryversion);
24
25var fileName = util.format('IEDriverServer_Win32_%s.zip', helper.binaryversion);
26var fileName64 = util.format('IEDriverServer_x64_%s.zip', helper.binaryversion);
27
28var promise = kew.resolve(true)
29promise = promise
30 .then(function() {
31 console.log('');
32 console.log('Downloading 64 bit Windows IE driver server');
33 console.log('-----');
34 return downloadDriver(downloadUrl64, fileName64, helper.md564, libPath64, 'iedriver64');
35 })
36 .then(function() {
37 console.log('');
38 console.log('Downloading 32 bit Windows IE driver server');
39 console.log('-----');
40 return downloadDriver(downloadUrl, fileName, helper.md5, libPath, 'iedriver');
41 });
42
43function downloadDriver(_downloadUrl, _fileName, _md5, _libPath, _driverTmpDirName) {
44 var deferred = kew.defer();
45
46 npmconf.load(function(err, conf) {
47 if (err) {
48 console.log('Error loading npm config')
49 console.error(err)
50 process.exit(1)
51 return
52 }
53
54 var tmpPath = findSuitableTempDirectory(conf, _driverTmpDirName)
55 //console.log("tmp path", tmpPath);
56 var downloadedFile = path.join(tmpPath, _fileName)
57 var promise = kew.resolve(true)
58
59 // Start the install.
60 promise = promise.then(function () {
61 console.log('Downloading', _downloadUrl)
62 //console.log('Saving to', downloadedFile)
63 return requestBinary(getRequestOptions(conf.get('proxy'), _downloadUrl), downloadedFile)
64 })
65 promise.then(function () {
66 return validateMd5(downloadedFile, _md5)
67 })
68 promise.then(function () {
69 return extractDownload(downloadedFile, tmpPath)
70 })
71 promise.then(function () {
72 return copyIntoPlace(tmpPath, _libPath)
73 })
74 promise.then(function () {
75 console.log('Success! IEDriverServer binary available at', _libPath+"\\IEDriverServer.exe");
76 deferred.resolve(true);
77 })
78 .fail(function (err) {
79 console.error('iedriver installation failed', err, err.stack);
80 process.exit(1);
81 })
82 });
83
84 return deferred.promise;
85}
86
87function findSuitableTempDirectory(npmConf, driverDir) {
88 var now = Date.now()
89 var candidateTmpDirs = [
90 process.env.TMPDIR || '/tmp',
91 npmConf.get('tmp'),
92 path.join(process.cwd(), 'tmp')
93 ]
94
95 for (var i = 0; i < candidateTmpDirs.length; i++) {
96 var candidatePath = path.join(candidateTmpDirs[i], driverDir)
97
98 try {
99 mkdirp.sync(candidatePath, '0777')
100 var testFile = path.join(candidatePath, now + '.tmp')
101 fs.writeFileSync(testFile, 'test')
102 fs.unlinkSync(testFile)
103 rimraf(candidatePath);
104 mkdirp.sync(candidatePath, '0777')
105 return candidatePath
106 } catch (e) {
107 console.log(candidatePath, 'is not writable:', e.message)
108 }
109 }
110
111 console.error('Can not find a writable tmp directory, please report issue on https://github.com/barretts/iedriver/issues/ with as much information as possible.');
112 process.exit(1);
113}
114
115
116function getRequestOptions(proxyUrl, _downloadUrl) {
117 if (proxyUrl) {
118 var options = url.parse(proxyUrl)
119 options.path = _downloadUrl
120 options.headers = { Host: url.parse(_downloadUrl).host }
121 // Turn basic authorization into proxy-authorization.
122 if (options.auth) {
123 options.headers['Proxy-Authorization'] = 'Basic ' + new Buffer(options.auth).toString('base64')
124 delete options.auth
125 }
126
127 return options
128 } else {
129 return url.parse(_downloadUrl)
130 }
131}
132
133
134function requestBinary(requestOptions, filePath) {
135 var deferred = kew.defer()
136
137 var count = 0
138 var notifiedCount = 0
139 var outFile = fs.openSync(filePath, 'w')
140
141 var client = http.get(requestOptions, function (response) {
142 var status = response.statusCode
143 console.log('Receiving...')
144
145 if (status === 200) {
146 response.addListener('data', function (data) {
147 fs.writeSync(outFile, data, 0, data.length, null)
148 count += data.length
149 if ((count - notifiedCount) > 800000) {
150 console.log('Received ' + Math.floor(count / 1024) + 'K...')
151 notifiedCount = count
152 }
153 })
154
155 response.addListener('end', function () {
156 console.log('Received ' + Math.floor(count / 1024) + 'K total.')
157 fs.closeSync(outFile)
158 deferred.resolve(true)
159 })
160
161 } else {
162 client.abort()
163 deferred.reject('Error with http request: ' + util.inspect(response.headers))
164 }
165 })
166
167 return deferred.promise
168}
169
170
171function validateMd5(filePath, md5value) {
172 var deferred = kew.defer()
173
174 console.log('Expecting archive MD5 hash of', md5value);
175 var md5fileValue = md5file(filePath).toLowerCase();
176 console.log(' archive MD5 hash is', md5fileValue);
177 //console.log('Validating MD5 checksum of file ' + filePath)
178
179 try {
180 if (md5fileValue == md5value.toLowerCase()) {
181 deferred.resolve(true)
182 } else {
183 deferred.reject('Error archive md5 checksum does not match')
184 }
185 } catch (err) {
186 deferred.reject('Error trying to match md5 checksum')
187 }
188
189 return deferred.promise
190}
191
192
193function extractDownload(filePath, tmpPath) {
194 var deferred = kew.defer()
195 var options = {cwd: tmpPath}
196
197 //console.log('Extracting zip contents')
198 try {
199 var zip = new AdmZip(filePath)
200 zip.extractAllTo(tmpPath, true)
201 deferred.resolve(true)
202 } catch (err) {
203 deferred.reject('Error extracting archive ' + err.stack)
204 }
205 return deferred.promise
206}
207
208function rmDir(dirPath) {
209 try { var files = fs.readdirSync(dirPath); }
210 catch(e) { return; }
211 if (files.length > 0)
212 for (var i = 0; i < files.length; i++) {
213 var filePath = dirPath + '/' + files[i];
214 if (fs.statSync(filePath).isFile())
215 fs.unlinkSync(filePath);
216 else
217 rmDir(filePath);
218 }
219 fs.rmdirSync(dirPath);
220};
221
222
223function copyIntoPlace(tmpPath, targetPath) {
224 rimraf(targetPath);
225 //console.log("Copying to target path", targetPath, "from", tmpPath);
226 fs.mkdirSync(targetPath);
227
228 // Look for the extracted directory, so we can rename it.
229 var files = fs.readdirSync(tmpPath);
230 var promises = files.map(function (name) {
231 var deferred = kew.defer();
232
233 var file = path.join(tmpPath, name);
234 var reader = fs.createReadStream(file);
235
236 var targetFile = path.join(targetPath, name);
237 var writer = fs.createWriteStream(targetFile);
238 writer.on("close", function() {
239 //console.log("copied", name);
240 deferred.resolve(true);
241 });
242
243 reader.pipe(writer);
244 return deferred.promise;
245 });
246
247 return kew.all(promises);
248}