Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/src/api/class-screencast.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ await page.screencast.stop();
```js
// Capture frames
await page.screencast.start({
onFrame: ({ data, viewportWidth, viewportHeight }) => {
console.log(`frame size: ${data.length} (${viewportWidth}x${viewportHeight})`);
onFrame: ({ data, timestamp, viewportWidth, viewportHeight }) => {
console.log(`frame size: ${data.length} (${viewportWidth}x${viewportHeight}) at ${timestamp}`);
},
size: { width: 800, height: 600 },
});
Expand All @@ -36,6 +36,7 @@ await page.screencast.stop();
- `onFrame` <[function]\([Object]\): [Promise]>
* alias: ScreencastFrame
- `data` <[Buffer]> JPEG-encoded frame data.
- `timestamp` <[float]> The timestamp of when the frame was presented by the browser, in milliseconds since the Unix epoch.
- `viewportWidth` <[int]> Width of the page viewport at the time the frame was captured.
- `viewportHeight` <[int]> Height of the page viewport at the time the frame was captured.

Expand All @@ -55,7 +56,6 @@ The quality of the image, between 0-100.

### option: Screencast.start.size
* since: v1.59
* langs: js
- `size` ?<[Object]>
* alias-csharp: ScreencastSize
- `width` <[int]> Max frame width in pixels.
Expand Down
6 changes: 3 additions & 3 deletions packages/playwright-client/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16706,8 +16706,8 @@ export interface Screencast {
* ```js
* // Capture frames
* await page.screencast.start({
* onFrame: ({ data, viewportWidth, viewportHeight }) => {
* console.log(`frame size: ${data.length} (${viewportWidth}x${viewportHeight})`);
* onFrame: ({ data, timestamp, viewportWidth, viewportHeight }) => {
* console.log(`frame size: ${data.length} (${viewportWidth}x${viewportHeight}) at ${timestamp}`);
* },
* size: { width: 800, height: 600 },
* });
Expand All @@ -16718,7 +16718,7 @@ export interface Screencast {
* @param options
*/
start(options?: {
onFrame?: (frame: { data: Buffer, viewportWidth: number, viewportHeight: number }) => Promise<any>|any;
onFrame?: (frame: { data: Buffer, timestamp: number, viewportWidth: number, viewportHeight: number }) => Promise<any>|any;
path?: string;
size?: {
width: number;
Expand Down
8 changes: 4 additions & 4 deletions packages/playwright-core/src/client/screencast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,17 @@ export class Screencast implements api.Screencast {
private _page: Page;
private _started = false;
private _savePath: string | undefined;
private _onFrame: ((frame: { data: Buffer, viewportWidth: number, viewportHeight: number }) => Promise<any>) | null = null;
private _onFrame: ((frame: { data: Buffer, timestamp: number, viewportWidth: number, viewportHeight: number }) => Promise<any>) | null = null;
private _artifact: Artifact | undefined;

constructor(page: Page) {
this._page = page;
this._page._channel.on('screencastFrame', ({ data, viewportWidth, viewportHeight }) => {
void this._onFrame?.({ data, viewportWidth, viewportHeight });
this._page._channel.on('screencastFrame', ({ data, timestamp, viewportWidth, viewportHeight }) => {
void this._onFrame?.({ data, timestamp, viewportWidth, viewportHeight });
});
}

async start(options: { onFrame?: (frame: { data: Buffer, viewportWidth: number, viewportHeight: number }) => Promise<any>|any, path?: string, size?: { width: number, height: number }, quality?: number } = {}): Promise<DisposableStub> {
async start(options: { onFrame?: (frame: { data: Buffer, timestamp: number, viewportWidth: number, viewportHeight: number }) => Promise<any>|any, path?: string, size?: { width: number, height: number }, quality?: number } = {}): Promise<DisposableStub> {
if (this._started)
throw new Error('Screencast is already started');
this._started = true;
Expand Down
1 change: 1 addition & 0 deletions packages/playwright-core/src/protocol/validator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2299,6 +2299,7 @@ scheme.PageRouteEvent = tObject({
});
scheme.PageScreencastFrameEvent = tObject({
data: tBinary,
timestamp: tFloat,
viewportWidth: tInt,
viewportHeight: tInt,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel, Brows
if (params.sendFrames) {
this._screencastClient = {
onFrame: (frame: ScreencastFrame) => {
this._dispatchEvent('screencastFrame', { data: frame.buffer, viewportWidth: frame.viewportWidth, viewportHeight: frame.viewportHeight });
this._dispatchEvent('screencastFrame', { data: frame.buffer, timestamp: frame.frameSwapWallTime, viewportWidth: frame.viewportWidth, viewportHeight: frame.viewportHeight });
},
dispose: () => {},
size: params.size,
Expand Down
12 changes: 6 additions & 6 deletions packages/playwright-core/src/server/har/harTracer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -321,15 +321,15 @@ export class HarTracer {
// In WebKit security details and server ip are reported in Network.loadingFinished, so we populate
// it here to not hang in case of long chunked responses, see https://github.com/microsoft/playwright/issues/21182.
if (!this._options.omitServerIP) {
this._addBarrier(page || request.serviceWorker(), response.serverAddr(nullProgress).then(server => {
this._addBarrier(page || request.serviceWorker(), response.internalServerAddr().then(server => {
if (server?.ipAddress)
harEntry.serverIPAddress = server.ipAddress;
if (server?.port)
harEntry._serverPort = server.port;
}));
}
if (!this._options.omitSecurityDetails) {
this._addBarrier(page || request.serviceWorker(), response.securityDetails(nullProgress).then(details => {
this._addBarrier(page || request.serviceWorker(), response.internalSecurityDetails().then(details => {
if (details)
harEntry._securityDetails = details;
}));
Expand Down Expand Up @@ -374,7 +374,7 @@ export class HarTracer {
});
this._addBarrier(page || request.serviceWorker(), promise);

this._addBarrier(page || request.serviceWorker(), response.httpVersion(nullProgress).then(httpVersion => {
this._addBarrier(page || request.serviceWorker(), response.internalHttpVersion().then(httpVersion => {
harEntry.request.httpVersion = httpVersion;
harEntry.response.httpVersion = httpVersion;
}));
Expand All @@ -385,7 +385,7 @@ export class HarTracer {
this._computeHarEntryTotalTime(harEntry);

if (!this._options.omitSizes) {
this._addBarrier(page || request.serviceWorker(), response.sizes(nullProgress).then(sizes => {
this._addBarrier(page || request.serviceWorker(), response.internalSizes().then(sizes => {
harEntry.response.bodySize = sizes.responseBodySize;
harEntry.response.headersSize = sizes.responseHeadersSize;
harEntry.response._transferSize = sizes.transferSize;
Expand Down Expand Up @@ -595,13 +595,13 @@ export class HarTracer {
}

this._recordRequestOverrides(harEntry, request);
this._addBarrier(page || request.serviceWorker(), request.rawRequestHeaders(nullProgress).then(headers => {
this._addBarrier(page || request.serviceWorker(), request.internalRawRequestHeaders().then(headers => {
this._recordRequestHeadersAndCookies(harEntry, headers);
}));
// Record available headers including redirect location in case the tracing is stopped before
// response extra info is received (in Chromium).
this._recordResponseHeaders(harEntry, response.headers());
this._addBarrier(page || request.serviceWorker(), response.rawResponseHeaders(nullProgress).then(headers => {
this._addBarrier(page || request.serviceWorker(), response.internalRawResponseHeaders().then(headers => {
this._recordResponseHeaders(harEntry, headers);
}));
}
Expand Down
26 changes: 17 additions & 9 deletions packages/playwright-core/src/server/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ export class Request extends SdkObject {
}

async rawRequestHeaders(progress: Progress): Promise<HeadersArray> {
return await this.raceWithPageClosure(progress, this._rawRequestHeaders());
return await this.raceWithPageClosure(progress, this.internalRawRequestHeaders());
}

async response(progress: Progress): Promise<Response | null> {
Expand Down Expand Up @@ -280,7 +280,7 @@ export class Request extends SdkObject {
this._rawRequestHeadersPromise.resolve(headers || this._headers);
}

private async _rawRequestHeaders(): Promise<HeadersArray> {
async internalRawRequestHeaders(): Promise<HeadersArray> {
return this._overrides?.headers || this._rawRequestHeadersPromise;
}

Expand Down Expand Up @@ -336,7 +336,7 @@ export class Request extends SdkObject {
}

async _requestHeadersSize(): Promise<number> {
return requestHeadersSize(await this._rawRequestHeaders(), this.url(), this.method());
return requestHeadersSize(await this.internalRawRequestHeaders(), this.url(), this.method());
}
}

Expand Down Expand Up @@ -553,19 +553,19 @@ export class Response extends SdkObject {
}

async serverAddr(progress: Progress): Promise<RemoteAddr | null> {
return (await this._request.raceWithPageClosure(progress, this._serverAddrPromise)) || null;
return await this._request.raceWithPageClosure(progress, this.internalServerAddr());
}

async rawResponseHeaders(progress: Progress): Promise<NameValue[]> {
return await this._request.raceWithPageClosure(progress, this._rawResponseHeadersPromise);
return await this._request.raceWithPageClosure(progress, this.internalRawResponseHeaders());
}

async httpVersion(progress: Progress): Promise<string> {
return await this._request.raceWithPageClosure(progress, this._httpVersion());
return await this._request.raceWithPageClosure(progress, this.internalHttpVersion());
}

async sizes(progress: Progress): Promise<ResourceSizes> {
return await this._request.raceWithPageClosure(progress, this._sizes());
return await this._request.raceWithPageClosure(progress, this.internalSizes());
}

_serverAddrFinished(addr?: RemoteAddr) {
Expand Down Expand Up @@ -634,6 +634,14 @@ export class Response extends SdkObject {
return await this._securityDetailsPromise || null;
}

async internalServerAddr(): Promise<RemoteAddr | null> {
return await this._serverAddrPromise || null;
}

async internalRawResponseHeaders(): Promise<HeadersArray> {
return await this._rawResponseHeadersPromise;
}

internalBody(): Promise<Buffer> {
if (!this._contentPromise) {
this._contentPromise = this._finishedPromise.then(async () => {
Expand Down Expand Up @@ -661,7 +669,7 @@ export class Response extends SdkObject {
return this._request.frame();
}

private async _httpVersion(): Promise<string> {
async internalHttpVersion(): Promise<string> {
const httpVersion = await this._httpVersionPromise || null;
if (!httpVersion)
return 'HTTP/1.1';
Expand All @@ -685,7 +693,7 @@ export class Response extends SdkObject {
return responseHeadersSize(await this._rawResponseHeadersPromise, this.statusText());
}

private async _sizes(): Promise<ResourceSizes> {
async internalSizes(): Promise<ResourceSizes> {
const requestHeadersSize = await this._request._requestHeadersSize();
const responseHeadersSize = await this.responseHeadersSize();

Expand Down
6 changes: 3 additions & 3 deletions packages/playwright-core/types/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16706,8 +16706,8 @@ export interface Screencast {
* ```js
* // Capture frames
* await page.screencast.start({
* onFrame: ({ data, viewportWidth, viewportHeight }) => {
* console.log(`frame size: ${data.length} (${viewportWidth}x${viewportHeight})`);
* onFrame: ({ data, timestamp, viewportWidth, viewportHeight }) => {
* console.log(`frame size: ${data.length} (${viewportWidth}x${viewportHeight}) at ${timestamp}`);
* },
* size: { width: 800, height: 600 },
* });
Expand All @@ -16718,7 +16718,7 @@ export interface Screencast {
* @param options
*/
start(options?: {
onFrame?: (frame: { data: Buffer, viewportWidth: number, viewportHeight: number }) => Promise<any>|any;
onFrame?: (frame: { data: Buffer, timestamp: number, viewportWidth: number, viewportHeight: number }) => Promise<any>|any;
path?: string;
size?: {
width: number;
Expand Down
1 change: 1 addition & 0 deletions packages/protocol/spec/page.yml
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,7 @@ Page:
screencastFrame:
parameters:
data: binary
timestamp: float
viewportWidth: int
viewportHeight: int

Expand Down
1 change: 1 addition & 0 deletions packages/protocol/src/channels.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4140,6 +4140,7 @@ export type PageRouteEvent = {
};
export type PageScreencastFrameEvent = {
data: Binary,
timestamp: number,
viewportWidth: number,
viewportHeight: number,
};
Expand Down
3 changes: 1 addition & 2 deletions tests/library/browsercontext-basic.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ it('should be able to click across browser contexts', async function({ browser }
await page2.close();
});

it('should be able to hover across browser contexts in parallel', async function({ browser, browserName, isBidi }) {
it.fixme(browserName === 'firefox' && !isBidi);
it('should be able to hover across browser contexts in parallel', async function({ browser }) {
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/40562' });

const html = `
Expand Down
5 changes: 3 additions & 2 deletions tests/library/screencast.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ test('onFrame receives viewport size', async ({ browser, server, trace }) => {
const context = await browser.newContext({ viewport: { width: 1000, height: 400 } });
const page = await context.newPage();

const frames: { viewportWidth: number, viewportHeight: number }[] = [];
const frames: { timestamp: number, viewportWidth: number, viewportHeight: number }[] = [];
await page.screencast.start({
onFrame: ({ viewportWidth, viewportHeight }) => frames.push({ viewportWidth, viewportHeight }),
onFrame: ({ timestamp, viewportWidth, viewportHeight }) => frames.push({ timestamp, viewportWidth, viewportHeight }),
size: { width: 500, height: 400 },
});
await page.goto(server.EMPTY_PAGE);
Expand All @@ -70,6 +70,7 @@ test('onFrame receives viewport size', async ({ browser, server, trace }) => {
for (const frame of frames) {
expect(frame.viewportWidth).toBe(1000);
expect(frame.viewportHeight).toBe(400);
expect(typeof frame.timestamp).toBe('number');
}

await context.close();
Expand Down
2 changes: 1 addition & 1 deletion utils/generate_types/overrides.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ export interface WebSocketRoute {

export interface Screencast {
start(options?: {
onFrame?: (frame: { data: Buffer, viewportWidth: number, viewportHeight: number }) => Promise<any>|any;
onFrame?: (frame: { data: Buffer, timestamp: number, viewportWidth: number, viewportHeight: number }) => Promise<any>|any;
path?: string;
size?: {
width: number;
Expand Down
Loading