mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-14 21:53:35 +03:00
chore: align FFConnection
with CRConnection
(#27450)
This commit is contained in:
parent
293c85935a
commit
cba2fc0752
@ -25,13 +25,14 @@ import type { Page, PageBinding, PageDelegate } from '../page';
|
||||
import type { ConnectionTransport } from '../transport';
|
||||
import type * as types from '../types';
|
||||
import type * as channels from '@protocol/channels';
|
||||
import { ConnectionEvents, FFConnection } from './ffConnection';
|
||||
import { ConnectionEvents, FFConnection, type FFSession } from './ffConnection';
|
||||
import { FFPage } from './ffPage';
|
||||
import type { Protocol } from './protocol';
|
||||
import type { SdkObject } from '../instrumentation';
|
||||
|
||||
export class FFBrowser extends Browser {
|
||||
_connection: FFConnection;
|
||||
private _connection: FFConnection;
|
||||
readonly session: FFSession;
|
||||
readonly _ffPages: Map<string, FFPage>;
|
||||
readonly _contexts: Map<string, FFBrowserContext>;
|
||||
private _version = '';
|
||||
@ -46,7 +47,7 @@ export class FFBrowser extends Browser {
|
||||
if (Object.keys(kBandaidFirefoxUserPrefs).length)
|
||||
firefoxUserPrefs = { ...kBandaidFirefoxUserPrefs, ...firefoxUserPrefs };
|
||||
const promises: Promise<any>[] = [
|
||||
connection.send('Browser.enable', {
|
||||
browser.session.send('Browser.enable', {
|
||||
attachToDefaultContext: !!options.persistent,
|
||||
userPrefs: Object.entries(firefoxUserPrefs).map(([name, value]) => ({ name, value })),
|
||||
}),
|
||||
@ -57,7 +58,7 @@ export class FFBrowser extends Browser {
|
||||
promises.push((browser._defaultContext as FFBrowserContext)._initialize());
|
||||
}
|
||||
if (options.proxy)
|
||||
promises.push(browser._connection.send('Browser.setBrowserProxy', toJugglerProxyOptions(options.proxy)));
|
||||
promises.push(browser.session.send('Browser.setBrowserProxy', toJugglerProxyOptions(options.proxy)));
|
||||
await Promise.all(promises);
|
||||
return browser;
|
||||
}
|
||||
@ -65,18 +66,19 @@ export class FFBrowser extends Browser {
|
||||
constructor(parent: SdkObject, connection: FFConnection, options: BrowserOptions) {
|
||||
super(parent, options);
|
||||
this._connection = connection;
|
||||
this.session = connection.rootSession;
|
||||
this._ffPages = new Map();
|
||||
this._contexts = new Map();
|
||||
this._connection.on(ConnectionEvents.Disconnected, () => this._onDisconnect());
|
||||
this._connection.on('Browser.attachedToTarget', this._onAttachedToTarget.bind(this));
|
||||
this._connection.on('Browser.detachedFromTarget', this._onDetachedFromTarget.bind(this));
|
||||
this._connection.on('Browser.downloadCreated', this._onDownloadCreated.bind(this));
|
||||
this._connection.on('Browser.downloadFinished', this._onDownloadFinished.bind(this));
|
||||
this._connection.on('Browser.videoRecordingFinished', this._onVideoRecordingFinished.bind(this));
|
||||
this.session.on('Browser.attachedToTarget', this._onAttachedToTarget.bind(this));
|
||||
this.session.on('Browser.detachedFromTarget', this._onDetachedFromTarget.bind(this));
|
||||
this.session.on('Browser.downloadCreated', this._onDownloadCreated.bind(this));
|
||||
this.session.on('Browser.downloadFinished', this._onDownloadFinished.bind(this));
|
||||
this.session.on('Browser.videoRecordingFinished', this._onVideoRecordingFinished.bind(this));
|
||||
}
|
||||
|
||||
async _initVersion() {
|
||||
const result = await this._connection.send('Browser.getInfo');
|
||||
const result = await this.session.send('Browser.getInfo');
|
||||
this._version = result.version.substring(result.version.indexOf('/') + 1);
|
||||
this._userAgent = result.userAgent;
|
||||
}
|
||||
@ -88,7 +90,7 @@ export class FFBrowser extends Browser {
|
||||
async doCreateNewContext(options: channels.BrowserNewContextParams): Promise<BrowserContext> {
|
||||
if (options.isMobile)
|
||||
throw new Error('options.isMobile is not supported in Firefox');
|
||||
const { browserContextId } = await this._connection.send('Browser.createBrowserContext', { removeOnDetach: true });
|
||||
const { browserContextId } = await this.session.send('Browser.createBrowserContext', { removeOnDetach: true });
|
||||
const context = new FFBrowserContext(this, browserContextId, options);
|
||||
await context._initialize();
|
||||
this._contexts.set(browserContextId, context);
|
||||
@ -178,7 +180,7 @@ export class FFBrowserContext extends BrowserContext {
|
||||
const browserContextId = this._browserContextId;
|
||||
const promises: Promise<any>[] = [super._initialize()];
|
||||
if (this._options.acceptDownloads !== 'internal-browser-default') {
|
||||
promises.push(this._browser._connection.send('Browser.setDownloadOptions', {
|
||||
promises.push(this._browser.session.send('Browser.setDownloadOptions', {
|
||||
browserContextId,
|
||||
downloadOptions: {
|
||||
behavior: this._options.acceptDownloads === 'accept' ? 'saveToDisk' : 'cancel',
|
||||
@ -191,22 +193,22 @@ export class FFBrowserContext extends BrowserContext {
|
||||
viewportSize: { width: this._options.viewport.width, height: this._options.viewport.height },
|
||||
deviceScaleFactor: this._options.deviceScaleFactor || 1,
|
||||
};
|
||||
promises.push(this._browser._connection.send('Browser.setDefaultViewport', { browserContextId, viewport }));
|
||||
promises.push(this._browser.session.send('Browser.setDefaultViewport', { browserContextId, viewport }));
|
||||
}
|
||||
if (this._options.hasTouch)
|
||||
promises.push(this._browser._connection.send('Browser.setTouchOverride', { browserContextId, hasTouch: true }));
|
||||
promises.push(this._browser.session.send('Browser.setTouchOverride', { browserContextId, hasTouch: true }));
|
||||
if (this._options.userAgent)
|
||||
promises.push(this._browser._connection.send('Browser.setUserAgentOverride', { browserContextId, userAgent: this._options.userAgent }));
|
||||
promises.push(this._browser.session.send('Browser.setUserAgentOverride', { browserContextId, userAgent: this._options.userAgent }));
|
||||
if (this._options.bypassCSP)
|
||||
promises.push(this._browser._connection.send('Browser.setBypassCSP', { browserContextId, bypassCSP: true }));
|
||||
promises.push(this._browser.session.send('Browser.setBypassCSP', { browserContextId, bypassCSP: true }));
|
||||
if (this._options.ignoreHTTPSErrors)
|
||||
promises.push(this._browser._connection.send('Browser.setIgnoreHTTPSErrors', { browserContextId, ignoreHTTPSErrors: true }));
|
||||
promises.push(this._browser.session.send('Browser.setIgnoreHTTPSErrors', { browserContextId, ignoreHTTPSErrors: true }));
|
||||
if (this._options.javaScriptEnabled === false)
|
||||
promises.push(this._browser._connection.send('Browser.setJavaScriptDisabled', { browserContextId, javaScriptDisabled: true }));
|
||||
promises.push(this._browser.session.send('Browser.setJavaScriptDisabled', { browserContextId, javaScriptDisabled: true }));
|
||||
if (this._options.locale)
|
||||
promises.push(this._browser._connection.send('Browser.setLocaleOverride', { browserContextId, locale: this._options.locale }));
|
||||
promises.push(this._browser.session.send('Browser.setLocaleOverride', { browserContextId, locale: this._options.locale }));
|
||||
if (this._options.timezoneId)
|
||||
promises.push(this._browser._connection.send('Browser.setTimezoneOverride', { browserContextId, timezoneId: this._options.timezoneId }));
|
||||
promises.push(this._browser.session.send('Browser.setTimezoneOverride', { browserContextId, timezoneId: this._options.timezoneId }));
|
||||
if (this._options.extraHTTPHeaders || this._options.locale)
|
||||
promises.push(this.setExtraHTTPHeaders(this._options.extraHTTPHeaders || []));
|
||||
if (this._options.httpCredentials)
|
||||
@ -216,26 +218,26 @@ export class FFBrowserContext extends BrowserContext {
|
||||
if (this._options.offline)
|
||||
promises.push(this.setOffline(this._options.offline));
|
||||
if (this._options.colorScheme !== 'no-override') {
|
||||
promises.push(this._browser._connection.send('Browser.setColorScheme', {
|
||||
promises.push(this._browser.session.send('Browser.setColorScheme', {
|
||||
browserContextId,
|
||||
colorScheme: this._options.colorScheme !== undefined ? this._options.colorScheme : 'light',
|
||||
}));
|
||||
}
|
||||
if (this._options.reducedMotion !== 'no-override') {
|
||||
promises.push(this._browser._connection.send('Browser.setReducedMotion', {
|
||||
promises.push(this._browser.session.send('Browser.setReducedMotion', {
|
||||
browserContextId,
|
||||
reducedMotion: this._options.reducedMotion !== undefined ? this._options.reducedMotion : 'no-preference',
|
||||
}));
|
||||
}
|
||||
if (this._options.forcedColors !== 'no-override') {
|
||||
promises.push(this._browser._connection.send('Browser.setForcedColors', {
|
||||
promises.push(this._browser.session.send('Browser.setForcedColors', {
|
||||
browserContextId,
|
||||
forcedColors: this._options.forcedColors !== undefined ? this._options.forcedColors : 'none',
|
||||
}));
|
||||
}
|
||||
if (this._options.recordVideo) {
|
||||
promises.push(this._ensureVideosPath().then(() => {
|
||||
return this._browser._connection.send('Browser.setVideoRecordingOptions', {
|
||||
return this._browser.session.send('Browser.setVideoRecordingOptions', {
|
||||
// validateBrowserContextOptions ensures correct video size.
|
||||
options: {
|
||||
...this._options.recordVideo!.size!,
|
||||
@ -246,7 +248,7 @@ export class FFBrowserContext extends BrowserContext {
|
||||
}));
|
||||
}
|
||||
if (this._options.proxy) {
|
||||
promises.push(this._browser._connection.send('Browser.setContextProxy', {
|
||||
promises.push(this._browser.session.send('Browser.setContextProxy', {
|
||||
browserContextId: this._browserContextId,
|
||||
...toJugglerProxyOptions(this._options.proxy)
|
||||
}));
|
||||
@ -265,7 +267,7 @@ export class FFBrowserContext extends BrowserContext {
|
||||
|
||||
async newPageDelegate(): Promise<PageDelegate> {
|
||||
assertBrowserContextIsNotOwned(this);
|
||||
const { targetId } = await this._browser._connection.send('Browser.newPage', {
|
||||
const { targetId } = await this._browser.session.send('Browser.newPage', {
|
||||
browserContextId: this._browserContextId
|
||||
}).catch(e => {
|
||||
if (e.message.includes('Failed to override timezone'))
|
||||
@ -276,7 +278,7 @@ export class FFBrowserContext extends BrowserContext {
|
||||
}
|
||||
|
||||
async doGetCookies(urls: string[]): Promise<channels.NetworkCookie[]> {
|
||||
const { cookies } = await this._browser._connection.send('Browser.getCookies', { browserContextId: this._browserContextId });
|
||||
const { cookies } = await this._browser.session.send('Browser.getCookies', { browserContextId: this._browserContextId });
|
||||
return network.filterCookies(cookies.map(c => {
|
||||
const copy: any = { ... c };
|
||||
delete copy.size;
|
||||
@ -290,11 +292,11 @@ export class FFBrowserContext extends BrowserContext {
|
||||
...c,
|
||||
expires: c.expires === -1 ? undefined : c.expires,
|
||||
}));
|
||||
await this._browser._connection.send('Browser.setCookies', { browserContextId: this._browserContextId, cookies: cc });
|
||||
await this._browser.session.send('Browser.setCookies', { browserContextId: this._browserContextId, cookies: cc });
|
||||
}
|
||||
|
||||
async clearCookies() {
|
||||
await this._browser._connection.send('Browser.clearCookies', { browserContextId: this._browserContextId });
|
||||
await this._browser.session.send('Browser.clearCookies', { browserContextId: this._browserContextId });
|
||||
}
|
||||
|
||||
async doGrantPermissions(origin: string, permissions: string[]) {
|
||||
@ -310,17 +312,17 @@ export class FFBrowserContext extends BrowserContext {
|
||||
throw new Error('Unknown permission: ' + permission);
|
||||
return protocolPermission;
|
||||
});
|
||||
await this._browser._connection.send('Browser.grantPermissions', { origin: origin, browserContextId: this._browserContextId, permissions: filtered });
|
||||
await this._browser.session.send('Browser.grantPermissions', { origin: origin, browserContextId: this._browserContextId, permissions: filtered });
|
||||
}
|
||||
|
||||
async doClearPermissions() {
|
||||
await this._browser._connection.send('Browser.resetPermissions', { browserContextId: this._browserContextId });
|
||||
await this._browser.session.send('Browser.resetPermissions', { browserContextId: this._browserContextId });
|
||||
}
|
||||
|
||||
async setGeolocation(geolocation?: types.Geolocation): Promise<void> {
|
||||
verifyGeolocation(geolocation);
|
||||
this._options.geolocation = geolocation;
|
||||
await this._browser._connection.send('Browser.setGeolocationOverride', { browserContextId: this._browserContextId, geolocation: geolocation || null });
|
||||
await this._browser.session.send('Browser.setGeolocationOverride', { browserContextId: this._browserContextId, geolocation: geolocation || null });
|
||||
}
|
||||
|
||||
async setExtraHTTPHeaders(headers: types.HeadersArray): Promise<void> {
|
||||
@ -328,33 +330,33 @@ export class FFBrowserContext extends BrowserContext {
|
||||
let allHeaders = this._options.extraHTTPHeaders;
|
||||
if (this._options.locale)
|
||||
allHeaders = network.mergeHeaders([allHeaders, network.singleHeader('Accept-Language', this._options.locale)]);
|
||||
await this._browser._connection.send('Browser.setExtraHTTPHeaders', { browserContextId: this._browserContextId, headers: allHeaders });
|
||||
await this._browser.session.send('Browser.setExtraHTTPHeaders', { browserContextId: this._browserContextId, headers: allHeaders });
|
||||
}
|
||||
|
||||
async setUserAgent(userAgent: string | undefined): Promise<void> {
|
||||
await this._browser._connection.send('Browser.setUserAgentOverride', { browserContextId: this._browserContextId, userAgent: userAgent || null });
|
||||
await this._browser.session.send('Browser.setUserAgentOverride', { browserContextId: this._browserContextId, userAgent: userAgent || null });
|
||||
}
|
||||
|
||||
async setOffline(offline: boolean): Promise<void> {
|
||||
this._options.offline = offline;
|
||||
await this._browser._connection.send('Browser.setOnlineOverride', { browserContextId: this._browserContextId, override: offline ? 'offline' : 'online' });
|
||||
await this._browser.session.send('Browser.setOnlineOverride', { browserContextId: this._browserContextId, override: offline ? 'offline' : 'online' });
|
||||
}
|
||||
|
||||
async doSetHTTPCredentials(httpCredentials?: types.Credentials): Promise<void> {
|
||||
this._options.httpCredentials = httpCredentials;
|
||||
await this._browser._connection.send('Browser.setHTTPCredentials', { browserContextId: this._browserContextId, credentials: httpCredentials || null });
|
||||
await this._browser.session.send('Browser.setHTTPCredentials', { browserContextId: this._browserContextId, credentials: httpCredentials || null });
|
||||
}
|
||||
|
||||
async doAddInitScript(source: string) {
|
||||
await this._browser._connection.send('Browser.setInitScripts', { browserContextId: this._browserContextId, scripts: this.initScripts.map(script => ({ script })) });
|
||||
await this._browser.session.send('Browser.setInitScripts', { browserContextId: this._browserContextId, scripts: this.initScripts.map(script => ({ script })) });
|
||||
}
|
||||
|
||||
async doRemoveInitScripts() {
|
||||
await this._browser._connection.send('Browser.setInitScripts', { browserContextId: this._browserContextId, scripts: [] });
|
||||
await this._browser.session.send('Browser.setInitScripts', { browserContextId: this._browserContextId, scripts: [] });
|
||||
}
|
||||
|
||||
async doExposeBinding(binding: PageBinding) {
|
||||
await this._browser._connection.send('Browser.addBinding', { browserContextId: this._browserContextId, name: binding.name, script: binding.source });
|
||||
await this._browser.session.send('Browser.addBinding', { browserContextId: this._browserContextId, name: binding.name, script: binding.source });
|
||||
}
|
||||
|
||||
async doRemoveExposedBindings() {
|
||||
@ -364,20 +366,20 @@ export class FFBrowserContext extends BrowserContext {
|
||||
}
|
||||
|
||||
async doUpdateRequestInterception(): Promise<void> {
|
||||
await this._browser._connection.send('Browser.setRequestInterception', { browserContextId: this._browserContextId, enabled: !!this._requestInterceptor });
|
||||
await this._browser.session.send('Browser.setRequestInterception', { browserContextId: this._browserContextId, enabled: !!this._requestInterceptor });
|
||||
}
|
||||
|
||||
onClosePersistent() {}
|
||||
|
||||
override async clearCache(): Promise<void> {
|
||||
// Clearing only the context cache does not work: https://bugzilla.mozilla.org/show_bug.cgi?id=1819147
|
||||
await this._browser._connection.send('Browser.clearCache');
|
||||
await this._browser.session.send('Browser.clearCache');
|
||||
}
|
||||
|
||||
async doClose() {
|
||||
if (!this._browserContextId) {
|
||||
if (this._options.recordVideo) {
|
||||
await this._browser._connection.send('Browser.setVideoRecordingOptions', {
|
||||
await this._browser.session.send('Browser.setVideoRecordingOptions', {
|
||||
options: undefined,
|
||||
browserContextId: this._browserContextId
|
||||
});
|
||||
@ -385,13 +387,13 @@ export class FFBrowserContext extends BrowserContext {
|
||||
// Closing persistent context should close the browser.
|
||||
await this._browser.close();
|
||||
} else {
|
||||
await this._browser._connection.send('Browser.removeBrowserContext', { browserContextId: this._browserContextId });
|
||||
await this._browser.session.send('Browser.removeBrowserContext', { browserContextId: this._browserContextId });
|
||||
this._browser._contexts.delete(this._browserContextId);
|
||||
}
|
||||
}
|
||||
|
||||
async cancelDownload(uuid: string) {
|
||||
await this._browser._connection.send('Browser.cancelDownload', { uuid });
|
||||
await this._browser.session.send('Browser.cancelDownload', { uuid });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
import { EventEmitter } from 'events';
|
||||
import { assert } from '../../utils';
|
||||
import type { ConnectionTransport, ProtocolRequest, ProtocolResponse } from '../transport';
|
||||
import type { Protocol } from './protocol';
|
||||
import { rewriteErrorMessage } from '../../utils/stackTrace';
|
||||
@ -36,19 +35,14 @@ export const kBrowserCloseMessageId = -9999;
|
||||
|
||||
export class FFConnection extends EventEmitter {
|
||||
private _lastId: number;
|
||||
private _callbacks: Map<number, {resolve: (o: any) => void, reject: (e: ProtocolError) => void, error: ProtocolError, method: string}>;
|
||||
private _transport: ConnectionTransport;
|
||||
private readonly _protocolLogger: ProtocolLogger;
|
||||
private readonly _browserLogsCollector: RecentLogsCollector;
|
||||
_browserDisconnectedLogs: string | undefined;
|
||||
readonly rootSession: FFSession;
|
||||
readonly _sessions: Map<string, FFSession>;
|
||||
_closed: boolean;
|
||||
|
||||
override on: <T extends keyof Protocol.Events | symbol>(event: T, listener: (payload: T extends symbol ? any : Protocol.Events[T extends keyof Protocol.Events ? T : never]) => void) => this;
|
||||
override addListener: <T extends keyof Protocol.Events | symbol>(event: T, listener: (payload: T extends symbol ? any : Protocol.Events[T extends keyof Protocol.Events ? T : never]) => void) => this;
|
||||
override off: <T extends keyof Protocol.Events | symbol>(event: T, listener: (payload: T extends symbol ? any : Protocol.Events[T extends keyof Protocol.Events ? T : never]) => void) => this;
|
||||
override removeListener: <T extends keyof Protocol.Events | symbol>(event: T, listener: (payload: T extends symbol ? any : Protocol.Events[T extends keyof Protocol.Events ? T : never]) => void) => this;
|
||||
override once: <T extends keyof Protocol.Events | symbol>(event: T, listener: (payload: T extends symbol ? any : Protocol.Events[T extends keyof Protocol.Events ? T : never]) => void) => this;
|
||||
|
||||
constructor(transport: ConnectionTransport, protocolLogger: ProtocolLogger, browserLogsCollector: RecentLogsCollector) {
|
||||
super();
|
||||
this.setMaxListeners(0);
|
||||
@ -56,43 +50,20 @@ export class FFConnection extends EventEmitter {
|
||||
this._protocolLogger = protocolLogger;
|
||||
this._browserLogsCollector = browserLogsCollector;
|
||||
this._lastId = 0;
|
||||
this._callbacks = new Map();
|
||||
|
||||
this._sessions = new Map();
|
||||
this._closed = false;
|
||||
|
||||
this.on = super.on;
|
||||
this.addListener = super.addListener;
|
||||
this.off = super.removeListener;
|
||||
this.removeListener = super.removeListener;
|
||||
this.once = super.once;
|
||||
this.rootSession = new FFSession(this, '', message => this._rawSend(message));
|
||||
this._sessions.set('', this.rootSession);
|
||||
|
||||
this._transport.onmessage = this._onMessage.bind(this);
|
||||
// onclose should be set last, since it can be immediately called.
|
||||
this._transport.onclose = this._onClose.bind(this);
|
||||
}
|
||||
|
||||
async send<T extends keyof Protocol.CommandParameters>(
|
||||
method: T,
|
||||
params?: Protocol.CommandParameters[T]
|
||||
): Promise<Protocol.CommandReturnValues[T]> {
|
||||
this._checkClosed(method);
|
||||
const id = this.nextMessageId();
|
||||
this._rawSend({ id, method, params });
|
||||
return new Promise((resolve, reject) => {
|
||||
this._callbacks.set(id, { resolve, reject, error: new ProtocolError(false), method });
|
||||
});
|
||||
}
|
||||
|
||||
nextMessageId(): number {
|
||||
return ++this._lastId;
|
||||
}
|
||||
|
||||
_checkClosed(method: string) {
|
||||
if (this._closed)
|
||||
throw new ProtocolError(true, `${method}): Browser closed.` + helper.formatBrowserLogs(this._browserLogsCollector.recentLogs()));
|
||||
}
|
||||
|
||||
_rawSend(message: ProtocolRequest) {
|
||||
this._protocolLogger('send', message);
|
||||
this._transport.send(message);
|
||||
@ -102,36 +73,17 @@ export class FFConnection extends EventEmitter {
|
||||
this._protocolLogger('receive', message);
|
||||
if (message.id === kBrowserCloseMessageId)
|
||||
return;
|
||||
if (message.sessionId) {
|
||||
const session = this._sessions.get(message.sessionId);
|
||||
if (session)
|
||||
session.dispatchMessage(message);
|
||||
} else if (message.id) {
|
||||
const callback = this._callbacks.get(message.id);
|
||||
// Callbacks could be all rejected if someone has called `.dispose()`.
|
||||
if (callback) {
|
||||
this._callbacks.delete(message.id);
|
||||
if (message.error)
|
||||
callback.reject(createProtocolError(callback.error, callback.method, message.error));
|
||||
else
|
||||
callback.resolve(message.result);
|
||||
}
|
||||
} else {
|
||||
Promise.resolve().then(() => this.emit(message.method!, message.params));
|
||||
}
|
||||
const session = this._sessions.get(message.sessionId || '');
|
||||
if (session)
|
||||
session.dispatchMessage(message);
|
||||
}
|
||||
|
||||
_onClose() {
|
||||
this._closed = true;
|
||||
this._transport.onmessage = undefined;
|
||||
this._transport.onclose = undefined;
|
||||
const formattedBrowserLogs = helper.formatBrowserLogs(this._browserLogsCollector.recentLogs());
|
||||
for (const callback of this._callbacks.values()) {
|
||||
const error = rewriteErrorMessage(callback.error, `Protocol error (${callback.method}): Browser closed.` + formattedBrowserLogs);
|
||||
error.sessionClosed = true;
|
||||
callback.reject(error);
|
||||
}
|
||||
this._callbacks.clear();
|
||||
this._browserDisconnectedLogs = helper.formatBrowserLogs(this._browserLogsCollector.recentLogs());
|
||||
this.rootSession.dispose();
|
||||
Promise.resolve().then(() => this.emit(ConnectionEvents.Disconnected));
|
||||
}
|
||||
|
||||
@ -179,15 +131,24 @@ export class FFSession extends EventEmitter {
|
||||
this._crashed = true;
|
||||
}
|
||||
|
||||
private _closedErrorMessage() {
|
||||
if (this._crashed)
|
||||
return 'Target crashed';
|
||||
if (this._connection._browserDisconnectedLogs !== undefined)
|
||||
return `Browser closed.` + this._connection._browserDisconnectedLogs;
|
||||
if (this._disposed)
|
||||
return `Target closed`;
|
||||
if (this._connection._closed)
|
||||
return 'Browser closed';
|
||||
}
|
||||
|
||||
async send<T extends keyof Protocol.CommandParameters>(
|
||||
method: T,
|
||||
params?: Protocol.CommandParameters[T]
|
||||
): Promise<Protocol.CommandReturnValues[T]> {
|
||||
if (this._crashed)
|
||||
throw new ProtocolError(true, 'Target crashed');
|
||||
this._connection._checkClosed(method);
|
||||
if (this._disposed)
|
||||
throw new ProtocolError(true, 'Target closed');
|
||||
const closedErrorMessage = this._closedErrorMessage();
|
||||
if (closedErrorMessage)
|
||||
throw new ProtocolError(true, closedErrorMessage);
|
||||
const id = this._connection.nextMessageId();
|
||||
this._rawSend({ method, params, id });
|
||||
return new Promise((resolve, reject) => {
|
||||
@ -200,27 +161,30 @@ export class FFSession extends EventEmitter {
|
||||
}
|
||||
|
||||
dispatchMessage(object: ProtocolResponse) {
|
||||
if (object.id && this._callbacks.has(object.id)) {
|
||||
const callback = this._callbacks.get(object.id)!;
|
||||
this._callbacks.delete(object.id);
|
||||
if (object.error)
|
||||
callback.reject(createProtocolError(callback.error, callback.method, object.error));
|
||||
else
|
||||
callback.resolve(object.result);
|
||||
if (object.id) {
|
||||
const callback = this._callbacks.get(object.id);
|
||||
// Callbacks could be all rejected if someone has called `.dispose()`.
|
||||
if (callback) {
|
||||
this._callbacks.delete(object.id);
|
||||
if (object.error)
|
||||
callback.reject(createProtocolError(callback.error, callback.method, object.error));
|
||||
else
|
||||
callback.resolve(object.result);
|
||||
}
|
||||
} else {
|
||||
assert(!object.id);
|
||||
Promise.resolve().then(() => this.emit(object.method!, object.params));
|
||||
}
|
||||
}
|
||||
|
||||
dispose() {
|
||||
for (const callback of this._callbacks.values()) {
|
||||
callback.error.sessionClosed = true;
|
||||
callback.reject(rewriteErrorMessage(callback.error, 'Target closed'));
|
||||
}
|
||||
this._callbacks.clear();
|
||||
this._disposed = true;
|
||||
this._connection._sessions.delete(this._sessionId);
|
||||
const errorMessage = this._closedErrorMessage()!;
|
||||
for (const callback of this._callbacks.values()) {
|
||||
callback.error.sessionClosed = true;
|
||||
callback.reject(rewriteErrorMessage(callback.error, errorMessage));
|
||||
}
|
||||
this._callbacks.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user