diff --git a/src/server/supplements/recorder/recorderApp.ts b/src/server/supplements/recorder/recorderApp.ts index a290bc51c9..f59f2b2372 100644 --- a/src/server/supplements/recorder/recorderApp.ts +++ b/src/server/supplements/recorder/recorderApp.ts @@ -21,10 +21,10 @@ import { ProgressController } from '../../progress'; import { EventEmitter } from 'events'; import { internalCallMetadata } from '../../instrumentation'; import type { CallLog, EventData, Mode, Source } from './recorderTypes'; -import { BrowserContext } from '../../browserContext'; import { isUnderTest } from '../../../utils/utils'; import * as mime from 'mime'; import { installAppIcon } from '../../chromium/crApp'; +import { findChromiumChannel } from '../../../utils/registry'; declare global { interface Window { @@ -85,7 +85,7 @@ export class RecorderApp extends EventEmitter { await mainFrame.goto(internalCallMetadata(), 'https://playwright/index.html'); } - static async open(inspectedContext: BrowserContext): Promise { + static async open(sdkLanguage: string): Promise { const recorderPlaywright = (require('../../playwright').createPlaywright as typeof import('../../playwright').createPlaywright)('javascript', true); const args = [ '--app=data:text/html,', @@ -94,19 +94,11 @@ export class RecorderApp extends EventEmitter { ]; if (process.env.PWTEST_RECORDER_PORT) args.push(`--remote-debugging-port=${process.env.PWTEST_RECORDER_PORT}`); - let channel: string | undefined; - let executablePath: string | undefined; - if (inspectedContext._browser.options.isChromium) { - channel = inspectedContext._browser.options.channel; - if (!channel) - executablePath = inspectedContext._browser.options.customExecutablePath; - } const context = await recorderPlaywright.chromium.launchPersistentContext(internalCallMetadata(), '', { - channel, - executablePath, + channel: findChromiumChannel(sdkLanguage), args, noDefaultViewport: true, - headless: !!process.env.PWTEST_CLI_HEADLESS || (isUnderTest() && !inspectedContext._browser.options.headful), + headless: !!process.env.PWTEST_CLI_HEADLESS || (isUnderTest() && !process.env.HEADFUL), useWebSocket: !!process.env.PWTEST_RECORDER_PORT }); const controller = new ProgressController(internalCallMetadata(), context._browser); diff --git a/src/server/supplements/recorderSupplement.ts b/src/server/supplements/recorderSupplement.ts index 07138f4b08..e0695cd9eb 100644 --- a/src/server/supplements/recorderSupplement.ts +++ b/src/server/supplements/recorderSupplement.ts @@ -76,7 +76,7 @@ export class RecorderSupplement implements InstrumentationListener { } async install() { - const recorderApp = await RecorderApp.open(this._context); + const recorderApp = await RecorderApp.open(this._context._browser.options.sdkLanguage); this._recorderApp = recorderApp; recorderApp.once('close', () => { this._debugger.resume(false); diff --git a/src/server/trace/viewer/traceViewer.ts b/src/server/trace/viewer/traceViewer.ts index be44bd8694..03457ec524 100644 --- a/src/server/trace/viewer/traceViewer.ts +++ b/src/server/trace/viewer/traceViewer.ts @@ -29,7 +29,7 @@ import { isUnderTest, download } from '../../../utils/utils'; import { internalCallMetadata } from '../../instrumentation'; import { ProgressController } from '../../progress'; import { BrowserContext } from '../../browserContext'; -import { registry } from '../../../utils/registry'; +import { findChromiumChannel } from '../../../utils/registry'; import { installAppIcon } from '../../chromium/crApp'; import { debugLogger } from '../../../utils/debugLogger'; @@ -134,32 +134,9 @@ export class TraceViewer { if (isUnderTest()) args.push(`--remote-debugging-port=0`); - // For Chromium, fall back to the stable channels of popular vendors for work out of the box. - // Null means no installation and no channels found. - let channel = null; - if (traceViewerBrowser === 'chromium') { - for (const name of ['chromium', 'chrome', 'msedge']) { - try { - registry.findExecutable(name)!.executablePathOrDie(traceViewerPlaywright.options.sdkLanguage); - channel = name === 'chromium' ? undefined : name; - break; - } catch (e) { - } - } - - if (channel === null) { - // TODO: language-specific error message, or fallback to default error. - throw new Error(` -================================================================== -Please run 'npx playwright install' to install Playwright browsers -================================================================== -`); - } - } - const context = await traceViewerPlaywright[traceViewerBrowser as 'chromium'].launchPersistentContext(internalCallMetadata(), '', { // TODO: store language in the trace. - channel: channel as any, + channel: findChromiumChannel(traceViewerPlaywright.options.sdkLanguage), args, noDefaultViewport: true, headless, diff --git a/src/utils/registry.ts b/src/utils/registry.ts index cd8f83a928..3efc2a58a3 100644 --- a/src/utils/registry.ts +++ b/src/utils/registry.ts @@ -726,4 +726,32 @@ export async function installBrowsersForNpmInstall(browsers: string[]) { await registry.install(executables); } +export function findChromiumChannel(sdkLanguage: string): string | undefined { + // Fall back to the stable channels of popular vendors to work out of the box. + // Null means no installation and no channels found. + let channel = null; + for (const name of ['chromium', 'chrome', 'msedge']) { + try { + registry.findExecutable(name)!.executablePathOrDie(sdkLanguage); + channel = name === 'chromium' ? undefined : name; + break; + } catch (e) { + } + } + + if (channel === null) { + const installCommand = buildPlaywrightCLICommand(sdkLanguage, `install chromium`); + const prettyMessage = [ + `No chromium-based browser found on the system.`, + `Please run the following command to download one:`, + ``, + ` ${installCommand}`, + ``, + `<3 Playwright Team`, + ].join('\n'); + throw new Error('\n' + wrapInASCIIBox(prettyMessage, 1)); + } + return channel; +} + export const registry = new Registry(require('../../browsers.json'));