diff --git a/src/server/browserType.ts b/src/server/browserType.ts index 1fb414f8b0..1191239c92 100644 --- a/src/server/browserType.ts +++ b/src/server/browserType.ts @@ -77,18 +77,20 @@ export interface BrowserType { const mkdtempAsync = util.promisify(fs.mkdtemp); const DOWNLOADS_FOLDER = path.join(os.tmpdir(), 'playwright_downloads-'); +type WebSocketNotPipe = { webSocketRegex: RegExp, stream: 'stdout' | 'stderr' }; + export abstract class BrowserTypeBase implements BrowserType { private _name: string; private _executablePath: string | undefined; - private _webSocketRegexNotPipe: RegExp | null; + private _webSocketNotPipe: WebSocketNotPipe | null; readonly _browserPath: string; - constructor(packagePath: string, browser: browserPaths.BrowserDescriptor, webSocketRegexNotPipe: RegExp | null) { + constructor(packagePath: string, browser: browserPaths.BrowserDescriptor, webSocketOrPipe: WebSocketNotPipe | null) { this._name = browser.name; const browsersPath = browserPaths.browsersPath(packagePath); this._browserPath = browserPaths.browserDirectory(browsersPath, browser); this._executablePath = browserPaths.executablePath(this._browserPath, browser); - this._webSocketRegexNotPipe = webSocketRegexNotPipe; + this._webSocketNotPipe = webSocketOrPipe; } executablePath(): string { @@ -203,7 +205,7 @@ export abstract class BrowserTypeBase implements BrowserType { handleSIGTERM, handleSIGHUP, progress, - pipe: !this._webSocketRegexNotPipe, + pipe: !this._webSocketNotPipe, tempDirectories, attemptToGracefullyClose: async () => { if ((options as any).__testHookGracefullyClose) @@ -221,8 +223,8 @@ export abstract class BrowserTypeBase implements BrowserType { browserServer = new BrowserServer(launchedProcess, gracefullyClose, kill); progress.cleanupWhenCanceled(() => browserServer && browserServer._closeOrKill(progress.deadline)); - if (this._webSocketRegexNotPipe) { - const match = await waitForLine(progress, launchedProcess, launchedProcess.stdout, this._webSocketRegexNotPipe); + if (this._webSocketNotPipe) { + const match = await waitForLine(progress, launchedProcess, this._webSocketNotPipe.stream === 'stdout' ? launchedProcess.stdout : launchedProcess.stderr, this._webSocketNotPipe.webSocketRegex); const innerEndpoint = match[1]; transport = await WebSocketTransport.connect(progress, innerEndpoint); } else { diff --git a/src/server/chromium.ts b/src/server/chromium.ts index 4d910ae684..8dd8774124 100644 --- a/src/server/chromium.ts +++ b/src/server/chromium.ts @@ -16,7 +16,7 @@ */ import * as path from 'path'; -import { helper, assert } from '../helper'; +import { helper, assert, getFromENV, logPolitely } from '../helper'; import { CRBrowser } from '../chromium/crBrowser'; import * as ws from 'ws'; import { Env } from './processLauncher'; @@ -32,9 +32,19 @@ import { BrowserOptions } from '../browser'; export class Chromium extends BrowserTypeBase { private _devtools: CRDevTools | undefined; + private _debugPort: number | undefined; constructor(packagePath: string, browser: BrowserDescriptor) { - super(packagePath, browser, null /* use pipe not websocket */); + const debugPortStr = getFromENV('PLAYWRIGHT_CHROMIUM_DEBUG_PORT'); + const debugPort: number | undefined = debugPortStr ? +debugPortStr : undefined; + if (debugPort !== undefined) { + if (Number.isNaN(debugPort)) + throw new Error(`PLAYWRIGHT_CHROMIUM_DEBUG_PORT must be a number, but is set to "${debugPortStr}"`); + logPolitely(`NOTE: Chromium will be launched in debug mode on port ${debugPort}`); + } + + super(packagePath, browser, debugPort ? { webSocketRegex: /^DevTools listening on (ws:\/\/.*)$/, stream: 'stderr' } : null); + this._debugPort = debugPort; if (debugSupport.isDebugMode()) this._devtools = this._createDevTools(); } @@ -79,7 +89,10 @@ export class Chromium extends BrowserTypeBase { throw new Error('Arguments can not specify page to be opened'); const chromeArguments = [...DEFAULT_ARGS]; chromeArguments.push(`--user-data-dir=${userDataDir}`); - chromeArguments.push('--remote-debugging-pipe'); + if (this._debugPort !== undefined) + chromeArguments.push('--remote-debugging-port=' + this._debugPort); + else + chromeArguments.push('--remote-debugging-pipe'); if (devtools) chromeArguments.push('--auto-open-devtools-for-tabs'); if (headless) { diff --git a/src/server/firefox.ts b/src/server/firefox.ts index faf6980229..bd0f2fb823 100644 --- a/src/server/firefox.ts +++ b/src/server/firefox.ts @@ -32,8 +32,8 @@ import { BrowserDescriptor } from '../install/browserPaths'; export class Firefox extends BrowserTypeBase { constructor(packagePath: string, browser: BrowserDescriptor) { - const websocketRegex = /^Juggler listening on (ws:\/\/.*)$/; - super(packagePath, browser, websocketRegex /* use websocket not pipe */); + const webSocketRegex = /^Juggler listening on (ws:\/\/.*)$/; + super(packagePath, browser, { webSocketRegex, stream: 'stdout' }); } _connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise {