-
Notifications
You must be signed in to change notification settings - Fork 116
/
chrome_xml.ts
163 lines (149 loc) · 5.14 KB
/
chrome_xml.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
import * as semver from 'semver';
import {Config} from '../config';
import {requestBody} from '../http_utils';
import {BinaryUrl} from './binary';
import {XmlConfigSource} from './config_source';
export class ChromeXml extends XmlConfigSource {
maxVersion = Config.binaryVersions().maxChrome;
constructor() {
super('chrome', Config.cdnUrls()['chrome']);
}
getUrl(version: string): Promise<BinaryUrl> {
if (version === 'latest') {
return this.getLatestChromeDriverVersion();
} else {
return this.getSpecificChromeDriverVersion(version);
}
}
/**
* Get a list of chrome drivers paths available for the configuration OS type and architecture.
*/
getVersionList(): Promise<string[]> {
return this.getXml().then(xml => {
let versionPaths: string[] = [];
let osType = this.getOsTypeName();
for (let content of xml.ListBucketResult.Contents) {
let contentKey: string = content.Key[0];
if (
// Filter for 32-bit devices, make sure x64 is not an option
(this.osarch.includes('64') || !contentKey.includes('64')) &&
// Filter for x86 macs, make sure m1 is not an option
((this.ostype === 'Darwin' && this.osarch === 'arm64') || !contentKey.includes('m1'))) {
// Filter for only the osType
if (contentKey.includes(osType)) {
versionPaths.push(contentKey);
}
}
}
return versionPaths;
});
}
/**
* Helper method, gets the ostype and gets the name used by the XML
*/
getOsTypeName(): string {
// Get the os type name.
if (this.ostype === 'Darwin') {
return 'mac';
} else if (this.ostype === 'Windows_NT') {
return 'win';
} else {
return 'linux';
}
}
/**
* Gets the latest item from the XML.
*/
private getLatestChromeDriverVersion(): Promise<BinaryUrl> {
const latestReleaseUrl = 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE';
return requestBody(latestReleaseUrl).then(latestVersion => {
return this.getSpecificChromeDriverVersion(latestVersion);
});
}
/**
* Gets a specific item from the XML.
*/
private getSpecificChromeDriverVersion(inputVersion: string): Promise<BinaryUrl> {
return this.getVersionList().then(list => {
const specificVersion = getValidSemver(inputVersion);
if (specificVersion === '') {
throw new Error(`version ${inputVersion} ChromeDriver does not exist`)
}
let itemFound = '';
for (let item of list) {
// Get a semantic version.
let version = item.split('/')[0];
if (semver.valid(version) == null) {
const lookUpVersion = getValidSemver(version);
if (semver.valid(lookUpVersion)) {
// Check to see if the specified version matches.
if (lookUpVersion === specificVersion) {
// When item found is null, check the os arch
// 64-bit version works OR not 64-bit version and the path does not have '64'
if (itemFound == '') {
if (this.osarch === 'x64' ||
(this.osarch !== 'x64' && !item.includes(this.getOsTypeName() + '64'))) {
itemFound = item;
}
if (this.osarch === 'arm64' && this.ostype === 'Darwin' && item.includes('m1')) {
itemFound = item;
}
}
// If the semantic version is the same, check os arch.
// For 64-bit systems, prefer the 64-bit version.
else if (this.osarch === 'x64') {
// No win64 version exists, so even on x64 we need to look for win32
const osTypeNameAndArch =
this.getOsTypeName() + (this.getOsTypeName() === 'win' ? '32' : '64');
if (item.includes(osTypeNameAndArch)) {
itemFound = item;
}
}
}
}
}
}
if (itemFound == '') {
return {url: '', version: inputVersion};
} else {
return {url: Config.cdnUrls().chrome + itemFound, version: inputVersion};
}
});
}
}
/**
* Chromedriver is the only binary that does not conform to semantic versioning
* and either has too little number of digits or too many. To get this to be in
* semver, we will either add a '.0' at the end or chop off the last set of
* digits. This is so we can compare to find the latest and greatest.
*
* Example:
* 2.46 -> 2.46.0
* 75.0.3770.8 -> 75.0.3770
*
* @param version
*/
export function getValidSemver(version: string): string {
let lookUpVersion = '';
// This supports downloading 2.46
try {
const oldRegex = /(\d+.\d+)/g;
const exec = oldRegex.exec(version);
if (exec) {
lookUpVersion = exec[1] + '.0';
}
} catch (_) {
// no-op: is this is not valid, do not throw here.
}
// This supports downloading 74.0.3729.6
try {
const newRegex = /(\d+.\d+.\d+).\d+/g;
const exec = newRegex.exec(version);
if (exec) {
lookUpVersion = exec[1];
}
} catch (_) {
// no-op: if this does not work, use the other regex pattern.
}
return lookUpVersion;
}