chore: exec path for browsers (#9658)

This commit is contained in:
Alex Rudenko 2023-02-13 16:10:54 +01:00 committed by GitHub
parent 78a302174e
commit 5c54d399bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 296 additions and 43 deletions

View File

@ -23,4 +23,9 @@ export const downloadUrls = {
[Browser.FIREFOX]: firefox.resolveDownloadUrl,
};
export const executablePathByBrowser = {
[Browser.CHROME]: chrome.executablePath,
[Browser.FIREFOX]: firefox.executablePath,
};
export {Browser, BrowserPlatform};

View File

@ -15,6 +15,7 @@
*/
import {BrowserPlatform} from './types.js';
import path from 'path';
function archive(platform: BrowserPlatform, revision: string): string {
switch (platform) {
@ -55,3 +56,27 @@ export function resolveDownloadUrl(
revision
)}.zip`;
}
export function executablePath(
platform: BrowserPlatform,
revision: string,
basePath = ''
): string {
const browserPath = path.join(basePath, `${platform}-${revision}`);
switch (platform) {
case BrowserPlatform.MAC:
case BrowserPlatform.MAC_ARM:
return path.join(
browserPath,
'Chromium.app',
'Contents',
'MacOS',
'Chromium'
);
case BrowserPlatform.LINUX:
return path.join(browserPath, 'chrome');
case BrowserPlatform.WIN32:
case BrowserPlatform.WIN64:
return path.join(browserPath, 'chrome.exe');
}
}

View File

@ -15,6 +15,7 @@
*/
import {BrowserPlatform} from './types.js';
import path from 'path';
function archive(platform: BrowserPlatform, revision: string): string {
switch (platform) {
@ -24,7 +25,6 @@ function archive(platform: BrowserPlatform, revision: string): string {
case BrowserPlatform.MAC:
return `firefox-${revision}.en-US.mac.dmg`;
case BrowserPlatform.WIN32:
return `firefox-${revision}.en-US.${platform}.zip`;
case BrowserPlatform.WIN64:
return `firefox-${revision}.en-US.${platform}.zip`;
}
@ -37,3 +37,27 @@ export function resolveDownloadUrl(
): string {
return `${baseUrl}/${archive(platform, revision)}`;
}
export function executablePath(
platform: BrowserPlatform,
revision: string,
basePath = ''
): string {
const browserPath = path.join(basePath, `${platform}-${revision}`);
switch (platform) {
case BrowserPlatform.MAC_ARM:
case BrowserPlatform.MAC:
return path.join(
browserPath,
'Firefox Nightly.app',
'Contents',
'MacOS',
'firefox'
);
case BrowserPlatform.LINUX:
return path.join(browserPath, 'firefox', 'firefox');
case BrowserPlatform.WIN32:
case BrowserPlatform.WIN64:
return path.join(browserPath, 'firefox', 'firefox.exe');
}
}

View File

@ -0,0 +1,57 @@
/**
* Copyright 2023 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import os from 'os';
import {BrowserPlatform} from './browsers/browsers.js';
export function detectPlatform(): BrowserPlatform | undefined {
const platform = os.platform();
switch (platform) {
case 'darwin':
return os.arch() === 'arm64'
? BrowserPlatform.MAC_ARM
: BrowserPlatform.MAC;
case 'linux':
return BrowserPlatform.LINUX;
case 'win32':
return os.arch() === 'x64' ||
// Windows 11 for ARM supports x64 emulation
(os.arch() === 'arm64' && isWindows11(os.release()))
? BrowserPlatform.WIN64
: BrowserPlatform.WIN32;
default:
return undefined;
}
}
/**
* Windows 11 is identified by the version 10.0.22000 or greater
* @internal
*/
function isWindows11(version: string): boolean {
const parts = version.split('.');
if (parts.length > 2) {
const major = parseInt(parts[0] as string, 10);
const minor = parseInt(parts[1] as string, 10);
const patch = parseInt(parts[2] as string, 10);
return (
major > 10 ||
(major === 10 && minor > 0) ||
(major === 10 && minor === 0 && patch >= 22000)
);
}
return false;
}

View File

@ -24,6 +24,7 @@ import {Browser, BrowserPlatform, downloadUrls} from './browsers/browsers.js';
import {downloadFile, headHttpRequest} from './httpUtil.js';
import assert from 'assert';
import {unpackArchive} from './fileUtil.js';
import {detectPlatform} from './detectPlatform.js';
const debugFetch = debug('puppeteer:browsers:fetcher');
@ -123,45 +124,6 @@ export async function canFetch(options: Options): Promise<boolean> {
);
}
/**
* Windows 11 is identified by the version 10.0.22000 or greater
* @internal
*/
function isWindows11(version: string): boolean {
const parts = version.split('.');
if (parts.length > 2) {
const major = parseInt(parts[0] as string, 10);
const minor = parseInt(parts[1] as string, 10);
const patch = parseInt(parts[2] as string, 10);
return (
major > 10 ||
(major === 10 && minor > 0) ||
(major === 10 && minor === 0 && patch >= 22000)
);
}
return false;
}
function detectPlatform(): BrowserPlatform | undefined {
const platform = os.platform();
switch (platform) {
case 'darwin':
return os.arch() === 'arm64'
? BrowserPlatform.MAC_ARM
: BrowserPlatform.MAC;
case 'linux':
return BrowserPlatform.LINUX;
case 'win32':
return os.arch() === 'x64' ||
// Windows 11 for ARM supports x64 emulation
(os.arch() === 'arm64' && isWindows11(os.release()))
? BrowserPlatform.WIN64
: BrowserPlatform.WIN32;
default:
return undefined;
}
}
function getDownloadUrl(
browser: Browser,
platform: BrowserPlatform,

View File

@ -0,0 +1,62 @@
/**
* Copyright 2023 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
Browser,
BrowserPlatform,
executablePathByBrowser,
} from './browsers/browsers.js';
import {detectPlatform} from './detectPlatform.js';
import os from 'os';
/**
* @public
*/
export interface Options {
/**
* Root path to the storage directory.
*/
path: string;
/**
* Determines which platform the browser will be suited for.
*
* @defaultValue Auto-detected.
*/
platform?: BrowserPlatform;
/**
* Determines which browser to fetch.
*/
browser: Browser;
/**
* Determines which revision to dowloand. Revision should uniquely identify
* binaries and they are used for caching.
*/
revision: string;
}
export function computeExecutablePath(options: Options): string {
options.platform ??= detectPlatform();
if (!options.platform) {
throw new Error(
`Cannot download a binary for the provided platform: ${os.platform()} (${os.arch()})`
);
}
return executablePathByBrowser[options.browser](
options.platform,
options.revision,
options.path
);
}

View File

@ -14,9 +14,13 @@
* limitations under the License.
*/
import {resolveDownloadUrl} from '../../lib/cjs/browsers/chrome.js';
import {
resolveDownloadUrl,
executablePath,
} from '../../lib/cjs/browsers/chrome.js';
import {BrowserPlatform} from '../../lib/cjs/browsers/browsers.js';
import assert from 'assert';
import path from 'path';
describe('Chrome', () => {
it('should resolve download URLs', () => {
@ -41,4 +45,33 @@ describe('Chrome', () => {
'https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/1083080/chrome-win.zip'
);
});
it('should resolve executable paths', () => {
assert.strictEqual(
executablePath(BrowserPlatform.LINUX, '12372323'),
path.join('linux-12372323', 'chrome')
);
assert.strictEqual(
executablePath(BrowserPlatform.MAC, '12372323'),
path.join('mac-12372323', 'Chromium.app', 'Contents', 'MacOS', 'Chromium')
);
assert.strictEqual(
executablePath(BrowserPlatform.MAC_ARM, '12372323'),
path.join(
'mac_arm-12372323',
'Chromium.app',
'Contents',
'MacOS',
'Chromium'
)
);
assert.strictEqual(
executablePath(BrowserPlatform.WIN32, '12372323'),
path.join('win32-12372323', 'chrome.exe')
);
assert.strictEqual(
executablePath(BrowserPlatform.WIN64, '12372323'),
path.join('win64-12372323', 'chrome.exe')
);
});
});

View File

@ -110,7 +110,7 @@ describe('fetch', () => {
(os.platform() === 'darwin' ? it : it.skip)(
'should download a revision that is a dmg archive',
async function () {
this.timeout(60000);
this.timeout(120000);
const expectedOutputPath = path.join(
tmpDir,
`${BrowserPlatform.MAC}-${testFirefoxRevision}`

View File

@ -14,9 +14,13 @@
* limitations under the License.
*/
import {resolveDownloadUrl} from '../../lib/cjs/browsers/firefox.js';
import {
executablePath,
resolveDownloadUrl,
} from '../../lib/cjs/browsers/firefox.js';
import {BrowserPlatform} from '../../lib/cjs/browsers/browsers.js';
import assert from 'assert';
import path from 'path';
describe('Firefox', () => {
it('should resolve download URLs', () => {
@ -41,4 +45,39 @@ describe('Firefox', () => {
'https://archive.mozilla.org/pub/firefox/nightly/latest-mozilla-central/firefox-111.0a1.en-US.win64.zip'
);
});
it('should resolve executable paths', () => {
assert.strictEqual(
executablePath(BrowserPlatform.LINUX, '111.0a1'),
path.join('linux-111.0a1', 'firefox', 'firefox')
);
assert.strictEqual(
executablePath(BrowserPlatform.MAC, '111.0a1'),
path.join(
'mac-111.0a1',
'Firefox Nightly.app',
'Contents',
'MacOS',
'firefox'
)
);
assert.strictEqual(
executablePath(BrowserPlatform.MAC_ARM, '111.0a1'),
path.join(
'mac_arm-111.0a1',
'Firefox Nightly.app',
'Contents',
'MacOS',
'firefox'
)
);
assert.strictEqual(
executablePath(BrowserPlatform.WIN32, '111.0a1'),
path.join('win32-111.0a1', 'firefox', 'firefox.exe')
);
assert.strictEqual(
executablePath(BrowserPlatform.WIN64, '111.0a1'),
path.join('win64-111.0a1', 'firefox', 'firefox.exe')
);
});
});

View File

@ -0,0 +1,46 @@
/**
* Copyright 2023 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {computeExecutablePath} from '../../lib/cjs/launcher.js';
import {Browser, BrowserPlatform} from '../../lib/cjs/browsers/browsers.js';
import assert from 'assert';
import path from 'path';
describe('launcher', () => {
it('should compute executable path for Chrome', () => {
assert.strictEqual(
computeExecutablePath({
browser: Browser.CHROME,
platform: BrowserPlatform.LINUX,
revision: '123',
path: 'cache',
}),
path.join('cache', 'linux-123', 'chrome')
);
});
it('should compute executable path for Firefox', () => {
assert.strictEqual(
computeExecutablePath({
browser: Browser.FIREFOX,
platform: BrowserPlatform.LINUX,
revision: '123',
path: 'cache',
}),
path.join('cache', 'linux-123', 'firefox', 'firefox')
);
});
});