chore: simplify Registry api (#7451)
This commit is contained in:
parent
9897fc5b60
commit
65606c093a
|
|
@ -31,7 +31,7 @@ import { Page } from '../client/page';
|
||||||
import { BrowserType } from '../client/browserType';
|
import { BrowserType } from '../client/browserType';
|
||||||
import { BrowserContextOptions, LaunchOptions } from '../client/types';
|
import { BrowserContextOptions, LaunchOptions } from '../client/types';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import { allBrowserNames, BrowserName, Registry } from '../utils/registry';
|
import { allBrowserNames, BrowserName, registry } from '../utils/registry';
|
||||||
import * as utils from '../utils/utils';
|
import * as utils from '../utils/utils';
|
||||||
|
|
||||||
const SCRIPTS_DIRECTORY = path.join(__dirname, '..', '..', 'bin');
|
const SCRIPTS_DIRECTORY = path.join(__dirname, '..', '..', 'bin');
|
||||||
|
|
@ -126,7 +126,7 @@ program
|
||||||
try {
|
try {
|
||||||
// Install default browsers when invoked without arguments.
|
// Install default browsers when invoked without arguments.
|
||||||
if (!args.length) {
|
if (!args.length) {
|
||||||
await Registry.currentPackageRegistry().installBinaries();
|
await registry.installBinaries();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const browserNames: Set<BrowserName> = new Set(args.filter((browser: any) => allBrowserNames.has(browser)));
|
const browserNames: Set<BrowserName> = new Set(args.filter((browser: any) => allBrowserNames.has(browser)));
|
||||||
|
|
@ -139,7 +139,7 @@ program
|
||||||
if (browserNames.has('chromium') || browserChannels.has('chrome-beta') || browserChannels.has('chrome') || browserChannels.has('msedge') || browserChannels.has('msedge-beta'))
|
if (browserNames.has('chromium') || browserChannels.has('chrome-beta') || browserChannels.has('chrome') || browserChannels.has('msedge') || browserChannels.has('msedge-beta'))
|
||||||
browserNames.add('ffmpeg');
|
browserNames.add('ffmpeg');
|
||||||
if (browserNames.size)
|
if (browserNames.size)
|
||||||
await Registry.currentPackageRegistry().installBinaries([...browserNames]);
|
await registry.installBinaries([...browserNames]);
|
||||||
for (const browserChannel of browserChannels)
|
for (const browserChannel of browserChannels)
|
||||||
await installBrowserChannel(browserChannel);
|
await installBrowserChannel(browserChannel);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -191,7 +191,7 @@ program
|
||||||
.action(async function(browserTypes) {
|
.action(async function(browserTypes) {
|
||||||
try {
|
try {
|
||||||
// TODO: verify the list and print supported browserTypes in the error message.
|
// TODO: verify the list and print supported browserTypes in the error message.
|
||||||
await Registry.currentPackageRegistry().installDeps(browserTypes);
|
await registry.installDeps(browserTypes);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(`Failed to install browser dependencies\n${e}`);
|
console.log(`Failed to install browser dependencies\n${e}`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ import { Download } from './download';
|
||||||
import { ProxySettings } from './types';
|
import { ProxySettings } from './types';
|
||||||
import { ChildProcess } from 'child_process';
|
import { ChildProcess } from 'child_process';
|
||||||
import { RecentLogsCollector } from '../utils/debugLogger';
|
import { RecentLogsCollector } from '../utils/debugLogger';
|
||||||
import * as registry from '../utils/registry';
|
|
||||||
import { SdkObject } from './instrumentation';
|
import { SdkObject } from './instrumentation';
|
||||||
import { Artifact } from './artifact';
|
import { Artifact } from './artifact';
|
||||||
import { Selectors } from './selectors';
|
import { Selectors } from './selectors';
|
||||||
|
|
@ -34,7 +33,6 @@ export interface BrowserProcess {
|
||||||
}
|
}
|
||||||
|
|
||||||
export type PlaywrightOptions = {
|
export type PlaywrightOptions = {
|
||||||
registry: registry.Registry,
|
|
||||||
rootSdkObject: SdkObject,
|
rootSdkObject: SdkObject,
|
||||||
selectors: Selectors,
|
selectors: Selectors,
|
||||||
loopbackProxyOverride?: () => string,
|
loopbackProxyOverride?: () => string,
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ import fs from 'fs';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { BrowserContext, normalizeProxySettings, validateBrowserContextOptions } from './browserContext';
|
import { BrowserContext, normalizeProxySettings, validateBrowserContextOptions } from './browserContext';
|
||||||
import * as registry from '../utils/registry';
|
import { registry, BrowserName } from '../utils/registry';
|
||||||
import { ConnectionTransport, WebSocketTransport } from './transport';
|
import { ConnectionTransport, WebSocketTransport } from './transport';
|
||||||
import { BrowserOptions, Browser, BrowserProcess, PlaywrightOptions } from './browser';
|
import { BrowserOptions, Browser, BrowserProcess, PlaywrightOptions } from './browser';
|
||||||
import { launchProcess, Env, envArrayToObject } from '../utils/processLauncher';
|
import { launchProcess, Env, envArrayToObject } from '../utils/processLauncher';
|
||||||
|
|
@ -34,20 +34,18 @@ import { CallMetadata, SdkObject } from './instrumentation';
|
||||||
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
|
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
|
||||||
|
|
||||||
export abstract class BrowserType extends SdkObject {
|
export abstract class BrowserType extends SdkObject {
|
||||||
private _name: registry.BrowserName;
|
private _name: BrowserName;
|
||||||
readonly _registry: registry.Registry;
|
|
||||||
readonly _playwrightOptions: PlaywrightOptions;
|
readonly _playwrightOptions: PlaywrightOptions;
|
||||||
|
|
||||||
constructor(browserName: registry.BrowserName, playwrightOptions: PlaywrightOptions) {
|
constructor(browserName: BrowserName, playwrightOptions: PlaywrightOptions) {
|
||||||
super(playwrightOptions.rootSdkObject, 'browser-type');
|
super(playwrightOptions.rootSdkObject, 'browser-type');
|
||||||
this.attribution.browserType = this;
|
this.attribution.browserType = this;
|
||||||
this._playwrightOptions = playwrightOptions;
|
this._playwrightOptions = playwrightOptions;
|
||||||
this._name = browserName;
|
this._name = browserName;
|
||||||
this._registry = playwrightOptions.registry;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
executablePath(channel?: string): string {
|
executablePath(channel?: string): string {
|
||||||
return this._registry.executablePath(this._name) || '';
|
return registry.executablePath(this._name) || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
name(): string {
|
name(): string {
|
||||||
|
|
@ -170,9 +168,9 @@ export abstract class BrowserType extends SdkObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only validate dependencies for downloadable browsers.
|
// Only validate dependencies for downloadable browsers.
|
||||||
const browserName: registry.BrowserName = (options.channel || this._name) as registry.BrowserName;
|
const browserName: BrowserName = (options.channel || this._name) as BrowserName;
|
||||||
if (!executablePath && this._registry.isSupportedBrowser(browserName))
|
if (!executablePath && registry.isSupportedBrowser(browserName))
|
||||||
await this._registry.validateHostRequirements(browserName);
|
await registry.validateHostRequirements(browserName);
|
||||||
|
|
||||||
let wsEndpointCallback: ((wsEndpoint: string) => void) | undefined;
|
let wsEndpointCallback: ((wsEndpoint: string) => void) | undefined;
|
||||||
const shouldWaitForWSListening = options.useWebSocket || options.args?.some(a => a.startsWith('--remote-debugging-port'));
|
const shouldWaitForWSListening = options.useWebSocket || options.args?.some(a => a.startsWith('--remote-debugging-port'));
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ import { helper } from '../helper';
|
||||||
import { CallMetadata } from '../instrumentation';
|
import { CallMetadata } from '../instrumentation';
|
||||||
import { findChromiumChannel } from './findChromiumChannel';
|
import { findChromiumChannel } from './findChromiumChannel';
|
||||||
import http from 'http';
|
import http from 'http';
|
||||||
|
import { registry } from '../../utils/registry';
|
||||||
|
|
||||||
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
|
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
|
||||||
|
|
||||||
|
|
@ -52,7 +53,7 @@ export class Chromium extends BrowserType {
|
||||||
if (channel) {
|
if (channel) {
|
||||||
let executablePath = undefined;
|
let executablePath = undefined;
|
||||||
if ((channel as any) === 'chromium-with-symbols')
|
if ((channel as any) === 'chromium-with-symbols')
|
||||||
executablePath = this._registry.executablePath('chromium-with-symbols');
|
executablePath = registry.executablePath('chromium-with-symbols');
|
||||||
else
|
else
|
||||||
executablePath = findChromiumChannel(channel);
|
executablePath = findChromiumChannel(channel);
|
||||||
assert(executablePath, `unsupported chromium channel "${channel}"`);
|
assert(executablePath, `unsupported chromium channel "${channel}"`);
|
||||||
|
|
@ -102,7 +103,7 @@ export class Chromium extends BrowserType {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _createDevTools() {
|
private _createDevTools() {
|
||||||
return new CRDevTools(path.join(this._registry.browserDirectory('chromium'), 'devtools-preferences.json'));
|
return new CRDevTools(path.join(registry.browserDirectory('chromium'), 'devtools-preferences.json'));
|
||||||
}
|
}
|
||||||
|
|
||||||
async _connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<CRBrowser> {
|
async _connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<CRBrowser> {
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import { assert, headersArrayToObject, createGuid, canAccessFile } from '../../u
|
||||||
import { VideoRecorder } from './videoRecorder';
|
import { VideoRecorder } from './videoRecorder';
|
||||||
import { Progress } from '../progress';
|
import { Progress } from '../progress';
|
||||||
import { DragManager } from './crDragDrop';
|
import { DragManager } from './crDragDrop';
|
||||||
|
import { registry } from '../../utils/registry';
|
||||||
|
|
||||||
|
|
||||||
const UTILITY_WORLD_NAME = '__playwright_utility_world__';
|
const UTILITY_WORLD_NAME = '__playwright_utility_world__';
|
||||||
|
|
@ -844,7 +845,7 @@ class FrameSession {
|
||||||
|
|
||||||
async _createVideoRecorder(screencastId: string, options: types.PageScreencastOptions): Promise<void> {
|
async _createVideoRecorder(screencastId: string, options: types.PageScreencastOptions): Promise<void> {
|
||||||
assert(!this._screencastId);
|
assert(!this._screencastId);
|
||||||
const ffmpegPath = this._crPage._browserContext._browser.options.registry.executablePath('ffmpeg');
|
const ffmpegPath = registry.executablePath('ffmpeg');
|
||||||
if (!ffmpegPath)
|
if (!ffmpegPath)
|
||||||
throw new Error('ffmpeg executable was not found');
|
throw new Error('ffmpeg executable was not found');
|
||||||
if (!canAccessFile(ffmpegPath)) {
|
if (!canAccessFile(ffmpegPath)) {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import { Env } from '../../utils/processLauncher';
|
||||||
import { ConnectionTransport } from '../transport';
|
import { ConnectionTransport } from '../transport';
|
||||||
import { BrowserOptions, PlaywrightOptions } from '../browser';
|
import { BrowserOptions, PlaywrightOptions } from '../browser';
|
||||||
import * as types from '../types';
|
import * as types from '../types';
|
||||||
|
import { registry } from '../../utils/registry';
|
||||||
|
|
||||||
export class Firefox extends BrowserType {
|
export class Firefox extends BrowserType {
|
||||||
constructor(playwrightOptions: PlaywrightOptions) {
|
constructor(playwrightOptions: PlaywrightOptions) {
|
||||||
|
|
@ -36,7 +37,7 @@ export class Firefox extends BrowserType {
|
||||||
if (channel) {
|
if (channel) {
|
||||||
let executablePath = undefined;
|
let executablePath = undefined;
|
||||||
if ((channel as any) === 'firefox-beta')
|
if ((channel as any) === 'firefox-beta')
|
||||||
executablePath = this._registry.executablePath('firefox-beta');
|
executablePath = registry.executablePath('firefox-beta');
|
||||||
assert(executablePath, `unsupported firefox channel "${channel}"`);
|
assert(executablePath, `unsupported firefox channel "${channel}"`);
|
||||||
assert(fs.existsSync(executablePath), `"${channel}" channel is not installed. Try running 'npx playwright install ${channel}'`);
|
assert(fs.existsSync(executablePath), `"${channel}" channel is not installed. Try running 'npx playwright install ${channel}'`);
|
||||||
return executablePath;
|
return executablePath;
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import path from 'path';
|
|
||||||
import { Android } from './android/android';
|
import { Android } from './android/android';
|
||||||
import { AdbBackend } from './android/backendAdb';
|
import { AdbBackend } from './android/backendAdb';
|
||||||
import { PlaywrightOptions } from './browser';
|
import { PlaywrightOptions } from './browser';
|
||||||
|
|
@ -23,7 +22,6 @@ import { Electron } from './electron/electron';
|
||||||
import { Firefox } from './firefox/firefox';
|
import { Firefox } from './firefox/firefox';
|
||||||
import { Selectors } from './selectors';
|
import { Selectors } from './selectors';
|
||||||
import { WebKit } from './webkit/webkit';
|
import { WebKit } from './webkit/webkit';
|
||||||
import { Registry } from '../utils/registry';
|
|
||||||
import { CallMetadata, createInstrumentation, SdkObject } from './instrumentation';
|
import { CallMetadata, createInstrumentation, SdkObject } from './instrumentation';
|
||||||
import { debugLogger } from '../utils/debugLogger';
|
import { debugLogger } from '../utils/debugLogger';
|
||||||
import { PortForwardingServer } from './socksSocket';
|
import { PortForwardingServer } from './socksSocket';
|
||||||
|
|
@ -48,7 +46,6 @@ export class Playwright extends SdkObject {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.options = {
|
this.options = {
|
||||||
registry: new Registry(path.join(__dirname, '..', '..')),
|
|
||||||
rootSdkObject: this,
|
rootSdkObject: this,
|
||||||
selectors: new Selectors(),
|
selectors: new Selectors(),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import { canAccessFile, isUnderTest } from '../../../utils/utils';
|
||||||
import { internalCallMetadata } from '../../instrumentation';
|
import { internalCallMetadata } from '../../instrumentation';
|
||||||
import { ProgressController } from '../../progress';
|
import { ProgressController } from '../../progress';
|
||||||
import { BrowserContext } from '../../browserContext';
|
import { BrowserContext } from '../../browserContext';
|
||||||
import { Registry } from '../../../utils/registry';
|
import { registry } from '../../../utils/registry';
|
||||||
import { findChromiumChannel } from '../../chromium/findChromiumChannel';
|
import { findChromiumChannel } from '../../chromium/findChromiumChannel';
|
||||||
import { installAppIcon } from '../../chromium/crApp';
|
import { installAppIcon } from '../../chromium/crApp';
|
||||||
|
|
||||||
|
|
@ -140,7 +140,6 @@ export class TraceViewer {
|
||||||
// Null means no installation and no channels found.
|
// Null means no installation and no channels found.
|
||||||
let channel = null;
|
let channel = null;
|
||||||
if (traceViewerBrowser === 'chromium') {
|
if (traceViewerBrowser === 'chromium') {
|
||||||
const registry = Registry.currentPackageRegistry();
|
|
||||||
if (canAccessFile(registry.executablePath('chromium')!)) {
|
if (canAccessFile(registry.executablePath('chromium')!)) {
|
||||||
// This means we have a browser downloaded.
|
// This means we have a browser downloaded.
|
||||||
channel = undefined;
|
channel = undefined;
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,7 @@ import * as jpeg from 'jpeg-js';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import * as png from 'pngjs';
|
import * as png from 'pngjs';
|
||||||
import { splitErrorMessage } from '../../utils/stackTrace';
|
import { splitErrorMessage } from '../../utils/stackTrace';
|
||||||
import { hostPlatform } from '../../utils/registry';
|
import { assert, createGuid, debugAssert, headersArrayToObject, headersObjectToArray, hostPlatform } from '../../utils/utils';
|
||||||
import { assert, createGuid, debugAssert, headersArrayToObject, headersObjectToArray } from '../../utils/utils';
|
|
||||||
import * as accessibility from '../accessibility';
|
import * as accessibility from '../accessibility';
|
||||||
import * as dialog from '../dialog';
|
import * as dialog from '../dialog';
|
||||||
import * as dom from '../dom';
|
import * as dom from '../dom';
|
||||||
|
|
@ -769,14 +768,13 @@ export class WKPage implements PageDelegate {
|
||||||
|
|
||||||
private _toolbarHeight(): number {
|
private _toolbarHeight(): number {
|
||||||
if (this._page._browserContext._browser?.options.headful)
|
if (this._page._browserContext._browser?.options.headful)
|
||||||
return hostPlatform.startsWith('10.15') ? 55 : 59;
|
return hostPlatform === 'mac10.15' ? 55 : 59;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _startVideo(options: types.PageScreencastOptions): Promise<void> {
|
private async _startVideo(options: types.PageScreencastOptions): Promise<void> {
|
||||||
assert(!this._recordingVideoFile);
|
assert(!this._recordingVideoFile);
|
||||||
const START_VIDEO_PROTOCOL_COMMAND = hostPlatform === 'mac10.14' ? 'Screencast.start' : 'Screencast.startVideo';
|
const { screencastId } = await this._pageProxySession.send('Screencast.startVideo', {
|
||||||
const { screencastId } = await this._pageProxySession.send(START_VIDEO_PROTOCOL_COMMAND as any, {
|
|
||||||
file: options.outputFile,
|
file: options.outputFile,
|
||||||
width: options.width,
|
width: options.width,
|
||||||
height: options.height,
|
height: options.height,
|
||||||
|
|
@ -789,8 +787,7 @@ export class WKPage implements PageDelegate {
|
||||||
private async _stopVideo(): Promise<void> {
|
private async _stopVideo(): Promise<void> {
|
||||||
if (!this._recordingVideoFile)
|
if (!this._recordingVideoFile)
|
||||||
return;
|
return;
|
||||||
const STOP_VIDEO_PROTOCOL_COMMAND = hostPlatform === 'mac10.14' ? 'Screencast.stop' : 'Screencast.stopVideo';
|
await this._pageProxySession.sendMayFail('Screencast.stopVideo');
|
||||||
await this._pageProxySession.sendMayFail(STOP_VIDEO_PROTOCOL_COMMAND as any);
|
|
||||||
this._recordingVideoFile = null;
|
this._recordingVideoFile = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ export async function downloadBrowserWithProgressBar(title: string, browserDirec
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = downloadURL;
|
const url = downloadURL;
|
||||||
const zipPath = path.join(os.tmpdir(), `${downloadFileName}.zip`);
|
const zipPath = path.join(os.tmpdir(), downloadFileName);
|
||||||
try {
|
try {
|
||||||
for (let attempt = 1, N = 3; attempt <= N; ++attempt) {
|
for (let attempt = 1, N = 3; attempt <= N; ++attempt) {
|
||||||
debugLogger.log('install', `downloading ${progressBarName} - attempt #${attempt}`);
|
debugLogger.log('install', `downloading ${progressBarName} - attempt #${attempt}`);
|
||||||
|
|
|
||||||
|
|
@ -20,8 +20,8 @@ import path from 'path';
|
||||||
import * as util from 'util';
|
import * as util from 'util';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import lockfile from 'proper-lockfile';
|
import lockfile from 'proper-lockfile';
|
||||||
import { getUbuntuVersion, getUbuntuVersionSync } from './ubuntuVersion';
|
import { getUbuntuVersion } from './ubuntuVersion';
|
||||||
import { assert, getFromENV, getAsBooleanFromENV, calculateSha1, removeFolders, existsAsync } from './utils';
|
import { assert, getFromENV, getAsBooleanFromENV, calculateSha1, removeFolders, existsAsync, hostPlatform } from './utils';
|
||||||
import { installDependenciesLinux, installDependenciesWindows, validateDependenciesLinux, validateDependenciesWindows } from './dependencies';
|
import { installDependenciesLinux, installDependenciesWindows, validateDependenciesLinux, validateDependenciesWindows } from './dependencies';
|
||||||
import { downloadBrowserWithProgressBar, logPolitely } from './browserFetcher';
|
import { downloadBrowserWithProgressBar, logPolitely } from './browserFetcher';
|
||||||
|
|
||||||
|
|
@ -30,14 +30,6 @@ export const allBrowserNames: Set<BrowserName> = new Set(['chromium', 'chromium-
|
||||||
|
|
||||||
const PACKAGE_PATH = path.join(__dirname, '..', '..');
|
const PACKAGE_PATH = path.join(__dirname, '..', '..');
|
||||||
|
|
||||||
type BrowserPlatform = 'win32'|'win64'|'mac10.13'|'mac10.14'|'mac10.15'|'mac11'|'mac11-arm64'|'ubuntu18.04'|'ubuntu20.04';
|
|
||||||
type BrowserDescriptor = {
|
|
||||||
name: BrowserName,
|
|
||||||
revision: string,
|
|
||||||
installByDefault: boolean,
|
|
||||||
browserDirectory: string,
|
|
||||||
};
|
|
||||||
|
|
||||||
const EXECUTABLE_PATHS = {
|
const EXECUTABLE_PATHS = {
|
||||||
'chromium': {
|
'chromium': {
|
||||||
'ubuntu18.04': ['chrome-linux', 'chrome'],
|
'ubuntu18.04': ['chrome-linux', 'chrome'],
|
||||||
|
|
@ -176,41 +168,7 @@ const DOWNLOAD_URLS = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const hostPlatform = ((): BrowserPlatform => {
|
const registryDirectory = (() => {
|
||||||
const platform = os.platform();
|
|
||||||
if (platform === 'darwin') {
|
|
||||||
const ver = os.release().split('.').map((a: string) => parseInt(a, 10));
|
|
||||||
let macVersion = '';
|
|
||||||
if (ver[0] < 18) {
|
|
||||||
// Everything before 10.14 is considered 10.13.
|
|
||||||
macVersion = 'mac10.13';
|
|
||||||
} else if (ver[0] === 18) {
|
|
||||||
macVersion = 'mac10.14';
|
|
||||||
} else if (ver[0] === 19) {
|
|
||||||
macVersion = 'mac10.15';
|
|
||||||
} else {
|
|
||||||
// ver[0] >= 20
|
|
||||||
const LAST_STABLE_MAC_MAJOR_VERSION = 11;
|
|
||||||
// Best-effort support for MacOS beta versions.
|
|
||||||
macVersion = 'mac' + Math.min(ver[0] - 9, LAST_STABLE_MAC_MAJOR_VERSION);
|
|
||||||
// BigSur is the first version that might run on Apple Silicon.
|
|
||||||
if (os.cpus().some(cpu => cpu.model.includes('Apple')))
|
|
||||||
macVersion += '-arm64';
|
|
||||||
}
|
|
||||||
return macVersion as BrowserPlatform;
|
|
||||||
}
|
|
||||||
if (platform === 'linux') {
|
|
||||||
const ubuntuVersion = getUbuntuVersionSync();
|
|
||||||
if (parseInt(ubuntuVersion, 10) <= 19)
|
|
||||||
return 'ubuntu18.04';
|
|
||||||
return 'ubuntu20.04';
|
|
||||||
}
|
|
||||||
if (platform === 'win32')
|
|
||||||
return os.arch() === 'x64' ? 'win64' : 'win32';
|
|
||||||
return platform as BrowserPlatform;
|
|
||||||
})();
|
|
||||||
|
|
||||||
export const registryDirectory = (() => {
|
|
||||||
let result: string;
|
let result: string;
|
||||||
|
|
||||||
const envDefined = getFromENV('PLAYWRIGHT_BROWSERS_PATH');
|
const envDefined = getFromENV('PLAYWRIGHT_BROWSERS_PATH');
|
||||||
|
|
@ -242,7 +200,7 @@ export const registryDirectory = (() => {
|
||||||
return result;
|
return result;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
export function isBrowserDirectory(browserDirectory: string): boolean {
|
function isBrowserDirectory(browserDirectory: string): boolean {
|
||||||
const baseName = path.basename(browserDirectory);
|
const baseName = path.basename(browserDirectory);
|
||||||
for (const browserName of allBrowserNames) {
|
for (const browserName of allBrowserNames) {
|
||||||
if (baseName.startsWith(browserName + '-'))
|
if (baseName.startsWith(browserName + '-'))
|
||||||
|
|
@ -251,38 +209,40 @@ export function isBrowserDirectory(browserDirectory: string): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let currentPackageRegistry: Registry | undefined = undefined;
|
type BrowserDescriptor = {
|
||||||
|
name: BrowserName,
|
||||||
|
revision: string,
|
||||||
|
installByDefault: boolean,
|
||||||
|
browserDirectory: string,
|
||||||
|
};
|
||||||
|
|
||||||
|
function readDescriptors(packagePath: string) {
|
||||||
|
const browsersJSON = require(path.join(packagePath, 'browsers.json'));
|
||||||
|
return (browsersJSON['browsers'] as any[]).map(obj => {
|
||||||
|
const name = obj.name;
|
||||||
|
const revisionOverride = (obj.revisionOverrides || {})[hostPlatform];
|
||||||
|
const revision = revisionOverride || obj.revision;
|
||||||
|
const browserDirectoryPrefix = revisionOverride ? `${name}_${hostPlatform}_special` : `${name}`;
|
||||||
|
const descriptor: BrowserDescriptor = {
|
||||||
|
name,
|
||||||
|
revision,
|
||||||
|
installByDefault: !!obj.installByDefault,
|
||||||
|
// Method `isBrowserDirectory` determines directory to be browser iff
|
||||||
|
// it starts with some browser name followed by '-'. Some browser names
|
||||||
|
// are prefixes of others, e.g. 'webkit' is a prefix of `webkit-technology-preview`.
|
||||||
|
// To avoid older registries erroneously removing 'webkit-technology-preview', we have to
|
||||||
|
// ensure that browser folders to never include dashes inside.
|
||||||
|
browserDirectory: browserDirectoryPrefix.replace(/-/g, '_') + '-' + revision,
|
||||||
|
};
|
||||||
|
return descriptor;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export class Registry {
|
export class Registry {
|
||||||
private _descriptors: BrowserDescriptor[];
|
private _descriptors: BrowserDescriptor[];
|
||||||
|
|
||||||
static currentPackageRegistry() {
|
|
||||||
if (!currentPackageRegistry)
|
|
||||||
currentPackageRegistry = new Registry(PACKAGE_PATH);
|
|
||||||
return currentPackageRegistry;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(packagePath: string) {
|
constructor(packagePath: string) {
|
||||||
// require() needs to be used there otherwise it breaks on Vercel serverless
|
this._descriptors = readDescriptors(packagePath);
|
||||||
// functions. See https://github.com/microsoft/playwright/pull/6186
|
|
||||||
const browsersJSON = require(path.join(packagePath, 'browsers.json'));
|
|
||||||
this._descriptors = browsersJSON['browsers'].map((obj: any) => {
|
|
||||||
const name = obj.name;
|
|
||||||
const revisionOverride = (obj.revisionOverrides || {})[hostPlatform];
|
|
||||||
const revision = revisionOverride || obj.revision;
|
|
||||||
const browserDirectoryPrefix = revisionOverride ? `${name}_${hostPlatform}_special` : `${name}`;
|
|
||||||
return {
|
|
||||||
name,
|
|
||||||
revision,
|
|
||||||
installByDefault: !!obj.installByDefault,
|
|
||||||
// Method `isBrowserDirectory` determines directory to be browser iff
|
|
||||||
// it starts with some browser name followed by '-'. Some browser names
|
|
||||||
// are prefixes of others, e.g. 'webkit' is a prefix of `webkit-technology-preview`.
|
|
||||||
// To avoid older registries erroneously removing 'webkit-technology-preview', we have to
|
|
||||||
// ensure that browser folders to never include dashes inside.
|
|
||||||
browserDirectory: browserDirectoryPrefix.replace(/-/g, '_') + '-' + revision,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
browserDirectory(browserName: BrowserName): string {
|
browserDirectory(browserName: BrowserName): string {
|
||||||
|
|
@ -291,10 +251,10 @@ export class Registry {
|
||||||
return path.join(registryDirectory, browser.browserDirectory);
|
return path.join(registryDirectory, browser.browserDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
private _revision(browserName: BrowserName): number {
|
private _revision(browserName: BrowserName): string {
|
||||||
const browser = this._descriptors.find(browser => browser.name === browserName);
|
const browser = this._descriptors.find(browser => browser.name === browserName);
|
||||||
assert(browser, `ERROR: Playwright does not support ${browserName}`);
|
assert(browser, `ERROR: Playwright does not support ${browserName}`);
|
||||||
return parseInt(browser.revision, 10);
|
return browser.revision;
|
||||||
}
|
}
|
||||||
|
|
||||||
executablePath(browserName: BrowserName): string | undefined {
|
executablePath(browserName: BrowserName): string | undefined {
|
||||||
|
|
@ -430,7 +390,7 @@ export class Registry {
|
||||||
const revision = this._revision(browserName);
|
const revision = this._revision(browserName);
|
||||||
const browserDirectory = this.browserDirectory(browserName);
|
const browserDirectory = this.browserDirectory(browserName);
|
||||||
const title = `${browserName} v${revision}`;
|
const title = `${browserName} v${revision}`;
|
||||||
const downloadFileName = `playwright-download-${browserName}-${hostPlatform}-${revision}`;
|
const downloadFileName = `playwright-download-${browserName}-${hostPlatform}-${revision}.zip`;
|
||||||
await downloadBrowserWithProgressBar(title, browserDirectory, this.executablePath(browserName)!, this._downloadURL(browserName), downloadFileName).catch(e => {
|
await downloadBrowserWithProgressBar(title, browserDirectory, this.executablePath(browserName)!, this._downloadURL(browserName), downloadFileName).catch(e => {
|
||||||
throw new Error(`Failed to download ${title}, caused by\n${e.stack}`);
|
throw new Error(`Failed to download ${title}, caused by\n${e.stack}`);
|
||||||
});
|
});
|
||||||
|
|
@ -449,12 +409,13 @@ export class Registry {
|
||||||
let linkTarget = '';
|
let linkTarget = '';
|
||||||
try {
|
try {
|
||||||
linkTarget = (await fs.promises.readFile(linkPath)).toString();
|
linkTarget = (await fs.promises.readFile(linkPath)).toString();
|
||||||
const linkRegistry = new Registry(linkTarget);
|
const descriptors = readDescriptors(linkTarget);
|
||||||
for (const browserName of allBrowserNames) {
|
for (const browserName of allBrowserNames) {
|
||||||
if (!linkRegistry.isSupportedBrowser(browserName))
|
const descriptor = descriptors.find(d => d.name === browserName);
|
||||||
|
if (!descriptor)
|
||||||
continue;
|
continue;
|
||||||
const usedBrowserPath = linkRegistry.browserDirectory(browserName);
|
const usedBrowserPath = path.join(registryDirectory, descriptor.browserDirectory);
|
||||||
const browserRevision = linkRegistry._revision(browserName);
|
const browserRevision = parseInt(descriptor.revision, 10);
|
||||||
// Old browser installations don't have marker file.
|
// Old browser installations don't have marker file.
|
||||||
const shouldHaveMarkerFile = (browserName === 'chromium' && browserRevision >= 786218) ||
|
const shouldHaveMarkerFile = (browserName === 'chromium' && browserRevision >= 786218) ||
|
||||||
(browserName === 'firefox' && browserRevision >= 1128) ||
|
(browserName === 'firefox' && browserRevision >= 1128) ||
|
||||||
|
|
@ -493,5 +454,7 @@ export async function installDefaultBrowsersForNpmInstall() {
|
||||||
logPolitely('Skipping browsers download because `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` env variable is set');
|
logPolitely('Skipping browsers download because `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` env variable is set');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
await Registry.currentPackageRegistry().installBinaries();
|
await registry.installBinaries();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const registry = new Registry(PACKAGE_PATH);
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import os from 'os';
|
||||||
import { spawn } from 'child_process';
|
import { spawn } from 'child_process';
|
||||||
import { getProxyForUrl } from 'proxy-from-env';
|
import { getProxyForUrl } from 'proxy-from-env';
|
||||||
import * as URL from 'url';
|
import * as URL from 'url';
|
||||||
|
import { getUbuntuVersionSync } from './ubuntuVersion';
|
||||||
|
|
||||||
// `https-proxy-agent` v5 is written in TypeScript and exposes generated types.
|
// `https-proxy-agent` v5 is written in TypeScript and exposes generated types.
|
||||||
// However, as of June 2020, its types are generated with tsconfig that enables
|
// However, as of June 2020, its types are generated with tsconfig that enables
|
||||||
|
|
@ -321,3 +322,38 @@ export function constructURLBasedOnBaseURL(baseURL: string | undefined, givenURL
|
||||||
return givenURL;
|
return givenURL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type HostPlatform = 'win32'|'win64'|'mac10.13'|'mac10.14'|'mac10.15'|'mac11'|'mac11-arm64'|'ubuntu18.04'|'ubuntu20.04';
|
||||||
|
export const hostPlatform = ((): HostPlatform => {
|
||||||
|
const platform = os.platform();
|
||||||
|
if (platform === 'darwin') {
|
||||||
|
const ver = os.release().split('.').map((a: string) => parseInt(a, 10));
|
||||||
|
let macVersion = '';
|
||||||
|
if (ver[0] < 18) {
|
||||||
|
// Everything before 10.14 is considered 10.13.
|
||||||
|
macVersion = 'mac10.13';
|
||||||
|
} else if (ver[0] === 18) {
|
||||||
|
macVersion = 'mac10.14';
|
||||||
|
} else if (ver[0] === 19) {
|
||||||
|
macVersion = 'mac10.15';
|
||||||
|
} else {
|
||||||
|
// ver[0] >= 20
|
||||||
|
const LAST_STABLE_MAC_MAJOR_VERSION = 11;
|
||||||
|
// Best-effort support for MacOS beta versions.
|
||||||
|
macVersion = 'mac' + Math.min(ver[0] - 9, LAST_STABLE_MAC_MAJOR_VERSION);
|
||||||
|
// BigSur is the first version that might run on Apple Silicon.
|
||||||
|
if (os.cpus().some(cpu => cpu.model.includes('Apple')))
|
||||||
|
macVersion += '-arm64';
|
||||||
|
}
|
||||||
|
return macVersion as HostPlatform;
|
||||||
|
}
|
||||||
|
if (platform === 'linux') {
|
||||||
|
const ubuntuVersion = getUbuntuVersionSync();
|
||||||
|
if (parseInt(ubuntuVersion, 10) <= 19)
|
||||||
|
return 'ubuntu18.04';
|
||||||
|
return 'ubuntu20.04';
|
||||||
|
}
|
||||||
|
if (platform === 'win32')
|
||||||
|
return os.arch() === 'x64' ? 'win64' : 'win32';
|
||||||
|
return platform as HostPlatform;
|
||||||
|
})();
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,8 @@ import { test, expect, stripAscii } from './playwright-test-fixtures';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { spawnSync } from 'child_process';
|
import { spawnSync } from 'child_process';
|
||||||
import { Registry } from '../../src/utils/registry';
|
import { registry } from '../../src/utils/registry';
|
||||||
|
|
||||||
const registry = new Registry(path.join(__dirname, '..', '..'));
|
|
||||||
const ffmpeg = registry.executablePath('ffmpeg') || '';
|
const ffmpeg = registry.executablePath('ffmpeg') || '';
|
||||||
|
|
||||||
export class VideoPlayer {
|
export class VideoPlayer {
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,8 @@ import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { spawnSync } from 'child_process';
|
import { spawnSync } from 'child_process';
|
||||||
import { PNG } from 'pngjs';
|
import { PNG } from 'pngjs';
|
||||||
import { Registry } from '../src/utils/registry';
|
import { registry } from '../src/utils/registry';
|
||||||
|
|
||||||
const registry = new Registry(path.join(__dirname, '..'));
|
|
||||||
const ffmpeg = registry.executablePath('ffmpeg') || '';
|
const ffmpeg = registry.executablePath('ffmpeg') || '';
|
||||||
|
|
||||||
export class VideoPlayer {
|
export class VideoPlayer {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue