Skip to content

Commit

Permalink
chore: simplify server screencast code (#4501)
Browse files Browse the repository at this point in the history
Currently, we always throw from FrameSession._stopScreencast
when not running with video, and immediately catch it in
CRPage.didClose (thanks to debugger to point that).

Overall, we have code prepared for start/stop API, which
we never did, so it makes sense to simplify code a bit,
and throw if something goes wrong.
  • Loading branch information
dgozman committed Nov 20, 2020
1 parent 5e6eed0 commit aea106b
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 78 deletions.
65 changes: 21 additions & 44 deletions src/server/chromium/crPage.ts
Expand Up @@ -217,14 +217,6 @@ export class CRPage implements PageDelegate {
await this._mainFrameSession._client.send('Emulation.setDefaultBackgroundColorOverride', { color });
}

async startScreencast(options: types.PageScreencastOptions): Promise<void> {
await this._mainFrameSession._startScreencast(createGuid(), options);
}

async stopScreencast(): Promise<void> {
await this._mainFrameSession._stopScreencast();
}

async takeScreenshot(format: 'png' | 'jpeg', documentRect: types.Rect | undefined, viewportRect: types.Rect | undefined, quality: number | undefined): Promise<Buffer> {
const { visualViewport } = await this._mainFrameSession._client.send('Page.getLayoutMetrics');
if (!documentRect) {
Expand Down Expand Up @@ -335,7 +327,6 @@ class FrameSession {
private _swappedIn = false;
private _videoRecorder: VideoRecorder | null = null;
private _screencastId: string | null = null;
private _screencastState: 'stopped' | 'starting' | 'started' = 'stopped';

constructor(crPage: CRPage, client: CRSession, targetId: string, parentSession: FrameSession | null) {
this._client = client;
Expand Down Expand Up @@ -777,44 +768,30 @@ class FrameSession {
}

async _startScreencast(screencastId: string, options: types.PageScreencastOptions): Promise<void> {
if (this._screencastState !== 'stopped')
throw new Error('Already started');
const videoRecorder = await VideoRecorder.launch(options);
this._screencastState = 'starting';
try {
this._screencastState = 'started';
this._videoRecorder = videoRecorder;
this._screencastId = screencastId;
this._crPage._browserContext._browser._videoStarted(this._crPage._browserContext, screencastId, options.outputFile, this._crPage.pageOrError());
await Promise.all([
this._client.send('Page.startScreencast', {
format: 'jpeg',
quality: 90,
maxWidth: options.width,
maxHeight: options.height,
}),
new Promise(f => this._client.once('Page.screencastFrame', f))
]);
} catch (e) {
videoRecorder.stop().catch(() => {});
throw e;
}
assert(!this._screencastId);
this._videoRecorder = await VideoRecorder.launch(options);
this._screencastId = screencastId;
const gotFirstFrame = new Promise(f => this._client.once('Page.screencastFrame', f));
await this._client.send('Page.startScreencast', {
format: 'jpeg',
quality: 90,
maxWidth: options.width,
maxHeight: options.height,
});
this._crPage._browserContext._browser._videoStarted(this._crPage._browserContext, screencastId, options.outputFile, this._crPage.pageOrError());
await gotFirstFrame;
}

async _stopScreencast(): Promise<void> {
if (this._screencastState !== 'started')
throw new Error('No screencast in progress, current state: ' + this._screencastState);
try {
await this._client.send('Page.stopScreencast');
} finally {
const recorder = this._videoRecorder!;
const screencastId = this._screencastId!;
this._videoRecorder = null;
this._screencastId = null;
this._screencastState = 'stopped';
await recorder.stop().catch(() => {});
this._crPage._browserContext._browser._videoFinished(screencastId);
}
if (!this._screencastId)
return;
await this._client._sendMayFail('Page.stopScreencast');
const recorder = this._videoRecorder!;
const screencastId = this._screencastId;
this._videoRecorder = null;
this._screencastId = null;
await recorder.stop().catch(() => {});
this._crPage._browserContext._browser._videoFinished(screencastId);
}

async _updateExtraHTTPHeaders(initial: boolean): Promise<void> {
Expand Down
12 changes: 0 additions & 12 deletions src/server/firefox/ffPage.ts
Expand Up @@ -380,18 +380,6 @@ export class FFPage implements PageDelegate {
throw new Error('Not implemented');
}

async startScreencast(options: types.PageScreencastOptions): Promise<void> {
this._session.send('Page.startVideoRecording', {
file: options.outputFile,
width: options.width,
height: options.height,
});
}

async stopScreencast(): Promise<void> {
await this._session.send('Page.stopVideoRecording');
}

async takeScreenshot(format: 'png' | 'jpeg', documentRect: types.Rect | undefined, viewportRect: types.Rect | undefined, quality: number | undefined): Promise<Buffer> {
if (!documentRect) {
const context = await this._page.mainFrame()._utilityContext();
Expand Down
2 changes: 0 additions & 2 deletions src/server/page.ts
Expand Up @@ -61,8 +61,6 @@ export interface PageDelegate {
canScreenshotOutsideViewport(): boolean;
resetViewport(): Promise<void>; // Only called if canScreenshotOutsideViewport() returns false.
setBackgroundColor(color?: { r: number; g: number; b: number; a: number; }): Promise<void>;
startScreencast(options: types.PageScreencastOptions): Promise<void>;
stopScreencast(): Promise<void>;
takeScreenshot(format: string, documentRect: types.Rect | undefined, viewportRect: types.Rect | undefined, quality: number | undefined): Promise<Buffer>;

isElementHandle(remoteObject: any): boolean;
Expand Down
33 changes: 13 additions & 20 deletions src/server/webkit/wkPage.ts
Expand Up @@ -119,7 +119,7 @@ export class WKPage implements PageDelegate {
const size = this._browserContext._options.recordVideo.size || this._browserContext._options.viewport || { width: 1280, height: 720 };
const outputFile = path.join(this._browserContext._options.recordVideo.dir, createGuid() + '.webm');
promises.push(this._browserContext._ensureVideosPath().then(() => {
return this.startScreencast({
return this._startScreencast({
...size,
outputFile,
});
Expand Down Expand Up @@ -712,8 +712,7 @@ export class WKPage implements PageDelegate {
}

async closePage(runBeforeUnload: boolean): Promise<void> {
if (this._recordingVideoFile)
await this.stopScreencast();
await this._stopScreencast();
await this._pageProxySession.sendMayFail('Target.close', {
targetId: this._session.sessionId,
runBeforeUnload
Expand All @@ -728,28 +727,22 @@ export class WKPage implements PageDelegate {
await this._session.send('Page.setDefaultBackgroundColorOverride', { color });
}

async startScreencast(options: types.PageScreencastOptions): Promise<void> {
if (this._recordingVideoFile)
throw new Error('Already recording');
async _startScreencast(options: types.PageScreencastOptions): Promise<void> {
assert(!this._recordingVideoFile);
const { screencastId } = await this._pageProxySession.send('Screencast.start', {
file: options.outputFile,
width: options.width,
height: options.height,
});
this._recordingVideoFile = options.outputFile;
try {
const {screencastId} = await this._pageProxySession.send('Screencast.start', {
file: options.outputFile,
width: options.width,
height: options.height,
}) as any;
this._browserContext._browser._videoStarted(this._browserContext, screencastId, options.outputFile, this.pageOrError());
} catch (e) {
this._recordingVideoFile = null;
throw e;
}
this._browserContext._browser._videoStarted(this._browserContext, screencastId, options.outputFile, this.pageOrError());
}

async stopScreencast(): Promise<void> {
async _stopScreencast(): Promise<void> {
if (!this._recordingVideoFile)
throw new Error('No video recording in progress');
return;
await this._pageProxySession.sendMayFail('Screencast.stop');
this._recordingVideoFile = null;
await this._pageProxySession.send('Screencast.stop');
}

async takeScreenshot(format: string, documentRect: types.Rect | undefined, viewportRect: types.Rect | undefined, quality: number | undefined): Promise<Buffer> {
Expand Down

0 comments on commit aea106b

Please sign in to comment.