chore: emit target configuration via CDP session (#10794)

This commit is contained in:
Alex Rudenko 2023-08-29 10:52:47 +02:00 committed by GitHub
parent 0eb5e93890
commit 599c0694ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 24 additions and 126 deletions

View File

@ -16,6 +16,6 @@
export const testChromeBuildId = '113.0.5672.0'; export const testChromeBuildId = '113.0.5672.0';
export const testChromiumBuildId = '1083080'; export const testChromiumBuildId = '1083080';
export const testFirefoxBuildId = '118.0a1'; export const testFirefoxBuildId = '119.0a1';
export const testChromeDriverBuildId = '115.0.5763.0'; export const testChromeDriverBuildId = '115.0.5763.0';
export const testChromeHeadlessShellBuildId = '118.0.5950.0'; export const testChromeHeadlessShellBuildId = '118.0.5950.0';

View File

@ -25,7 +25,6 @@ import {CDPSession, CDPSessionEmittedEvents, Connection} from './Connection.js';
import {EventEmitter} from './EventEmitter.js'; import {EventEmitter} from './EventEmitter.js';
import {InitializationStatus, CDPTarget} from './Target.js'; import {InitializationStatus, CDPTarget} from './Target.js';
import { import {
TargetInterceptor,
TargetFactory, TargetFactory,
TargetManager, TargetManager,
TargetManagerEmittedEvents, TargetManagerEmittedEvents,
@ -80,11 +79,6 @@ export class ChromeTargetManager extends EventEmitter implements TargetManager {
#targetFilterCallback: TargetFilterCallback | undefined; #targetFilterCallback: TargetFilterCallback | undefined;
#targetFactory: TargetFactory; #targetFactory: TargetFactory;
#targetInterceptors = new WeakMap<
CDPSession | Connection,
TargetInterceptor[]
>();
#attachedToTargetListenersBySession = new WeakMap< #attachedToTargetListenersBySession = new WeakMap<
CDPSession | Connection, CDPSession | Connection,
(event: Protocol.Target.AttachedToTargetEvent) => Promise<void> (event: Protocol.Target.AttachedToTargetEvent) => Promise<void>
@ -197,28 +191,6 @@ export class ChromeTargetManager extends EventEmitter implements TargetManager {
return result; return result;
} }
addTargetInterceptor(
session: CDPSession | Connection,
interceptor: TargetInterceptor
): void {
const interceptors = this.#targetInterceptors.get(session) || [];
interceptors.push(interceptor);
this.#targetInterceptors.set(session, interceptors);
}
removeTargetInterceptor(
client: CDPSession | Connection,
interceptor: TargetInterceptor
): void {
const interceptors = this.#targetInterceptors.get(client) || [];
this.#targetInterceptors.set(
client,
interceptors.filter(currentInterceptor => {
return currentInterceptor !== interceptor;
})
);
}
#setupAttachmentListeners(session: CDPSession | Connection): void { #setupAttachmentListeners(session: CDPSession | Connection): void {
const listener = (event: Protocol.Target.AttachedToTargetEvent) => { const listener = (event: Protocol.Target.AttachedToTargetEvent) => {
return this.#onAttachedToTarget(session, event); return this.#onAttachedToTarget(session, event);
@ -257,7 +229,6 @@ export class ChromeTargetManager extends EventEmitter implements TargetManager {
#onSessionDetached = (session: CDPSession) => { #onSessionDetached = (session: CDPSession) => {
this.#removeAttachmentListeners(session); this.#removeAttachmentListeners(session);
this.#targetInterceptors.delete(session);
}; };
#onTargetCreated = async (event: Protocol.Target.TargetCreatedEvent) => { #onTargetCreated = async (event: Protocol.Target.TargetCreatedEvent) => {
@ -392,11 +363,11 @@ export class ChromeTargetManager extends EventEmitter implements TargetManager {
return; return;
} }
const existingTarget = this.#attachedTargetsByTargetId.has( const isExistingTarget = this.#attachedTargetsByTargetId.has(
targetInfo.targetId targetInfo.targetId
); );
const target = existingTarget const target = isExistingTarget
? this.#attachedTargetsByTargetId.get(targetInfo.targetId)! ? this.#attachedTargetsByTargetId.get(targetInfo.targetId)!
: this.#targetFactory( : this.#targetFactory(
targetInfo, targetInfo,
@ -411,13 +382,13 @@ export class ChromeTargetManager extends EventEmitter implements TargetManager {
return; return;
} }
if (!existingTarget) { if (!isExistingTarget) {
target._initialize(); target._initialize();
} }
this.#setupAttachmentListeners(session); this.#setupAttachmentListeners(session);
if (existingTarget) { if (isExistingTarget) {
this.#attachedTargetsBySessionId.set( this.#attachedTargetsBySessionId.set(
session.id(), session.id(),
this.#attachedTargetsByTargetId.get(targetInfo.targetId)! this.#attachedTargetsByTargetId.get(targetInfo.targetId)!
@ -427,23 +398,10 @@ export class ChromeTargetManager extends EventEmitter implements TargetManager {
this.#attachedTargetsBySessionId.set(session.id(), target); this.#attachedTargetsBySessionId.set(session.id(), target);
} }
for (const interceptor of this.#targetInterceptors.get(parentSession) || parentSession.emit(CDPSessionEmittedEvents.Ready, session);
[]) {
if (!(parentSession instanceof Connection)) {
// Sanity check: if parent session is not a connection, it should be
// present in #attachedTargetsBySessionId.
assert(this.#attachedTargetsBySessionId.has(parentSession.id()));
}
interceptor(
target,
parentSession instanceof Connection
? null
: this.#attachedTargetsBySessionId.get(parentSession.id())!
);
}
this.#targetsIdsForInit.delete(target._targetId); this.#targetsIdsForInit.delete(target._targetId);
if (!existingTarget && isTargetExposed(target)) { if (!isExistingTarget && isTargetExposed(target)) {
this.emit(TargetManagerEmittedEvents.TargetAvailable, target); this.emit(TargetManagerEmittedEvents.TargetAvailable, target);
} }
this.#finishInitializationIfReady(); this.#finishInitializationIfReady();

View File

@ -431,6 +431,11 @@ export interface CDPSessionOnMessageObject {
export const CDPSessionEmittedEvents = { export const CDPSessionEmittedEvents = {
Disconnected: Symbol('CDPSession.Disconnected'), Disconnected: Symbol('CDPSession.Disconnected'),
Swapped: Symbol('CDPSession.Swapped'), Swapped: Symbol('CDPSession.Swapped'),
/**
* Emitted when the session is ready to be configured during the auto-attach
* process. Right after the event is handled, the session will be resumed.
*/
Ready: Symbol('CDPSession.Ready'),
} as const; } as const;
/** /**

View File

@ -20,12 +20,11 @@ import {TargetFilterCallback} from '../api/Browser.js';
import {assert} from '../util/assert.js'; import {assert} from '../util/assert.js';
import {Deferred} from '../util/Deferred.js'; import {Deferred} from '../util/Deferred.js';
import {CDPSession, Connection} from './Connection.js'; import {CDPSession, CDPSessionEmittedEvents, Connection} from './Connection.js';
import {EventEmitter} from './EventEmitter.js'; import {EventEmitter} from './EventEmitter.js';
import {CDPTarget} from './Target.js'; import {CDPTarget} from './Target.js';
import { import {
TargetFactory, TargetFactory,
TargetInterceptor,
TargetManagerEmittedEvents, TargetManagerEmittedEvents,
TargetManager, TargetManager,
} from './TargetManager.js'; } from './TargetManager.js';
@ -79,11 +78,6 @@ export class FirefoxTargetManager
#targetFilterCallback: TargetFilterCallback | undefined; #targetFilterCallback: TargetFilterCallback | undefined;
#targetFactory: TargetFactory; #targetFactory: TargetFactory;
#targetInterceptors = new WeakMap<
CDPSession | Connection,
TargetInterceptor[]
>();
#attachedToTargetListenersBySession = new WeakMap< #attachedToTargetListenersBySession = new WeakMap<
CDPSession | Connection, CDPSession | Connection,
(event: Protocol.Target.AttachedToTargetEvent) => Promise<void> (event: Protocol.Target.AttachedToTargetEvent) => Promise<void>
@ -108,28 +102,6 @@ export class FirefoxTargetManager
this.setupAttachmentListeners(this.#connection); this.setupAttachmentListeners(this.#connection);
} }
addTargetInterceptor(
client: CDPSession | Connection,
interceptor: TargetInterceptor
): void {
const interceptors = this.#targetInterceptors.get(client) || [];
interceptors.push(interceptor);
this.#targetInterceptors.set(client, interceptors);
}
removeTargetInterceptor(
client: CDPSession | Connection,
interceptor: TargetInterceptor
): void {
const interceptors = this.#targetInterceptors.get(client) || [];
this.#targetInterceptors.set(
client,
interceptors.filter(currentInterceptor => {
return currentInterceptor !== interceptor;
})
);
}
setupAttachmentListeners(session: CDPSession | Connection): void { setupAttachmentListeners(session: CDPSession | Connection): void {
const listener = (event: Protocol.Target.AttachedToTargetEvent) => { const listener = (event: Protocol.Target.AttachedToTargetEvent) => {
return this.#onAttachedToTarget(session, event); return this.#onAttachedToTarget(session, event);
@ -141,7 +113,6 @@ export class FirefoxTargetManager
#onSessionDetached = (session: CDPSession) => { #onSessionDetached = (session: CDPSession) => {
this.removeSessionListeners(session); this.removeSessionListeners(session);
this.#targetInterceptors.delete(session);
this.#availableTargetsBySessionId.delete(session.id()); this.#availableTargetsBySessionId.delete(session.id());
}; };
@ -236,17 +207,7 @@ export class FirefoxTargetManager
this.#availableTargetsByTargetId.get(targetInfo.targetId)! this.#availableTargetsByTargetId.get(targetInfo.targetId)!
); );
for (const hook of this.#targetInterceptors.get(parentSession) || []) { parentSession.emit(CDPSessionEmittedEvents.Ready, session);
if (!(parentSession instanceof Connection)) {
assert(this.#availableTargetsBySessionId.has(parentSession.id()));
}
await hook(
target,
parentSession instanceof Connection
? null
: this.#availableTargetsBySessionId.get(parentSession.id())!
);
}
}; };
#finishInitializationIfReady(targetId: string): void { #finishInitializationIfReady(targetId: string): void {

View File

@ -332,9 +332,7 @@ export class CDPPage extends Page {
} }
#setupEventListeners() { #setupEventListeners() {
this.#target this.#client.on(CDPSessionEmittedEvents.Ready, this.#onAttachedToTarget);
._targetManager()
.addTargetInterceptor(this.#client, this.#onAttachedToTarget);
this.#target this.#target
._targetManager() ._targetManager()
@ -355,9 +353,10 @@ export class CDPPage extends Page {
this.#target._isClosedDeferred this.#target._isClosedDeferred
.valueOrThrow() .valueOrThrow()
.then(() => { .then(() => {
this.#target this.#client.off(
._targetManager() CDPSessionEmittedEvents.Ready,
.removeTargetInterceptor(this.#client, this.#onAttachedToTarget); this.#onAttachedToTarget
);
this.#target this.#target
._targetManager() ._targetManager()
@ -382,28 +381,19 @@ export class CDPPage extends Page {
this.emit(PageEmittedEvents.WorkerDestroyed, worker); this.emit(PageEmittedEvents.WorkerDestroyed, worker);
}; };
#onAttachedToTarget = (createdTarget: CDPTarget) => { #onAttachedToTarget = (session: CDPSessionImpl) => {
this.#frameManager.onAttachedToTarget(createdTarget); this.#frameManager.onAttachedToTarget(session._target());
if (createdTarget._getTargetInfo().type === 'worker') { if (session._target()._getTargetInfo().type === 'worker') {
const session = createdTarget._session();
assert(session);
const worker = new WebWorker( const worker = new WebWorker(
session, session,
createdTarget.url(), session._target().url(),
this.#addConsoleMessage.bind(this), this.#addConsoleMessage.bind(this),
this.#handleException.bind(this) this.#handleException.bind(this)
); );
this.#workers.set(session.id(), worker); this.#workers.set(session.id(), worker);
this.emit(PageEmittedEvents.WorkerCreated, worker); this.emit(PageEmittedEvents.WorkerCreated, worker);
} }
if (createdTarget._session()) { session.on(CDPSessionEmittedEvents.Ready, this.#onAttachedToTarget);
this.#target
._targetManager()
.addTargetInterceptor(
createdTarget._session()!,
this.#onAttachedToTarget
);
}
}; };
async #initialize(): Promise<void> { async #initialize(): Promise<void> {

View File

@ -29,14 +29,6 @@ export type TargetFactory = (
parentSession?: CDPSession parentSession?: CDPSession
) => CDPTarget; ) => CDPTarget;
/**
* @internal
*/
export type TargetInterceptor = (
createdTarget: CDPTarget,
parentTarget: CDPTarget | null
) => void;
/** /**
* TargetManager encapsulates all interactions with CDP targets and is * TargetManager encapsulates all interactions with CDP targets and is
* responsible for coordinating the configuration of targets with the rest of * responsible for coordinating the configuration of targets with the rest of
@ -52,14 +44,6 @@ export interface TargetManager extends EventEmitter {
getAvailableTargets(): Map<string, CDPTarget>; getAvailableTargets(): Map<string, CDPTarget>;
initialize(): Promise<void>; initialize(): Promise<void>;
dispose(): void; dispose(): void;
addTargetInterceptor(
session: CDPSession,
interceptor: TargetInterceptor
): void;
removeTargetInterceptor(
session: CDPSession,
interceptor: TargetInterceptor
): void;
} }
/** /**