diff --git a/.npmignore b/.npmignore index bf5b117533a77..dc91417a90a4f 100644 --- a/.npmignore +++ b/.npmignore @@ -10,9 +10,6 @@ lib/injected/ !types/* !index.d.ts -# used for npm install scripts -!download-browser.js - # root for "playwright-core" package !index.js diff --git a/download-browser.js b/download-browser.js deleted file mode 100644 index 214757bbe98e9..0000000000000 --- a/download-browser.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Copyright (c) Microsoft Corporation. - * - * 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. - */ - -const path = require('path'); -const { getFromENV, logPolitely } = require('./lib/helper.js'); -const { Playwright } = require('./lib/server/playwright.js'); -const browserFetcher = require('./lib/server/browserFetcher.js'); - -function browsersPath(packagePath) { - const result = getFromENV('PLAYWRIGHT_BROWSERS_PATH'); - return result || path.join(packagePath, '.local-browsers'); -} - -function executablePath(packagePath, browser) { - return browserFetcher.executablePath(browsersPath(packagePath), browser.name, browser.revision); -} - -function targetDirectory(packagePath, browser) { - return browserFetcher.targetDirectory(browsersPath(packagePath), browser.name, browser.revision); -} - -async function downloadBrowsersWithProgressBar(packagePath, browsersJSON) { - if (getFromENV('PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD')) { - logPolitely('Skipping browsers download because `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` env variable is set'); - return false; - } - for (const browser of browsersJSON.browsers) - await downloadBrowserWithProgressBar(packagePath, browser); -} - -async function downloadBrowserWithProgressBar(packagePath, browser) { - return browserFetcher.downloadBrowserWithProgressBar({ - baseDir: browsersPath(packagePath), - browserName: browser.name, - browserRevision: browser.revision, - serverHost: getFromENV('PLAYWRIGHT_DOWNLOAD_HOST'), - }); -} - -function initializePlaywright(packagePath, browsersJSON) { - const browsers = browsersJSON.browsers; - const playwright = new Playwright({ - browsers: browsers.map(browser => browser.name), - }); - for (const browser of browsers) - playwright[browser.name]._executablePath = executablePath(packagePath, browser); - return playwright; -} - -module.exports = { - executablePath, - targetDirectory, - downloadBrowserWithProgressBar, - downloadBrowsersWithProgressBar, - initializePlaywright -}; diff --git a/index.js b/index.js index 531b582ab5961..bcc6ecaa3de48 100644 --- a/index.js +++ b/index.js @@ -14,6 +14,6 @@ * limitations under the License. */ -const { initializePlaywright } = require('./download-browser'); +const { Playwright } = require('./lib/server/playwright'); -module.exports = initializePlaywright(__dirname, require('./browsers.json')); +module.exports = new Playwright(__dirname, require('./browsers.json')['browsers']); diff --git a/install-from-github.js b/install-from-github.js index 12a1192dc6f0a..9a9e0c8c12e74 100644 --- a/install-from-github.js +++ b/install-from-github.js @@ -63,18 +63,19 @@ async function listFiles(dirpath) { } async function downloadAllBrowsersAndGenerateProtocolTypes() { - const { targetDirectory, executablePath, downloadBrowserWithProgressBar } = require('./download-browser'); + const { downloadBrowserWithProgressBar } = require('./lib/install/browserFetcher'); const protocolGenerator = require('./utils/protocol-types-generator'); + const browserPaths = require('./lib/install/browserPaths'); const browsers = require('./browsers.json')['browsers']; for (const browser of browsers) { if (await downloadBrowserWithProgressBar(__dirname, browser)) - await protocolGenerator.generateProtocol(browser.name, executablePath(__dirname, browser)).catch(console.warn); + await protocolGenerator.generateProtocol(browser.name, browserPaths.executablePath(__dirname, browser)).catch(console.warn); } // Cleanup stale revisions. const directories = new Set(await readdirAsync(path.join(__dirname, '.local-browsers'))); for (const browser of browsers) - directories.delete(targetDirectory(__dirname, browser)); + directories.delete(browserPaths.browserDirectory(__dirname, browser)); await Promise.all([...directories].map(directory => rmAsync(directory))); try { diff --git a/package.json b/package.json index 48e0347bcc0f3..b47b5f42b496d 100644 --- a/package.json +++ b/package.json @@ -76,13 +76,5 @@ "typescript": "^3.8.3", "webpack": "^4.41.0", "webpack-cli": "^3.3.9" - }, - "browser": { - "./lib/BrowserFetcher.js": false, - "ws": "./utils/browser/WebSocket", - "fs": false, - "child_process": false, - "rimraf": false, - "readline": false } } diff --git a/packages/playwright-chromium/index.js b/packages/playwright-chromium/index.js index c89987b126873..238612395c0d6 100644 --- a/packages/playwright-chromium/index.js +++ b/packages/playwright-chromium/index.js @@ -14,6 +14,6 @@ * limitations under the License. */ -const { initializePlaywright } = require('playwright-core/download-browser'); +const { Playwright } = require('playwright-core/lib/server/playwright'); -module.exports = initializePlaywright(__dirname, require('./browsers.json')); \ No newline at end of file +module.exports = new Playwright(__dirname, require('./browsers.json')['browsers']); diff --git a/packages/playwright-chromium/install.js b/packages/playwright-chromium/install.js index 5e65804376651..c0ce8cb98368a 100644 --- a/packages/playwright-chromium/install.js +++ b/packages/playwright-chromium/install.js @@ -14,6 +14,6 @@ * limitations under the License. */ -const { downloadBrowsersWithProgressBar } = require('playwright-core/download-browser'); +const { downloadBrowsersWithProgressBar } = require('playwright-core/lib/install/browserFetcher'); -downloadBrowsersWithProgressBar(__dirname, require('./browsers.json')); +downloadBrowsersWithProgressBar(__dirname, require('./browsers.json')['browsers']); diff --git a/packages/playwright-firefox/index.js b/packages/playwright-firefox/index.js index c89987b126873..238612395c0d6 100644 --- a/packages/playwright-firefox/index.js +++ b/packages/playwright-firefox/index.js @@ -14,6 +14,6 @@ * limitations under the License. */ -const { initializePlaywright } = require('playwright-core/download-browser'); +const { Playwright } = require('playwright-core/lib/server/playwright'); -module.exports = initializePlaywright(__dirname, require('./browsers.json')); \ No newline at end of file +module.exports = new Playwright(__dirname, require('./browsers.json')['browsers']); diff --git a/packages/playwright-firefox/install.js b/packages/playwright-firefox/install.js index 5e65804376651..c0ce8cb98368a 100644 --- a/packages/playwright-firefox/install.js +++ b/packages/playwright-firefox/install.js @@ -14,6 +14,6 @@ * limitations under the License. */ -const { downloadBrowsersWithProgressBar } = require('playwright-core/download-browser'); +const { downloadBrowsersWithProgressBar } = require('playwright-core/lib/install/browserFetcher'); -downloadBrowsersWithProgressBar(__dirname, require('./browsers.json')); +downloadBrowsersWithProgressBar(__dirname, require('./browsers.json')['browsers']); diff --git a/packages/playwright-webkit/index.js b/packages/playwright-webkit/index.js index 8390e61bb53b0..238612395c0d6 100644 --- a/packages/playwright-webkit/index.js +++ b/packages/playwright-webkit/index.js @@ -14,6 +14,6 @@ * limitations under the License. */ -const { initializePlaywright } = require('playwright-core/download-browser'); +const { Playwright } = require('playwright-core/lib/server/playwright'); -module.exports = initializePlaywright(__dirname, require('./browsers.json')); +module.exports = new Playwright(__dirname, require('./browsers.json')['browsers']); diff --git a/packages/playwright-webkit/install.js b/packages/playwright-webkit/install.js index 5e65804376651..c0ce8cb98368a 100644 --- a/packages/playwright-webkit/install.js +++ b/packages/playwright-webkit/install.js @@ -14,6 +14,6 @@ * limitations under the License. */ -const { downloadBrowsersWithProgressBar } = require('playwright-core/download-browser'); +const { downloadBrowsersWithProgressBar } = require('playwright-core/lib/install/browserFetcher'); -downloadBrowsersWithProgressBar(__dirname, require('./browsers.json')); +downloadBrowsersWithProgressBar(__dirname, require('./browsers.json')['browsers']); diff --git a/packages/playwright/index.js b/packages/playwright/index.js index 8390e61bb53b0..238612395c0d6 100644 --- a/packages/playwright/index.js +++ b/packages/playwright/index.js @@ -14,6 +14,6 @@ * limitations under the License. */ -const { initializePlaywright } = require('playwright-core/download-browser'); +const { Playwright } = require('playwright-core/lib/server/playwright'); -module.exports = initializePlaywright(__dirname, require('./browsers.json')); +module.exports = new Playwright(__dirname, require('./browsers.json')['browsers']); diff --git a/packages/playwright/install.js b/packages/playwright/install.js index 5e65804376651..c0ce8cb98368a 100644 --- a/packages/playwright/install.js +++ b/packages/playwright/install.js @@ -14,6 +14,6 @@ * limitations under the License. */ -const { downloadBrowsersWithProgressBar } = require('playwright-core/download-browser'); +const { downloadBrowsersWithProgressBar } = require('playwright-core/lib/install/browserFetcher'); -downloadBrowsersWithProgressBar(__dirname, require('./browsers.json')); +downloadBrowsersWithProgressBar(__dirname, require('./browsers.json')['browsers']); diff --git a/src/server/browserFetcher.ts b/src/install/browserFetcher.ts similarity index 63% rename from src/server/browserFetcher.ts rename to src/install/browserFetcher.ts index bad3b403c3e89..da9f36fcd115c 100644 --- a/src/server/browserFetcher.ts +++ b/src/install/browserFetcher.ts @@ -15,7 +15,6 @@ * limitations under the License. */ -import { execSync } from 'child_process'; import * as extract from 'extract-zip'; import * as fs from 'fs'; import * as ProxyAgent from 'https-proxy-agent'; @@ -25,37 +24,23 @@ import * as ProgressBar from 'progress'; import { getProxyForUrl } from 'proxy-from-env'; import * as URL from 'url'; import * as util from 'util'; -import { assert, logPolitely } from '../helper'; +import { assert, logPolitely, getFromENV } from '../helper'; +import * as browserPaths from './browserPaths'; +import { BrowserName, BrowserPlatform, BrowserDescriptor } from './browserPaths'; const unlinkAsync = util.promisify(fs.unlink.bind(fs)); const chmodAsync = util.promisify(fs.chmod.bind(fs)); const existsAsync = (path: string): Promise => new Promise(resolve => fs.stat(path, err => resolve(!err))); export type OnProgressCallback = (downloadedBytes: number, totalBytes: number) => void; -export type BrowserName = ('chromium'|'webkit'|'firefox'); -export type BrowserPlatform = ('win32'|'win64'|'mac10.13'|'mac10.14'|'mac10.15'|'linux'); -const DEFAULT_DOWNLOAD_HOSTS = { +const DEFAULT_DOWNLOAD_HOSTS: { [key: string]: string } = { chromium: 'https://storage.googleapis.com', firefox: 'https://playwright.azureedge.net', webkit: 'https://playwright.azureedge.net', }; -const hostPlatform = ((): BrowserPlatform => { - const platform = os.platform(); - if (platform === 'darwin') { - const macVersion = execSync('sw_vers -productVersion').toString('utf8').trim().split('.').slice(0, 2).join('.'); - return `mac${macVersion}` as BrowserPlatform; - } - if (platform === 'linux') - return 'linux'; - if (platform === 'win32') - return os.arch() === 'x64' ? 'win64' : 'win32'; - return platform as BrowserPlatform; -})(); - -function getDownloadUrl(browserName: BrowserName, platform?: BrowserPlatform): string | undefined { - platform = platform || hostPlatform; +function getDownloadUrl(browserName: BrowserName, platform: BrowserPlatform): string | undefined { if (browserName === 'chromium') { return new Map([ ['linux', '%s/chromium-browser-snapshots/Linux_x64/%d/chrome-linux.zip'], @@ -90,79 +75,31 @@ function getDownloadUrl(browserName: BrowserName, platform?: BrowserPlatform): s } } -function getRelativeExecutablePath(browserName: BrowserName): string[] | undefined { - if (browserName === 'chromium') { - return new Map([ - ['linux', ['chrome-linux', 'chrome']], - ['mac10.13', ['chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium']], - ['mac10.14', ['chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium']], - ['mac10.15', ['chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium']], - ['win32', ['chrome-win', 'chrome.exe']], - ['win64', ['chrome-win', 'chrome.exe']], - ]).get(hostPlatform); - } - - if (browserName === 'firefox') { - return new Map([ - ['linux', ['firefox', 'firefox']], - ['mac10.13', ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox']], - ['mac10.14', ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox']], - ['mac10.15', ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox']], - ['win32', ['firefox', 'firefox.exe']], - ['win64', ['firefox', 'firefox.exe']], - ]).get(hostPlatform); - } - - if (browserName === 'webkit') { - return new Map([ - ['linux', ['pw_run.sh']], - ['mac10.13', undefined], - ['mac10.14', ['pw_run.sh']], - ['mac10.15', ['pw_run.sh']], - ['win32', ['Playwright.exe']], - ['win64', ['Playwright.exe']], - ]).get(hostPlatform); - } -} - export type DownloadOptions = { - baseDir: string, - browserName: BrowserName, - browserRevision: string, + browser: BrowserDescriptor, + packagePath: string, serverHost?: string, }; -function revisionURL(options: DownloadOptions, platform?: BrowserPlatform): string { - const { - browserName, - browserRevision, - serverHost = DEFAULT_DOWNLOAD_HOSTS[browserName], - } = options; - assert(browserRevision, `'revision' must be specified`); - const urlTemplate = getDownloadUrl(browserName, platform); - assert(urlTemplate, `ERROR: Playwright does not support ${browserName} on ${hostPlatform}`); - return util.format(urlTemplate, serverHost, browserRevision); +function revisionURL(browser: BrowserDescriptor, platform = browserPaths.hostPlatform): string { + const serverHost = getFromENV('PLAYWRIGHT_DOWNLOAD_HOST') || DEFAULT_DOWNLOAD_HOSTS[browser.name]; + const urlTemplate = getDownloadUrl(browser.name, platform); + assert(urlTemplate, `ERROR: Playwright does not support ${browser.name} on ${platform}`); + return util.format(urlTemplate, serverHost, browser.revision); } -export function targetDirectory(baseDir: string, browserName: string, browserRevision: string): string { - return path.join(baseDir, `${browserName}-${browserRevision}`); -} - -export function executablePath(baseDir: string, browserName: BrowserName, browserRevision: string): string { - const relativePath = getRelativeExecutablePath(browserName); - assert(relativePath, `Unsupported platform for ${browserName}: ${hostPlatform}`); - return path.join(targetDirectory(baseDir, browserName, browserRevision), ...relativePath); +export async function downloadBrowsersWithProgressBar(packagePath: string, browsers: BrowserDescriptor[]) { + if (getFromENV('PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD')) { + logPolitely('Skipping browsers download because `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` env variable is set'); + return false; + } + for (const browser of browsers) + await downloadBrowserWithProgressBar(packagePath, browser); } -export async function downloadBrowserWithProgressBar(options: DownloadOptions): Promise { - const { - baseDir, - browserName, - browserRevision, - } = options; - const progressBarName = `${browserName} v${browserRevision}`; - assert(baseDir, '`baseDir` must be provided'); - const targetDir = targetDirectory(baseDir, browserName, browserRevision); +export async function downloadBrowserWithProgressBar(packagePath: string, browser: BrowserDescriptor): Promise { + const progressBarName = `${browser.name} v${browser.revision}`; + const targetDir = browserPaths.browserDirectory(packagePath, browser); if (await existsAsync(targetDir)) { // Already downloaded. return false; @@ -185,12 +122,12 @@ export async function downloadBrowserWithProgressBar(options: DownloadOptions): progressBar.tick(delta); } - const url = revisionURL(options); - const zipPath = path.join(os.tmpdir(), `playwright-download-${browserName}-${hostPlatform}-${browserRevision}.zip`); + const url = revisionURL(browser); + const zipPath = path.join(os.tmpdir(), `playwright-download-${browser.name}-${browserPaths.hostPlatform}-${browser.revision}.zip`); try { await downloadFile(url, zipPath, progress); await extract(zipPath, {dir: targetDir}); - await chmodAsync(executablePath(baseDir, browserName, browserRevision), 0o755); + await chmodAsync(browserPaths.executablePath(packagePath, browser), 0o755); } catch (e) { process.exitCode = 1; throw e; @@ -208,11 +145,7 @@ function toMegabytes(bytes: number) { } export async function canDownload(browserName: BrowserName, browserRevision: string, platform: BrowserPlatform): Promise { - const url = revisionURL({ - baseDir: '', - browserName, - browserRevision - }, platform); + const url = revisionURL({ name: browserName, revision: browserRevision }, platform); let resolve: (result: boolean) => void = () => {}; const promise = new Promise(x => resolve = x); const request = httpRequest(url, 'HEAD', response => { diff --git a/src/install/browserPaths.ts b/src/install/browserPaths.ts new file mode 100644 index 0000000000000..d72eb7aa02a0e --- /dev/null +++ b/src/install/browserPaths.ts @@ -0,0 +1,91 @@ +/** + * Copyright 2017 Google Inc. All rights reserved. + * Modifications copyright (c) Microsoft Corporation. + * + * 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 { execSync } from 'child_process'; +import * as os from 'os'; +import * as path from 'path'; +import { assert, getFromENV } from '../helper'; + +export type BrowserName = 'chromium'|'webkit'|'firefox'; +export type BrowserPlatform = 'win32'|'win64'|'mac10.13'|'mac10.14'|'mac10.15'|'linux'; +export type BrowserDescriptor = { + name: BrowserName, + revision: string +}; + +export const hostPlatform = ((): BrowserPlatform => { + const platform = os.platform(); + if (platform === 'darwin') { + const macVersion = execSync('sw_vers -productVersion').toString('utf8').trim().split('.').slice(0, 2).join('.'); + return `mac${macVersion}` as BrowserPlatform; + } + if (platform === 'linux') + return 'linux'; + if (platform === 'win32') + return os.arch() === 'x64' ? 'win64' : 'win32'; + return platform as BrowserPlatform; +})(); + +function getRelativeExecutablePath(browserName: BrowserName): string[] | undefined { + if (browserName === 'chromium') { + return new Map([ + ['linux', ['chrome-linux', 'chrome']], + ['mac10.13', ['chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium']], + ['mac10.14', ['chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium']], + ['mac10.15', ['chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium']], + ['win32', ['chrome-win', 'chrome.exe']], + ['win64', ['chrome-win', 'chrome.exe']], + ]).get(hostPlatform); + } + + if (browserName === 'firefox') { + return new Map([ + ['linux', ['firefox', 'firefox']], + ['mac10.13', ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox']], + ['mac10.14', ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox']], + ['mac10.15', ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox']], + ['win32', ['firefox', 'firefox.exe']], + ['win64', ['firefox', 'firefox.exe']], + ]).get(hostPlatform); + } + + if (browserName === 'webkit') { + return new Map([ + ['linux', ['pw_run.sh']], + ['mac10.13', undefined], + ['mac10.14', ['pw_run.sh']], + ['mac10.15', ['pw_run.sh']], + ['win32', ['Playwright.exe']], + ['win64', ['Playwright.exe']], + ]).get(hostPlatform); + } +} + +function browsersPath(packagePath: string): string { + const result = getFromENV('PLAYWRIGHT_BROWSERS_PATH'); + return result || path.join(packagePath, '.local-browsers'); +} + +export function browserDirectory(packagePath: string, browser: BrowserDescriptor): string { + return path.join(browsersPath(packagePath), `${browser.name}-${browser.revision}`); +} + +export function executablePath(packagePath: string, browser: BrowserDescriptor): string { + const relativePath = getRelativeExecutablePath(browser.name); + assert(relativePath, `Unsupported platform for ${browser.name}: ${hostPlatform}`); + return path.join(browserDirectory(packagePath, browser), ...relativePath); +} diff --git a/src/server/browserType.ts b/src/server/browserType.ts index 68ff93e5d2b4b..dd88db91ea59e 100644 --- a/src/server/browserType.ts +++ b/src/server/browserType.ts @@ -16,6 +16,7 @@ import { BrowserContext } from '../browserContext'; import { BrowserServer } from './browserServer'; +import * as browserPaths from '../install/browserPaths'; import { Logger } from '../logger'; export type BrowserArgOptions = { @@ -50,3 +51,26 @@ export interface BrowserType { launchPersistentContext(userDataDir: string, options?: LaunchOptions): Promise; connect(options: ConnectOptions): Promise; } + +export abstract class AbstractBrowserType implements BrowserType { + private _name: string; + private _executablePath: string; + + constructor(packagePath: string, browser: browserPaths.BrowserDescriptor) { + this._name = browser.name; + this._executablePath = browserPaths.executablePath(packagePath, browser); + } + + executablePath(): string { + return this._executablePath; + } + + name(): string { + return this._name; + } + + abstract launch(options?: LaunchOptions): Promise; + abstract launchServer(options?: LaunchServerOptions): Promise; + abstract launchPersistentContext(userDataDir: string, options?: LaunchOptions): Promise; + abstract connect(options: ConnectOptions): Promise; +} diff --git a/src/server/chromium.ts b/src/server/chromium.ts index 88d8762ca0740..6c79eabb1cd41 100644 --- a/src/server/chromium.ts +++ b/src/server/chromium.ts @@ -25,25 +25,18 @@ import * as ws from 'ws'; import { launchProcess } from './processLauncher'; import { kBrowserCloseMessageId } from '../chromium/crConnection'; import { PipeTransport } from './pipeTransport'; -import { LaunchOptions, BrowserArgOptions, BrowserType, ConnectOptions, LaunchServerOptions } from './browserType'; +import { LaunchOptions, BrowserArgOptions, ConnectOptions, LaunchServerOptions, AbstractBrowserType } from './browserType'; import { LaunchType } from '../browser'; import { BrowserServer, WebSocketWrapper } from './browserServer'; import { Events } from '../events'; import { ConnectionTransport, ProtocolRequest, WebSocketTransport } from '../transport'; import { BrowserContext } from '../browserContext'; import { InnerLogger, logError, RootLogger } from '../logger'; +import { BrowserDescriptor } from '../install/browserPaths'; -export class Chromium implements BrowserType { - private _executablePath: (string|undefined); - - executablePath(): string { - if (!this._executablePath) - throw new Error('No executable path!'); - return this._executablePath; - } - - name() { - return 'chromium'; +export class Chromium extends AbstractBrowserType { + constructor(packagePath: string, browser: BrowserDescriptor) { + super(packagePath, browser); } async launch(options: LaunchOptions = {}): Promise { @@ -95,7 +88,7 @@ export class Chromium implements BrowserType { else chromeArguments.push(...args); - const chromeExecutable = executablePath || this._executablePath; + const chromeExecutable = executablePath || this.executablePath(); if (!chromeExecutable) throw new Error(`No executable path is specified. Pass "executablePath" option directly.`); const { launchedProcess, gracefullyClose, downloadsPath } = await launchProcess({ diff --git a/src/server/firefox.ts b/src/server/firefox.ts index 168d6671b4200..81d8021f67779 100644 --- a/src/server/firefox.ts +++ b/src/server/firefox.ts @@ -28,24 +28,17 @@ import { FFBrowser } from '../firefox/ffBrowser'; import { kBrowserCloseMessageId } from '../firefox/ffConnection'; import { helper, assert } from '../helper'; import { BrowserServer, WebSocketWrapper } from './browserServer'; -import { BrowserArgOptions, BrowserType, LaunchOptions, LaunchServerOptions, ConnectOptions } from './browserType'; +import { BrowserArgOptions, LaunchOptions, LaunchServerOptions, ConnectOptions, AbstractBrowserType } from './browserType'; import { launchProcess, waitForLine } from './processLauncher'; import { ConnectionTransport, SequenceNumberMixer, WebSocketTransport } from '../transport'; import { RootLogger, InnerLogger, logError } from '../logger'; +import { BrowserDescriptor } from '../install/browserPaths'; const mkdtempAsync = util.promisify(fs.mkdtemp); -export class Firefox implements BrowserType { - private _executablePath: (string|undefined); - - executablePath(): string { - if (!this._executablePath) - throw new Error('No executable path!'); - return this._executablePath; - } - - name() { - return 'firefox'; +export class Firefox extends AbstractBrowserType { + constructor(packagePath: string, browser: BrowserDescriptor) { + super(packagePath, browser); } async launch(options: LaunchOptions = {}): Promise { @@ -109,7 +102,7 @@ export class Firefox implements BrowserType { else firefoxArguments.push(...args); - const firefoxExecutable = executablePath || this._executablePath; + const firefoxExecutable = executablePath || this.executablePath(); if (!firefoxExecutable) throw new Error(`No executable path is specified. Pass "executablePath" option directly.`); diff --git a/src/server/playwright.ts b/src/server/playwright.ts index bfdd4863138cf..9f506bf3951c5 100644 --- a/src/server/playwright.ts +++ b/src/server/playwright.ts @@ -23,16 +23,13 @@ import { Chromium } from './chromium'; import { WebKit } from './webkit'; import { Firefox } from './firefox'; import { selectors } from '../selectors'; +import * as browserPaths from '../install/browserPaths'; for (const className in api) { if (typeof (api as any)[className] === 'function') helper.installApiHooks(className[0].toLowerCase() + className.substring(1), (api as any)[className]); } -type PlaywrightOptions = { - browsers: Array<('firefox'|'webkit'|'chromium')>, -}; - export class Playwright { readonly selectors = selectors; readonly devices: types.Devices; @@ -41,17 +38,20 @@ export class Playwright { readonly firefox: (Firefox|undefined); readonly webkit: (WebKit|undefined); - constructor(options: PlaywrightOptions) { - const { - browsers, - } = options; + constructor(packagePath: string, browsers: browserPaths.BrowserDescriptor[]) { this.devices = DeviceDescriptors; this.errors = { TimeoutError }; - if (browsers.includes('chromium')) - this.chromium = new Chromium(); - if (browsers.includes('webkit')) - this.webkit = new WebKit(); - if (browsers.includes('firefox')) - this.firefox = new Firefox(); + + const chromium = browsers.find(browser => browser.name === 'chromium'); + if (chromium) + this.chromium = new Chromium(packagePath, chromium); + + const firefox = browsers.find(browser => browser.name === 'firefox'); + if (firefox) + this.firefox = new Firefox(packagePath, firefox); + + const webkit = browsers.find(browser => browser.name === 'webkit'); + if (webkit) + this.webkit = new WebKit(packagePath, webkit); } } diff --git a/src/server/webkit.ts b/src/server/webkit.ts index 52bc48f714e7e..84d92e52559be 100644 --- a/src/server/webkit.ts +++ b/src/server/webkit.ts @@ -24,7 +24,7 @@ import * as os from 'os'; import * as util from 'util'; import { helper, assert } from '../helper'; import { kBrowserCloseMessageId } from '../webkit/wkConnection'; -import { LaunchOptions, BrowserArgOptions, BrowserType, LaunchServerOptions, ConnectOptions } from './browserType'; +import { LaunchOptions, BrowserArgOptions, LaunchServerOptions, ConnectOptions, AbstractBrowserType } from './browserType'; import { ConnectionTransport, SequenceNumberMixer, WebSocketTransport } from '../transport'; import * as ws from 'ws'; import { LaunchType } from '../browser'; @@ -32,18 +32,11 @@ import { BrowserServer, WebSocketWrapper } from './browserServer'; import { Events } from '../events'; import { BrowserContext } from '../browserContext'; import { InnerLogger, logError, RootLogger } from '../logger'; +import { BrowserDescriptor } from '../install/browserPaths'; -export class WebKit implements BrowserType { - private _executablePath: (string|undefined); - - executablePath(): string { - if (!this._executablePath) - throw new Error('No executable path!'); - return this._executablePath; - } - - name() { - return 'webkit'; +export class WebKit extends AbstractBrowserType { + constructor(packagePath: string, browser: BrowserDescriptor) { + super(packagePath, browser); } async launch(options: LaunchOptions = {}): Promise { @@ -99,7 +92,7 @@ export class WebKit implements BrowserType { else webkitArguments.push(...args); - const webkitExecutable = executablePath || this._executablePath; + const webkitExecutable = executablePath || this.executablePath(); if (!webkitExecutable) throw new Error(`No executable path is specified.`); diff --git a/utils/check_availability.js b/utils/check_availability.js index 685b05a4b622a..92fc66d1d2b63 100755 --- a/utils/check_availability.js +++ b/utils/check_availability.js @@ -16,7 +16,7 @@ */ const assert = require('assert'); -const browserFetcher = require('../lib/server/browserFetcher.js'); +const browserFetcher = require('../lib/install/browserFetcher.js'); const https = require('https'); const SUPPORTER_PLATFORMS = ['linux', 'mac', 'win32', 'win64'];