diff --git a/packages/playwright-core/src/server/DEPS.list b/packages/playwright-core/src/server/DEPS.list index bc32bb8486..cfeb255af6 100644 --- a/packages/playwright-core/src/server/DEPS.list +++ b/packages/playwright-core/src/server/DEPS.list @@ -13,6 +13,7 @@ ./recorder/ ./registry/ ./trace/recorder/tracing.ts +./chromium/crApp.ts [playwright.ts] ./android/ diff --git a/packages/playwright-core/src/server/browserType.ts b/packages/playwright-core/src/server/browserType.ts index dedba5df0a..672b5a80f7 100644 --- a/packages/playwright-core/src/server/browserType.ts +++ b/packages/playwright-core/src/server/browserType.ts @@ -20,7 +20,7 @@ import path from 'path'; import type { BrowserContext } from './browserContext'; import { normalizeProxySettings, validateBrowserContextOptions } from './browserContext'; import type { BrowserName } from './registry'; -import { registry } from './registry'; +import { findChromiumChannel, registry } from './registry'; import type { ConnectionTransport } from './transport'; import { WebSocketTransport } from './transport'; import type { BrowserOptions, Browser, BrowserProcess } from './browser'; @@ -37,8 +37,9 @@ import { existsAsync } from '../utils/fileUtils'; import { helper } from './helper'; import { RecentLogsCollector } from '../common/debugLogger'; import type { CallMetadata } from './instrumentation'; -import { SdkObject } from './instrumentation'; +import { SdkObject, serverSideCallMetadata } from './instrumentation'; import { ManualPromise } from '../utils/manualPromise'; +import { installAppIcon } from './chromium/crApp'; export const kNoXServerRunningError = 'Looks like you launched a headed browser without having a XServer running.\n' + 'Set either \'headless: true\' or use \'xvfb-run \' before running Playwright.\n\n<3 Playwright Team'; @@ -84,6 +85,37 @@ export abstract class BrowserType extends SdkObject { return browser._defaultContext!; } + async launchApp(options: { + sdkLanguage: string, + windowSize: types.Size, + windowPosition?: types.Point, + persistentContextOptions?: Parameters[2]; + }) { + const args = [...options.persistentContextOptions?.args ?? []]; + + if (this._name === 'chromium') { + args.push( + '--app=data:text/html,', + `--window-size=${options.windowSize.width},${options.windowSize.height}`, + ...(options.windowPosition ? [`--window-position=${options.windowPosition.x},${options.windowPosition.y}`] : []), + '--test-type=', + ); + } + + const context = await this.launchPersistentContext(serverSideCallMetadata(), '', { + channel: findChromiumChannel(options.sdkLanguage), + noDefaultViewport: true, + ignoreDefaultArgs: ['--enable-automation'], + colorScheme: 'no-override', + ...options?.persistentContextOptions, + args, + }); + const [page] = context.pages(); + if (this._name === 'chromium') + await installAppIcon(page); + return { context, page }; + } + async _innerLaunchWithRetries(progress: Progress, options: types.LaunchOptions, persistent: channels.BrowserNewContextParams | undefined, protocolLogger: types.ProtocolLogger, userDataDir?: string): Promise { try { return await this._innerLaunch(progress, options, persistent, protocolLogger, userDataDir); diff --git a/packages/playwright-core/src/server/recorder/recorderApp.ts b/packages/playwright-core/src/server/recorder/recorderApp.ts index eb09c5c1c1..a435898f26 100644 --- a/packages/playwright-core/src/server/recorder/recorderApp.ts +++ b/packages/playwright-core/src/server/recorder/recorderApp.ts @@ -23,8 +23,7 @@ import { serverSideCallMetadata } from '../instrumentation'; import type { CallLog, EventData, Mode, Source } from '@recorder/recorderTypes'; import { isUnderTest } from '../../utils'; import { mime } from '../../utilsBundle'; -import { installAppIcon, syncLocalStorageWithSettings } from '../chromium/crApp'; -import { findChromiumChannel } from '../registry'; +import { syncLocalStorageWithSettings } from '../chromium/crApp'; import type { Recorder } from '../recorder'; import type { BrowserContext } from '../browserContext'; @@ -79,7 +78,6 @@ export class RecorderApp extends EventEmitter implements IRecorderApp { } private async _init() { - await installAppIcon(this._page); await syncLocalStorageWithSettings(this._page, 'recorder'); await this._page._setServerRequestInterceptor(route => { @@ -117,30 +115,23 @@ export class RecorderApp extends EventEmitter implements IRecorderApp { const sdkLanguage = inspectedContext.attribution.playwright.options.sdkLanguage; const headed = !!inspectedContext._browser.options.headful; const recorderPlaywright = (require('../playwright').createPlaywright as typeof import('../playwright').createPlaywright)({ sdkLanguage: 'javascript', isInternalPlaywright: true }); - const args = [ - '--app=data:text/html,', - '--window-size=600,600', - '--window-position=1020,10', - '--test-type=', - ]; - if (process.env.PWTEST_RECORDER_PORT) - args.push(`--remote-debugging-port=${process.env.PWTEST_RECORDER_PORT}`); - const context = await recorderPlaywright.chromium.launchPersistentContext(serverSideCallMetadata(), '', { - channel: findChromiumChannel(sdkLanguage), - args, - noDefaultViewport: true, - ignoreDefaultArgs: ['--enable-automation'], - colorScheme: 'no-override', - headless: !!process.env.PWTEST_CLI_HEADLESS || (isUnderTest() && !headed), - useWebSocket: !!process.env.PWTEST_RECORDER_PORT, - handleSIGINT, + const { context, page } = await recorderPlaywright.chromium.launchApp({ + sdkLanguage, + windowSize: { width: 600, height: 600 }, + windowPosition: { x: 1020, y: 10 }, + persistentContextOptions: { + noDefaultViewport: true, + headless: !!process.env.PWTEST_CLI_HEADLESS || (isUnderTest() && !headed), + useWebSocket: !!process.env.PWTEST_RECORDER_PORT, + handleSIGINT, + args: process.env.PWTEST_RECORDER_PORT ? [`--remote-debugging-port=${process.env.PWTEST_RECORDER_PORT}`] : [], + } }); const controller = new ProgressController(serverSideCallMetadata(), context._browser); await controller.run(async progress => { await context._browser._defaultContext!._loadDefaultContextAsIs(progress); }); - const [page] = context.pages(); const result = new RecorderApp(recorder, page, context._browser.options.wsEndpoint); await result._init(); return result; diff --git a/packages/playwright-core/src/server/trace/viewer/traceViewer.ts b/packages/playwright-core/src/server/trace/viewer/traceViewer.ts index 3b5cf78dab..6419312a11 100644 --- a/packages/playwright-core/src/server/trace/viewer/traceViewer.ts +++ b/packages/playwright-core/src/server/trace/viewer/traceViewer.ts @@ -17,9 +17,8 @@ import path from 'path'; import fs from 'fs'; import { HttpServer } from '../../../utils/httpServer'; -import { findChromiumChannel } from '../../registry'; import { createGuid, gracefullyProcessExitDoNotHang, isUnderTest } from '../../../utils'; -import { installAppIcon, syncLocalStorageWithSettings } from '../../chromium/crApp'; +import { syncLocalStorageWithSettings } from '../../chromium/crApp'; import { serverSideCallMetadata } from '../../instrumentation'; import { createPlaywright } from '../../playwright'; import { ProgressController } from '../../progress'; @@ -131,35 +130,26 @@ export async function openTraceViewerApp(traceUrls: string[], browserName: strin const { url } = await startTraceViewerServer(traceUrls, options); const traceViewerPlaywright = createPlaywright({ sdkLanguage: 'javascript', isInternalPlaywright: true }); const traceViewerBrowser = isUnderTest() ? 'chromium' : browserName; - const args = traceViewerBrowser === 'chromium' ? [ - '--app=data:text/html,', - '--window-size=1280,800', - '--test-type=', - ] : []; - const context = await traceViewerPlaywright[traceViewerBrowser as 'chromium'].launchPersistentContext(serverSideCallMetadata(), '', { + const { context, page } = await traceViewerPlaywright[traceViewerBrowser as 'chromium'].launchApp({ // TODO: store language in the trace. - channel: findChromiumChannel(traceViewerPlaywright.options.sdkLanguage), - args, - noDefaultViewport: true, - headless: options?.headless, - ignoreDefaultArgs: ['--enable-automation'], - colorScheme: 'no-override', - useWebSocket: isUnderTest(), - ...options?.persistentContextOptions, + sdkLanguage: traceViewerPlaywright.options.sdkLanguage, + windowSize: { width: 1280, height: 800 }, + persistentContextOptions: { + ...options?.persistentContextOptions, + useWebSocket: isUnderTest(), + headless: options?.headless, + }, }); const controller = new ProgressController(serverSideCallMetadata(), context._browser); await controller.run(async progress => { await context._browser._defaultContext!._loadDefaultContextAsIs(progress); }); - const [page] = context.pages(); if (process.env.PWTEST_PRINT_WS_ENDPOINT) process.stderr.write('DevTools listening on: ' + context._browser.options.wsEndpoint + '\n'); - if (traceViewerBrowser === 'chromium') - await installAppIcon(page); if (!isUnderTest()) await syncLocalStorageWithSettings(page, 'traceviewer');