mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
browser(firefox): start screencast in existing pages upon setScreencastOptions (#4045)
This makes it work in persistent context. To achieve this, we have to move screencast logic into PageTarget and make PageHandler listen to an event.
This commit is contained in:
parent
1f16ce2632
commit
133de10a47
@ -1,2 +1,2 @@
|
|||||||
1179
|
1180
|
||||||
Changed: lushnikov@chromium.org Fri Oct 2 03:14:15 PDT 2020
|
Changed: dgozman@gmail.com Fri Oct 2 09:36:06 PDT 2020
|
||||||
|
|||||||
@ -10,6 +10,7 @@ const {Preferences} = ChromeUtils.import("resource://gre/modules/Preferences.jsm
|
|||||||
const {ContextualIdentityService} = ChromeUtils.import("resource://gre/modules/ContextualIdentityService.jsm");
|
const {ContextualIdentityService} = ChromeUtils.import("resource://gre/modules/ContextualIdentityService.jsm");
|
||||||
const {NetUtil} = ChromeUtils.import('resource://gre/modules/NetUtil.jsm');
|
const {NetUtil} = ChromeUtils.import('resource://gre/modules/NetUtil.jsm');
|
||||||
const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
|
||||||
|
const {OS} = ChromeUtils.import("resource://gre/modules/osfile.jsm");
|
||||||
|
|
||||||
const helper = new Helper();
|
const helper = new Helper();
|
||||||
|
|
||||||
@ -350,6 +351,7 @@ class PageTarget {
|
|||||||
this._openerId = opener ? opener.id() : undefined;
|
this._openerId = opener ? opener.id() : undefined;
|
||||||
this._channel = SimpleChannel.createForMessageManager(`browser::page[${this._targetId}]`, this._linkedBrowser.messageManager);
|
this._channel = SimpleChannel.createForMessageManager(`browser::page[${this._targetId}]`, this._linkedBrowser.messageManager);
|
||||||
this._channelIds = new Set();
|
this._channelIds = new Set();
|
||||||
|
this._screencastInfo = undefined;
|
||||||
|
|
||||||
const navigationListener = {
|
const navigationListener = {
|
||||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]),
|
QueryInterface: ChromeUtils.generateQI([Ci.nsIWebProgressListener, Ci.nsISupportsWeakReference]),
|
||||||
@ -454,6 +456,50 @@ class PageTarget {
|
|||||||
return await this._channel.connect('').send('hasFailedToOverrideTimezone').catch(e => true);
|
return await this._channel.connect('').send('hasFailedToOverrideTimezone').catch(e => true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async startVideoRecording({width, height, scale, dir}) {
|
||||||
|
// On Mac the window may not yet be visible when TargetCreated and its
|
||||||
|
// NSWindow.windowNumber may be -1, so we wait until the window is known
|
||||||
|
// to be initialized and visible.
|
||||||
|
await this.windowReady();
|
||||||
|
const file = OS.Path.join(dir, helper.generateId() + '.webm');
|
||||||
|
if (width < 10 || width > 10000 || height < 10 || height > 10000)
|
||||||
|
throw new Error("Invalid size");
|
||||||
|
if (scale && (scale <= 0 || scale > 1))
|
||||||
|
throw new Error("Unsupported scale");
|
||||||
|
|
||||||
|
const screencast = Cc['@mozilla.org/juggler/screencast;1'].getService(Ci.nsIScreencastService);
|
||||||
|
const docShell = this._gBrowser.ownerGlobal.docShell;
|
||||||
|
// Exclude address bar and navigation control from the video.
|
||||||
|
const rect = this.linkedBrowser().getBoundingClientRect();
|
||||||
|
const devicePixelRatio = this._window.devicePixelRatio;
|
||||||
|
const videoSessionId = screencast.startVideoRecording(docShell, file, width, height, scale || 0, devicePixelRatio * rect.top);
|
||||||
|
this._screencastInfo = { videoSessionId, file };
|
||||||
|
this.emit('screencastStarted');
|
||||||
|
}
|
||||||
|
|
||||||
|
async stopVideoRecording() {
|
||||||
|
if (!this._screencastInfo)
|
||||||
|
throw new Error('No video recording in progress');
|
||||||
|
const screencastInfo = this._screencastInfo;
|
||||||
|
this._screencastInfo = undefined;
|
||||||
|
const screencast = Cc['@mozilla.org/juggler/screencast;1'].getService(Ci.nsIScreencastService);
|
||||||
|
const result = new Promise(resolve =>
|
||||||
|
Services.obs.addObserver(function onStopped(subject, topic, data) {
|
||||||
|
if (screencastInfo.videoSessionId != data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Services.obs.removeObserver(onStopped, 'juggler-screencast-stopped');
|
||||||
|
resolve();
|
||||||
|
}, 'juggler-screencast-stopped')
|
||||||
|
);
|
||||||
|
screencast.stopVideoRecording(screencastInfo.videoSessionId);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
screencastInfo() {
|
||||||
|
return this._screencastInfo;
|
||||||
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
this._disposed = true;
|
this._disposed = true;
|
||||||
this._browserContext.pages.delete(this);
|
this._browserContext.pages.delete(this);
|
||||||
@ -673,8 +719,14 @@ class BrowserContext {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
setScreencastOptions(options) {
|
async setScreencastOptions(options) {
|
||||||
this.screencastOptions = options;
|
this.screencastOptions = options;
|
||||||
|
if (!options)
|
||||||
|
return;
|
||||||
|
const promises = [];
|
||||||
|
for (const page of this.pages)
|
||||||
|
promises.push(page.startVideoRecording(options));
|
||||||
|
await Promise.all(promises);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
|
|
||||||
const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
|
const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
|
||||||
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||||
const {OS} = ChromeUtils.import("resource://gre/modules/osfile.jsm");
|
|
||||||
|
|
||||||
const Cc = Components.classes;
|
const Cc = Components.classes;
|
||||||
const Ci = Components.interfaces;
|
const Ci = Components.interfaces;
|
||||||
@ -91,7 +90,6 @@ class PageHandler {
|
|||||||
this._dialogs = new Map();
|
this._dialogs = new Map();
|
||||||
|
|
||||||
this._enabled = false;
|
this._enabled = false;
|
||||||
this._videoSessionId = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_onWorkerCreated({workerId, frameId, url}) {
|
_onWorkerCreated({workerId, frameId, url}) {
|
||||||
@ -132,24 +130,23 @@ class PageHandler {
|
|||||||
helper.on(this._pageTarget, 'crashed', () => {
|
helper.on(this._pageTarget, 'crashed', () => {
|
||||||
this._session.emitEvent('Page.crashed', {});
|
this._session.emitEvent('Page.crashed', {});
|
||||||
}),
|
}),
|
||||||
|
helper.on(this._pageTarget, 'screencastStarted', () => {
|
||||||
|
const info = this._pageTarget.screencastInfo();
|
||||||
|
this._session.emitEvent('Page.screencastStarted', { screencastId: '' + info.videoSessionId, file: info.file });
|
||||||
|
}),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const options = this._pageTarget.browserContext().screencastOptions;
|
const options = this._pageTarget.browserContext().screencastOptions;
|
||||||
if (options) {
|
if (options)
|
||||||
const file = OS.Path.join(options.dir, helper.generateId() + '.webm');
|
await this._pageTarget.startVideoRecording(options);
|
||||||
// On Mac the window may not yet be visible when TargetCreated and its
|
|
||||||
// NSWindow.windowNumber may be -1, so we wait until the window is known
|
|
||||||
// to be initialized and visible.
|
|
||||||
await this._pageTarget.windowReady();
|
|
||||||
await this.startVideoRecording(Object.assign({file}, options));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async dispose() {
|
async dispose() {
|
||||||
this._contentPage.dispose();
|
this._contentPage.dispose();
|
||||||
helper.removeListeners(this._eventListeners);
|
helper.removeListeners(this._eventListeners);
|
||||||
if (this._videoSessionId !== -1)
|
|
||||||
await this.stopVideoRecording().catch(e => dump(`stopVideoRecording failed:\n${e}\n`));
|
if (this._pageTarget.screencastInfo())
|
||||||
|
await this._pageTarget.stopVideoRecording().catch(e => dump(`stopVideoRecording failed:\n${e}\n`));
|
||||||
}
|
}
|
||||||
|
|
||||||
async setViewportSize({viewportSize}) {
|
async setViewportSize({viewportSize}) {
|
||||||
@ -303,38 +300,8 @@ class PageHandler {
|
|||||||
return await worker.sendMessage(JSON.parse(message));
|
return await worker.sendMessage(JSON.parse(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
startVideoRecording({file, width, height, scale}) {
|
|
||||||
if (width < 10 || width > 10000 || height < 10 || height > 10000)
|
|
||||||
throw new Error("Invalid size");
|
|
||||||
if (scale && (scale <= 0 || scale > 1))
|
|
||||||
throw new Error("Unsupported scale");
|
|
||||||
|
|
||||||
const screencast = Cc['@mozilla.org/juggler/screencast;1'].getService(Ci.nsIScreencastService);
|
|
||||||
const docShell = this._pageTarget._gBrowser.ownerGlobal.docShell;
|
|
||||||
// Exclude address bar and navigation control from the video.
|
|
||||||
const rect = this._pageTarget.linkedBrowser().getBoundingClientRect();
|
|
||||||
const devicePixelRatio = this._pageTarget._window.devicePixelRatio;
|
|
||||||
this._videoSessionId = screencast.startVideoRecording(docShell, file, width, height, scale || 0, devicePixelRatio * rect.top);
|
|
||||||
this._session.emitEvent('Page.screencastStarted', {screencastId: '' + this._videoSessionId, file});
|
|
||||||
}
|
|
||||||
|
|
||||||
async stopVideoRecording() {
|
async stopVideoRecording() {
|
||||||
if (this._videoSessionId === -1)
|
await this._pageTarget.stopVideoRecording();
|
||||||
throw new Error('No video recording in progress');
|
|
||||||
const videoSessionId = this._videoSessionId;
|
|
||||||
this._videoSessionId = -1;
|
|
||||||
const screencast = Cc['@mozilla.org/juggler/screencast;1'].getService(Ci.nsIScreencastService);
|
|
||||||
const result = new Promise(resolve =>
|
|
||||||
Services.obs.addObserver(function onStopped(subject, topic, data) {
|
|
||||||
if (videoSessionId != data)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Services.obs.removeObserver(onStopped, 'juggler-screencast-stopped');
|
|
||||||
resolve();
|
|
||||||
}, 'juggler-screencast-stopped')
|
|
||||||
);
|
|
||||||
screencast.stopVideoRecording(videoSessionId);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user