diff --git a/packages/playwright-core/src/browserServerImpl.ts b/packages/playwright-core/src/browserServerImpl.ts index e3dcda6687..76a1807342 100644 --- a/packages/playwright-core/src/browserServerImpl.ts +++ b/packages/playwright-core/src/browserServerImpl.ts @@ -20,7 +20,7 @@ import { BrowserServerLauncher, BrowserServer } from './client/browserType'; import { envObjectToArray } from './client/clientHelper'; import { createGuid } from './utils/utils'; import { ProtocolLogger } from './server/types'; -import { internalCallMetadata } from './server/instrumentation'; +import { serverSideCallMetadata } from './server/instrumentation'; import { createPlaywright } from './server/playwright'; import { PlaywrightServer } from './remote/playwrightServer'; import { helper } from './server/helper'; @@ -36,7 +36,7 @@ export class BrowserServerLauncherImpl implements BrowserServerLauncher { async launchServer(options: LaunchServerOptions = {}): Promise { const playwright = createPlaywright('javascript'); // 1. Pre-launch the browser - const metadata = internalCallMetadata(); + const metadata = serverSideCallMetadata(); const browser = await playwright[this._browserName].launch(metadata, { ...options, ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined, diff --git a/packages/playwright-core/src/dispatchers/browserDispatcher.ts b/packages/playwright-core/src/dispatchers/browserDispatcher.ts index e2a5f02112..d145747bc2 100644 --- a/packages/playwright-core/src/dispatchers/browserDispatcher.ts +++ b/packages/playwright-core/src/dispatchers/browserDispatcher.ts @@ -21,7 +21,7 @@ import { CDPSessionDispatcher } from './cdpSessionDispatcher'; import { Dispatcher, DispatcherScope } from './dispatcher'; import { CRBrowser } from '../server/chromium/crBrowser'; import { PageDispatcher } from './pageDispatcher'; -import { CallMetadata, internalCallMetadata } from '../server/instrumentation'; +import { CallMetadata, serverSideCallMetadata } from '../server/instrumentation'; import { BrowserContext } from '../server/browserContext'; import { Selectors } from '../server/selectors'; @@ -131,6 +131,6 @@ export class ConnectedBrowserDispatcher extends Dispatcher context.close(internalCallMetadata()))); + await Promise.all(Array.from(this._contexts).map(context => context.close(serverSideCallMetadata()))); } } diff --git a/packages/playwright-core/src/protocol/callMetadata.ts b/packages/playwright-core/src/protocol/callMetadata.ts index b1f9fbf877..d8890d6fa6 100644 --- a/packages/playwright-core/src/protocol/callMetadata.ts +++ b/packages/playwright-core/src/protocol/callMetadata.ts @@ -27,7 +27,12 @@ export type CallMetadata = { method: string; params: any; apiName?: string; + // Client is making an internal call that should not show up in + // the inspector or trace. internal?: boolean; + // Service-side is making a call to itself, this metadata does not go + // through the dispatcher, so is always excluded from inspector / tracing. + isServerSide?: boolean; stack?: StackFrame[]; log: string[]; afterSnapshot?: string; diff --git a/packages/playwright-core/src/remote/playwrightServer.ts b/packages/playwright-core/src/remote/playwrightServer.ts index cfb763625c..35aadf3099 100644 --- a/packages/playwright-core/src/remote/playwrightServer.ts +++ b/packages/playwright-core/src/remote/playwrightServer.ts @@ -18,7 +18,7 @@ import debug from 'debug'; import * as http from 'http'; import WebSocket from 'ws'; import { DispatcherConnection, DispatcherScope, Root } from '../dispatchers/dispatcher'; -import { internalCallMetadata } from '../server/instrumentation'; +import { serverSideCallMetadata } from '../server/instrumentation'; import { createPlaywright, Playwright } from '../server/playwright'; import { Browser } from '../server/browser'; import { gracefullyCloseAll } from '../utils/processLauncher'; @@ -169,7 +169,7 @@ class Connection { const playwright = createPlaywright('javascript'); const socksProxy = enableSocksProxy ? await this._enableSocksProxy(playwright) : undefined; - const browser = await playwright[executable.browserName].launch(internalCallMetadata(), { + const browser = await playwright[executable.browserName].launch(serverSideCallMetadata(), { channel: executable.type === 'browser' ? undefined : executable.name, }); diff --git a/packages/playwright-core/src/server/android/android.ts b/packages/playwright-core/src/server/android/android.ts index fefd9f2ece..1faf9529ff 100644 --- a/packages/playwright-core/src/server/android/android.ts +++ b/packages/playwright-core/src/server/android/android.ts @@ -33,7 +33,7 @@ import { RecentLogsCollector } from '../../utils/debugLogger'; import { gracefullyCloseSet } from '../../utils/processLauncher'; import { TimeoutSettings } from '../../utils/timeoutSettings'; import { AndroidWebView } from '../../protocol/channels'; -import { SdkObject, internalCallMetadata } from '../instrumentation'; +import { SdkObject, serverSideCallMetadata } from '../instrumentation'; const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-'); @@ -288,7 +288,7 @@ export class AndroidDevice extends SdkObject { validateBrowserContextOptions(options, browserOptions); const browser = await CRBrowser.connect(androidBrowser, browserOptions); - const controller = new ProgressController(internalCallMetadata(), this); + const controller = new ProgressController(serverSideCallMetadata(), this); const defaultContext = browser._defaultContext!; await controller.run(async progress => { await defaultContext._loadDefaultContextAsIs(progress); diff --git a/packages/playwright-core/src/server/browser.ts b/packages/playwright-core/src/server/browser.ts index 7c07e31700..6e79480b11 100644 --- a/packages/playwright-core/src/server/browser.ts +++ b/packages/playwright-core/src/server/browser.ts @@ -103,10 +103,10 @@ export abstract class Browser extends SdkObject { _videoStarted(context: BrowserContext, videoId: string, path: string, pageOrError: Promise) { const artifact = new Artifact(context, path); this._idToVideo.set(videoId, { context, artifact }); - context.emit(BrowserContext.Events.VideoStarted, artifact); pageOrError.then(page => { if (page instanceof Page) { page._video = artifact; + page.emitOnContext(BrowserContext.Events.VideoStarted, artifact); page.emit(Page.Events.Video, artifact); } }); diff --git a/packages/playwright-core/src/server/browserContext.ts b/packages/playwright-core/src/server/browserContext.ts index bcf3af9279..f15053fc32 100644 --- a/packages/playwright-core/src/server/browserContext.ts +++ b/packages/playwright-core/src/server/browserContext.ts @@ -28,7 +28,7 @@ import { Progress } from './progress'; import { Selectors } from './selectors'; import * as types from './types'; import path from 'path'; -import { CallMetadata, internalCallMetadata, SdkObject } from './instrumentation'; +import { CallMetadata, serverSideCallMetadata, SdkObject } from './instrumentation'; import { Debugger } from './supplements/debugger'; import { Tracing } from './trace/recorder/tracing'; import { HarRecorder } from './supplements/har/harRecorder'; @@ -97,7 +97,7 @@ export abstract class BrowserContext extends SdkObject { } async _initialize() { - if (this.attribution.isInternal) + if (this.attribution.isInternalPlaywright) return; // Debugger will pause execution upon page.pause in headed mode. const contextDebugger = new Debugger(this); @@ -326,6 +326,8 @@ export abstract class BrowserContext extends SdkObject { async newPage(metadata: CallMetadata): Promise { const pageDelegate = await this.newPageDelegate(); + if (metadata.isServerSide) + pageDelegate.potentiallyUninitializedPage().markAsServerSideOnly(); const pageOrError = await pageDelegate.pageOrError(); if (pageOrError instanceof Page) { if (pageOrError.isClosed()) @@ -345,7 +347,7 @@ export abstract class BrowserContext extends SdkObject { origins: [] }; if (this._origins.size) { - const internalMetadata = internalCallMetadata(); + const internalMetadata = serverSideCallMetadata(); const page = await this.newPage(internalMetadata); await page._setServerRequestInterceptor(handler => { handler.fulfill({ body: '' }).catch(() => {}); @@ -370,7 +372,7 @@ export abstract class BrowserContext extends SdkObject { if (state.cookies) await this.addCookies(state.cookies); if (state.origins && state.origins.length) { - const internalMetadata = internalCallMetadata(); + const internalMetadata = serverSideCallMetadata(); const page = await this.newPage(internalMetadata); await page._setServerRequestInterceptor(handler => { handler.fulfill({ body: '' }).catch(() => {}); diff --git a/packages/playwright-core/src/server/chromium/crBrowser.ts b/packages/playwright-core/src/server/chromium/crBrowser.ts index bc6e30ec21..b7fb59819f 100644 --- a/packages/playwright-core/src/server/chromium/crBrowser.ts +++ b/packages/playwright-core/src/server/chromium/crBrowser.ts @@ -174,14 +174,14 @@ export class CRBrowser extends Browser { assert(!this._serviceWorkers.has(targetInfo.targetId), 'Duplicate target ' + targetInfo.targetId); if (targetInfo.type === 'background_page') { - const backgroundPage = new CRPage(session, targetInfo.targetId, context, null, false, true); + const backgroundPage = new CRPage(session, targetInfo.targetId, context, null, { hasUIWindow: false, isBackgroundPage: true }); this._backgroundPages.set(targetInfo.targetId, backgroundPage); return; } if (targetInfo.type === 'page') { const opener = targetInfo.openerId ? this._crPages.get(targetInfo.openerId) || null : null; - const crPage = new CRPage(session, targetInfo.targetId, context, opener, true, false); + const crPage = new CRPage(session, targetInfo.targetId, context, opener, { hasUIWindow: true, isBackgroundPage: false }); this._crPages.set(targetInfo.targetId, crPage); return; } diff --git a/packages/playwright-core/src/server/chromium/crPage.ts b/packages/playwright-core/src/server/chromium/crPage.ts index 301ad2b847..a5457ad49f 100644 --- a/packages/playwright-core/src/server/chromium/crPage.ts +++ b/packages/playwright-core/src/server/chromium/crPage.ts @@ -74,10 +74,10 @@ export class CRPage implements PageDelegate { return crPage._mainFrameSession; } - constructor(client: CRSession, targetId: string, browserContext: CRBrowserContext, opener: CRPage | null, hasUIWindow: boolean, isBackgroundPage: boolean) { + constructor(client: CRSession, targetId: string, browserContext: CRBrowserContext, opener: CRPage | null, bits: { hasUIWindow: boolean, isBackgroundPage: boolean }) { this._targetId = targetId; this._opener = opener; - this._isBackgroundPage = isBackgroundPage; + this._isBackgroundPage = bits.isBackgroundPage; const dragManager = new DragManager(this); this.rawKeyboard = new RawKeyboardImpl(client, browserContext._browser._platform() === 'mac', dragManager); this.rawMouse = new RawMouseImpl(this, client, dragManager); @@ -97,7 +97,7 @@ export class CRPage implements PageDelegate { } // Note: it is important to call |reportAsNew| before resolving pageOrError promise, // so that anyone who awaits pageOrError got a ready and reported page. - this._pagePromise = this._mainFrameSession._initialize(hasUIWindow).then(async r => { + this._pagePromise = this._mainFrameSession._initialize(bits.hasUIWindow).then(async r => { await this._page.initOpener(this._opener); return r; }).catch(async e => { @@ -113,6 +113,10 @@ export class CRPage implements PageDelegate { }); } + potentiallyUninitializedPage(): Page { + return this._page; + } + private _reportAsNew(error?: Error) { if (this._isBackgroundPage) { if (!error) diff --git a/packages/playwright-core/src/server/chromium/videoRecorder.ts b/packages/playwright-core/src/server/chromium/videoRecorder.ts index 644af4fe18..b320d0fda3 100644 --- a/packages/playwright-core/src/server/chromium/videoRecorder.ts +++ b/packages/playwright-core/src/server/chromium/videoRecorder.ts @@ -19,7 +19,7 @@ import { assert, monotonicTime } from '../../utils/utils'; import { Page } from '../page'; import { launchProcess } from '../../utils/processLauncher'; import { Progress, ProgressController } from '../progress'; -import { internalCallMetadata } from '../instrumentation'; +import { serverSideCallMetadata } from '../instrumentation'; import * as types from '../types'; const fps = 25; @@ -40,7 +40,7 @@ export class VideoRecorder { if (!options.outputFile.endsWith('.webm')) throw new Error('File must have .webm extension'); - const controller = new ProgressController(internalCallMetadata(), page); + const controller = new ProgressController(serverSideCallMetadata(), page); controller.setLogName('browser'); return await controller.run(async progress => { const recorder = new VideoRecorder(page, ffmpegPath, progress); diff --git a/packages/playwright-core/src/server/electron/electron.ts b/packages/playwright-core/src/server/electron/electron.ts index 356fe2c656..6b6b02de06 100644 --- a/packages/playwright-core/src/server/electron/electron.ts +++ b/packages/playwright-core/src/server/electron/electron.ts @@ -35,7 +35,7 @@ import { BrowserOptions, BrowserProcess, PlaywrightOptions } from '../browser'; import * as childProcess from 'child_process'; import * as readline from 'readline'; import { RecentLogsCollector } from '../../utils/debugLogger'; -import { internalCallMetadata, SdkObject } from '../instrumentation'; +import { serverSideCallMetadata, SdkObject } from '../instrumentation'; import * as channels from '../../protocol/channels'; import { BrowserContextOptions } from '../types'; @@ -82,9 +82,9 @@ export class ElectronApplication extends SdkObject { } async close() { - const progressController = new ProgressController(internalCallMetadata(), this); + const progressController = new ProgressController(serverSideCallMetadata(), this); const closed = progressController.run(progress => helper.waitForEvent(progress, this, ElectronApplication.Events.Close).promise); - await this._browserContext.close(internalCallMetadata()); + await this._browserContext.close(serverSideCallMetadata()); this._nodeConnection.close(); await closed; } @@ -112,7 +112,7 @@ export class Electron extends SdkObject { const { args = [], } = options; - const controller = new ProgressController(internalCallMetadata(), this); + const controller = new ProgressController(serverSideCallMetadata(), this); controller.setLogName('browser'); return controller.run(async progress => { let app: ElectronApplication | undefined = undefined; diff --git a/packages/playwright-core/src/server/firefox/ffPage.ts b/packages/playwright-core/src/server/firefox/ffPage.ts index 6eba2ebc64..3e37cc5ea9 100644 --- a/packages/playwright-core/src/server/firefox/ffPage.ts +++ b/packages/playwright-core/src/server/firefox/ffPage.ts @@ -116,6 +116,10 @@ export class FFPage implements PageDelegate { this.evaluateOnNewDocument('', UTILITY_WORLD_NAME).catch(e => this._markAsError(e)); } + potentiallyUninitializedPage(): Page { + return this._page; + } + async _markAsError(error: Error) { // Same error may be report twice: channer disconnected and session.send fails. if (this._initializationFailed) diff --git a/packages/playwright-core/src/server/frames.ts b/packages/playwright-core/src/server/frames.ts index cf0243329b..637f402f5e 100644 --- a/packages/playwright-core/src/server/frames.ts +++ b/packages/playwright-core/src/server/frames.ts @@ -30,7 +30,7 @@ import { Progress, ProgressController } from './progress'; import { assert, constructURLBasedOnBaseURL, makeWaitForNextTask } from '../utils/utils'; import { ManualPromise } from '../utils/async'; import { debugLogger } from '../utils/debugLogger'; -import { CallMetadata, internalCallMetadata, SdkObject } from './instrumentation'; +import { CallMetadata, serverSideCallMetadata, SdkObject } from './instrumentation'; import type InjectedScript from './injected/injectedScript'; import type { ElementStateWithoutStable, FrameExpectParams, InjectedScriptPoll, InjectedScriptProgress } from './injected/injectedScript'; import { isSessionClosedError } from './protocolError'; @@ -277,7 +277,7 @@ export class FrameManager { route.continue(request, {}); return; } - this._page._browserContext.emit(BrowserContext.Events.Request, request); + this._page.emitOnContext(BrowserContext.Events.Request, request); if (route) this._page._requestStarted(request, route); } @@ -285,14 +285,14 @@ export class FrameManager { requestReceivedResponse(response: network.Response) { if (response.request()._isFavicon) return; - this._page._browserContext.emit(BrowserContext.Events.Response, response); + this._page.emitOnContext(BrowserContext.Events.Response, response); } reportRequestFinished(request: network.Request, response: network.Response | null) { this._inflightRequestFinished(request); if (request._isFavicon) return; - this._page._browserContext.emit(BrowserContext.Events.RequestFinished, { request, response }); + this._page.emitOnContext(BrowserContext.Events.RequestFinished, { request, response }); } requestFailed(request: network.Request, canceled: boolean) { @@ -306,7 +306,7 @@ export class FrameManager { } if (request._isFavicon) return; - this._page._browserContext.emit(BrowserContext.Events.RequestFailed, request); + this._page.emitOnContext(BrowserContext.Events.RequestFailed, request); } dialogDidOpen(dialog: Dialog) { @@ -1366,7 +1366,7 @@ export class Frame extends SdkObject { return result; return JSON.stringify(result); }`; - const handle = await this._waitForFunctionExpression(internalCallMetadata(), expression, true, undefined, { timeout: progress.timeUntilDeadline() }, 'utility'); + const handle = await this._waitForFunctionExpression(serverSideCallMetadata(), expression, true, undefined, { timeout: progress.timeUntilDeadline() }, 'utility'); return JSON.parse(handle.rawValue()) as R; } diff --git a/packages/playwright-core/src/server/instrumentation.ts b/packages/playwright-core/src/server/instrumentation.ts index 4a31d10007..478f4b2cff 100644 --- a/packages/playwright-core/src/server/instrumentation.ts +++ b/packages/playwright-core/src/server/instrumentation.ts @@ -25,7 +25,7 @@ import type { Frame } from './frames'; import type { Page } from './page'; export type Attribution = { - isInternal: boolean, + isInternalPlaywright: boolean, browserType?: BrowserType; browser?: Browser; context?: BrowserContext | APIRequestContext; @@ -92,7 +92,7 @@ export function createInstrumentation(): Instrumentation { }); } -export function internalCallMetadata(): CallMetadata { +export function serverSideCallMetadata(): CallMetadata { return { id: '', wallTime: 0, @@ -102,6 +102,7 @@ export function internalCallMetadata(): CallMetadata { method: '', params: {}, log: [], - snapshots: [] + snapshots: [], + isServerSide: true, }; } diff --git a/packages/playwright-core/src/server/page.ts b/packages/playwright-core/src/server/page.ts index 51be7ca751..df2bb31823 100644 --- a/packages/playwright-core/src/server/page.ts +++ b/packages/playwright-core/src/server/page.ts @@ -49,6 +49,7 @@ export interface PageDelegate { exposeBinding(binding: PageBinding): Promise; evaluateOnNewDocument(source: string): Promise; closePage(runBeforeUnload: boolean): Promise; + potentiallyUninitializedPage(): Page; pageOrError(): Promise; navigateFrame(frame: frames.Frame, url: string, referrer: string | undefined): Promise; @@ -158,6 +159,7 @@ export class Page extends SdkObject { _video: Artifact | null = null; _opener: Page | undefined; private _frameThrottler = new FrameThrottler(10, 200); + private _isServerSideOnly = false; constructor(delegate: PageDelegate, browserContext: BrowserContext) { super(browserContext, 'page'); @@ -203,8 +205,8 @@ export class Page extends SdkObject { this._setIsError(error); } this._initialized = true; - this._browserContext.emit(BrowserContext.Events.Page, this); - // I may happen that page iniatialization finishes after Close event has already been sent, + this.emitOnContext(BrowserContext.Events.Page, this); + // I may happen that page initialization finishes after Close event has already been sent, // in that case we fire another Close event to ensure that each reported Page will have // corresponding Close event after it is reported on the context. if (this.isClosed()) @@ -215,6 +217,12 @@ export class Page extends SdkObject { return this._initialized ? this : undefined; } + emitOnContext(event: string | symbol, ...args: any[]) { + if (this._isServerSideOnly) + return; + this._browserContext.emit(event, ...args); + } + async _doSlowMo() { const slowMo = this._browserContext._browser.options.slowMo; if (!slowMo) @@ -611,6 +619,10 @@ export class Page extends SdkObject { async hideHighlight() { await Promise.all(this.frames().map(frame => frame.hideHighlight().catch(() => {}))); } + + markAsServerSideOnly() { + this._isServerSideOnly = true; + } } export class Worker extends SdkObject { diff --git a/packages/playwright-core/src/server/playwright.ts b/packages/playwright-core/src/server/playwright.ts index 8240459fe8..f84c2962bc 100644 --- a/packages/playwright-core/src/server/playwright.ts +++ b/packages/playwright-core/src/server/playwright.ts @@ -36,8 +36,8 @@ export class Playwright extends SdkObject { readonly options: PlaywrightOptions; private _allPages = new Set(); - constructor(sdkLanguage: string, isInternal: boolean) { - super({ attribution: { isInternal }, instrumentation: createInstrumentation() } as any, undefined, 'Playwright'); + constructor(sdkLanguage: string, isInternalPlaywright: boolean) { + super({ attribution: { isInternalPlaywright }, instrumentation: createInstrumentation() } as any, undefined, 'Playwright'); this.instrumentation.addListener({ onPageOpen: page => this._allPages.add(page), onPageClose: page => this._allPages.delete(page), @@ -63,6 +63,6 @@ export class Playwright extends SdkObject { } } -export function createPlaywright(sdkLanguage: string, isInternal: boolean = false) { - return new Playwright(sdkLanguage, isInternal); +export function createPlaywright(sdkLanguage: string, isInternalPlaywright: boolean = false) { + return new Playwright(sdkLanguage, isInternalPlaywright); } diff --git a/packages/playwright-core/src/server/supplements/recorder/recorderApp.ts b/packages/playwright-core/src/server/supplements/recorder/recorderApp.ts index af3429b04d..1d7c470904 100644 --- a/packages/playwright-core/src/server/supplements/recorder/recorderApp.ts +++ b/packages/playwright-core/src/server/supplements/recorder/recorderApp.ts @@ -19,7 +19,7 @@ import path from 'path'; import { Page } from '../../page'; import { ProgressController } from '../../progress'; import { EventEmitter } from 'events'; -import { internalCallMetadata } from '../../instrumentation'; +import { serverSideCallMetadata } from '../../instrumentation'; import type { CallLog, EventData, Mode, Source } from './recorderTypes'; import { isUnderTest } from '../../../utils/utils'; import * as mime from 'mime'; @@ -61,7 +61,7 @@ export class RecorderApp extends EventEmitter implements IRecorderApp { } async close() { - await this._page.context().close(internalCallMetadata()); + await this._page.context().close(serverSideCallMetadata()); } private async _init() { @@ -89,11 +89,11 @@ export class RecorderApp extends EventEmitter implements IRecorderApp { this._page.once('close', () => { this.emit('close'); - this._page.context().close(internalCallMetadata()).catch(() => {}); + this._page.context().close(serverSideCallMetadata()).catch(() => {}); }); const mainFrame = this._page.mainFrame(); - await mainFrame.goto(internalCallMetadata(), 'https://playwright/index.html'); + await mainFrame.goto(serverSideCallMetadata(), 'https://playwright/index.html'); } static async open(sdkLanguage: string, headed: boolean): Promise { @@ -108,7 +108,7 @@ export class RecorderApp extends EventEmitter implements IRecorderApp { ]; if (process.env.PWTEST_RECORDER_PORT) args.push(`--remote-debugging-port=${process.env.PWTEST_RECORDER_PORT}`); - const context = await recorderPlaywright.chromium.launchPersistentContext(internalCallMetadata(), '', { + const context = await recorderPlaywright.chromium.launchPersistentContext(serverSideCallMetadata(), '', { channel: findChromiumChannel(sdkLanguage), args, noDefaultViewport: true, @@ -116,7 +116,7 @@ export class RecorderApp extends EventEmitter implements IRecorderApp { headless: !!process.env.PWTEST_CLI_HEADLESS || (isUnderTest() && !headed), useWebSocket: !!process.env.PWTEST_RECORDER_PORT }); - const controller = new ProgressController(internalCallMetadata(), context._browser); + const controller = new ProgressController(serverSideCallMetadata(), context._browser); await controller.run(async progress => { await context._browser._defaultContext!._loadDefaultContextAsIs(progress); }); diff --git a/packages/playwright-core/src/server/trace/viewer/traceViewer.ts b/packages/playwright-core/src/server/trace/viewer/traceViewer.ts index ab71bbbfcf..57e9ea4af6 100644 --- a/packages/playwright-core/src/server/trace/viewer/traceViewer.ts +++ b/packages/playwright-core/src/server/trace/viewer/traceViewer.ts @@ -22,7 +22,7 @@ import { findChromiumChannel } from '../../../utils/registry'; import { isUnderTest } from '../../../utils/utils'; import { BrowserContext } from '../../browserContext'; import { installAppIcon } from '../../chromium/crApp'; -import { internalCallMetadata } from '../../instrumentation'; +import { serverSideCallMetadata } from '../../instrumentation'; import { createPlaywright } from '../../playwright'; import { ProgressController } from '../../progress'; @@ -61,7 +61,7 @@ export async function showTraceViewer(traceUrls: string[], browserName: string, if (isUnderTest()) args.push(`--remote-debugging-port=0`); - const context = await traceViewerPlaywright[traceViewerBrowser as 'chromium'].launchPersistentContext(internalCallMetadata(), '', { + const context = await traceViewerPlaywright[traceViewerBrowser as 'chromium'].launchPersistentContext(serverSideCallMetadata(), '', { // TODO: store language in the trace. channel: findChromiumChannel(traceViewerPlaywright.options.sdkLanguage), args, @@ -71,7 +71,7 @@ export async function showTraceViewer(traceUrls: string[], browserName: string, useWebSocket: isUnderTest() }); - const controller = new ProgressController(internalCallMetadata(), context._browser); + const controller = new ProgressController(serverSideCallMetadata(), context._browser); await controller.run(async progress => { await context._browser._defaultContext!._loadDefaultContextAsIs(progress); }); @@ -82,11 +82,11 @@ export async function showTraceViewer(traceUrls: string[], browserName: string, await installAppIcon(page); if (isUnderTest()) - page.on('close', () => context.close(internalCallMetadata()).catch(() => {})); + page.on('close', () => context.close(serverSideCallMetadata()).catch(() => {})); else page.on('close', () => process.exit()); const searchQuery = traceUrls.length ? '?' + traceUrls.map(t => `trace=${t}`).join('&') : ''; - await page.mainFrame().goto(internalCallMetadata(), urlPrefix + `/trace/index.html${searchQuery}`); + await page.mainFrame().goto(serverSideCallMetadata(), urlPrefix + `/trace/index.html${searchQuery}`); return context; } diff --git a/packages/playwright-core/src/server/webkit/wkPage.ts b/packages/playwright-core/src/server/webkit/wkPage.ts index ca2888baa3..9d21c6dcb4 100644 --- a/packages/playwright-core/src/server/webkit/wkPage.ts +++ b/packages/playwright-core/src/server/webkit/wkPage.ts @@ -109,6 +109,10 @@ export class WKPage implements PageDelegate { } } + potentiallyUninitializedPage(): Page { + return this._page; + } + private async _initializePageProxySession() { const promises: Promise[] = [ this._pageProxySession.send('Dialog.enable'), diff --git a/tests/browsercontext-storage-state.spec.ts b/tests/browsercontext-storage-state.spec.ts index 99fe00894d..bf9ece7000 100644 --- a/tests/browsercontext-storage-state.spec.ts +++ b/tests/browsercontext-storage-state.spec.ts @@ -141,3 +141,24 @@ it('should capture cookies', async ({ server, context, page, contextFactory }) = 'empty=', ]); }); + +it('should not emit events about internal page', async ({ contextFactory }) => { + const context = await contextFactory(); + const page = await context.newPage(); + await page.route('**/*', route => { + route.fulfill({ body: '' }); + }); + await page.goto('https://www.example.com'); + await page.evaluate(() => localStorage['name1'] = 'value1'); + await page.goto('https://www.domain.com'); + await page.evaluate(() => localStorage['name2'] = 'value2'); + + const events = []; + context.on('page', e => events.push(e)); + context.on('request', e => events.push(e)); + context.on('requestfailed', e => events.push(e)); + context.on('requestfinished', e => events.push(e)); + context.on('response', e => events.push(e)); + await context.storageState(); + expect(events).toHaveLength(0); +});