Skip to content

Commit

Permalink
fix: Fix Chromedriver download for version 115+ (shaka-project#28)
Browse files Browse the repository at this point in the history
Chrome has a new distribution system since version 115.
  • Loading branch information
joeyparrish authored Aug 17, 2023
1 parent edb2cdf commit 1d17e40
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 5 deletions.
115 changes: 110 additions & 5 deletions chrome.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ const os = require('os');
const path = require('path');

const CDN_URL = 'https://chromedriver.storage.googleapis.com';
const VERSION_DATA_URL = 'https://googlechromelabs.github.io/chrome-for-testing/latest-versions-per-milestone-with-downloads.json';
// Chrome distribution changed in version 115.
const NEW_CHROME_DISTRIBUTION_VERSION = 115;

/**
* An installer for chromedriver for desktop Chrome.
Expand Down Expand Up @@ -64,10 +67,26 @@ class ChromeWebDriverInstaller extends WebDriverInstallerBase {
*/
async getBestDriverVersion(browserVersion) {
const idealMajorVersion = parseInt(browserVersion.split('.')[0], 10);
return await InstallerUtils.fetchVersionUrlWithAutomaticDowngrade(
idealMajorVersion,
/* minMajorVersion */ idealMajorVersion - 2,
(majorVersion) => `${CDN_URL}/LATEST_RELEASE_${majorVersion}`);

if (idealMajorVersion < NEW_CHROME_DISTRIBUTION_VERSION) {
return await InstallerUtils.fetchVersionUrl(
`${CDN_URL}/LATEST_RELEASE_${idealMajorVersion}`);
} else {
const data = await this.getVersionData_();

// Fall back on the major version if necessary.
// We haven't seen this become necessary yet since the new distribution
// mechanism debuted, but better safe than sorry.
let majorVersion = idealMajorVersion;
while (majorVersion >= NEW_CHROME_DISTRIBUTION_VERSION) {
if (majorVersion in data['milestones']) {
return data['milestones'][majorVersion]['version'];
}
majorVersion -= 1;
}

throw new Error(`Unable to locate chromedriver ${idealMajorVersion}!`);
}
}

/**
Expand All @@ -76,12 +95,31 @@ class ChromeWebDriverInstaller extends WebDriverInstallerBase {
* @return {!Promise}
*/
async install(driverVersion, outputDirectory) {
const majorVersion = parseInt(driverVersion.split('.')[0], 10);

if (majorVersion < NEW_CHROME_DISTRIBUTION_VERSION) {
await this.installOld_(driverVersion, outputDirectory);
} else {
await this.installNew_(majorVersion, driverVersion, outputDirectory);
}
}

/**
* @param {string} driverVersion
* @param {string} outputDirectory
* @return {!Promise}
*/
async installOld_(driverVersion, outputDirectory) {
let platform;

if (os.platform() == 'linux') {
platform = 'linux64';
} else if (os.platform() == 'darwin') {
platform = 'mac64';
if (process.arch == 'arm64') {
platform = 'mac_arm64';
} else {
platform = 'mac64';
}
} else if (os.platform() == 'win32') {
platform = 'win32';
} else {
Expand All @@ -105,6 +143,73 @@ class ChromeWebDriverInstaller extends WebDriverInstallerBase {
archiveUrl, binaryName, outputName,
outputDirectory, /* isZip= */ true);
}

/**
* @param {number} majorVersion
* @param {string} driverVersion
* @param {string} outputDirectory
* @return {!Promise}
*/
async installNew_(majorVersion, driverVersion, outputDirectory) {
let platform;

if (os.platform() == 'linux') {
platform = 'linux64';
} else if (os.platform() == 'darwin') {
if (process.arch == 'arm64') {
platform = 'mac-arm64';
} else {
platform = 'mac-x64';
}
} else if (os.platform() == 'win32') {
platform = 'win64';
} else {
throw new Error(`Unrecognized platform: ${os.platform()}`);
}

let binaryName = `chromedriver-${platform}/chromedriver`;
if (os.platform() == 'win32') {
binaryName += '.exe';
}

let outputName = this.getDriverName();
if (os.platform() == 'win32') {
outputName += '.exe';
}

const data = await this.getVersionData_();
const downloads = data['milestones'][majorVersion]['downloads']['chromedriver'];

let archiveUrl;
for (const download of downloads) {
if (download['platform'] == platform) {
archiveUrl = download['url'];
break;
}
}

if (!archiveUrl) {
throw new Error(
`Unable to locate chromedriver ${majorVersion} for ${platform}!`);
}

return await InstallerUtils.installBinary(
archiveUrl, binaryName, outputName,
outputDirectory, /* isZip= */ true);
}

/**
* @return {!Object}
* @private
*/
async getVersionData_() {
if (!this.versionDataCache_) {
const response = await InstallerUtils.fetchUrl(VERSION_DATA_URL);
this.versionDataCache_ = await response.json();
}

return this.versionDataCache_;
}
}

module.exports = {ChromeWebDriverInstaller};
3 changes: 3 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 1d17e40

Please sign in to comment.