chore: remove connection / session redundancy (#51)

This commit is contained in:
Pavel Feldman 2019-11-22 10:05:32 -08:00 committed by Andrey Lushnikov
parent 7783400156
commit c26166203e
4 changed files with 30 additions and 57 deletions

View File

@ -47,15 +47,13 @@ export class Browser extends EventEmitter {
defaultViewport: Viewport | null,
process: childProcess.ChildProcess | null,
closeCallback?: (() => Promise<void>)) {
const session = await connection.createBrowserSession();
const browser = new Browser(connection, session, contextIds, ignoreHTTPSErrors, defaultViewport, process, closeCallback);
await session.send('Target.setDiscoverTargets', {discover: true});
const browser = new Browser(connection, contextIds, ignoreHTTPSErrors, defaultViewport, process, closeCallback);
await connection.rootSession.send('Target.setDiscoverTargets', { discover: true });
return browser;
}
constructor(
connection: Connection,
client: CDPSession,
contextIds: string[],
ignoreHTTPSErrors: boolean,
defaultViewport: Viewport | null,
@ -63,7 +61,7 @@ export class Browser extends EventEmitter {
closeCallback?: (() => Promise<void>)) {
super();
this._connection = connection;
this._client = client;
this._client = connection.rootSession;
this._ignoreHTTPSErrors = ignoreHTTPSErrors;
this._defaultViewport = defaultViewport;
this._process = process;
@ -151,13 +149,17 @@ export class Browser extends EventEmitter {
}
async _createPageInContext(contextId: string | null): Promise<Page> {
const {targetId} = await this._connection.send('Target.createTarget', {url: 'about:blank', browserContextId: contextId || undefined});
const { targetId } = await this._client.send('Target.createTarget', { url: 'about:blank', browserContextId: contextId || undefined });
const target = await this._targets.get(targetId);
assert(await target._initializedPromise, 'Failed to create target for page');
const page = await target.page();
return page;
}
async _closeTarget(target: Target) {
await this._client.send('Target.closeTarget', { targetId: target._targetId });
}
targets(): Target[] {
return Array.from(this._targets.values()).filter(target => target._isInitialized);
}
@ -222,6 +224,6 @@ export class Browser extends EventEmitter {
}
_getVersion(): Promise<any> {
return this._connection.send('Browser.getVersion');
return this._client.send('Browser.getVersion');
}
}

View File

@ -30,16 +30,11 @@ export const ConnectionEvents = {
export class Connection extends EventEmitter {
private _url: string;
private _lastId = 0;
private _callbacks = new Map<number, {resolve:(o: any) => void, reject: (e: Error) => void, error: Error, method: string}>();
private _delay: number;
private _transport: ConnectionTransport;
private _sessions = new Map<string, CDPSession>();
readonly rootSession: CDPSession;
_closed = false;
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;
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;
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;
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;
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(url: string, transport: ConnectionTransport, delay: number | undefined = 0) {
super();
@ -49,6 +44,8 @@ export class Connection extends EventEmitter {
this._transport = transport;
this._transport.onmessage = this._onMessage.bind(this);
this._transport.onclose = this._onClose.bind(this);
this.rootSession = new CDPSession(this, 'browser', '');
this._sessions.set('', this.rootSession);
}
static fromSession(session: CDPSession): Connection {
@ -63,21 +60,14 @@ export class Connection extends EventEmitter {
return this._url;
}
send<T extends keyof Protocol.CommandParameters>(
method: T,
params?: Protocol.CommandParameters[T]
): Promise<Protocol.CommandReturnValues[T]> {
const id = this._rawSend({method, params});
return new Promise((resolve, reject) => {
this._callbacks.set(id, {resolve, reject, error: new Error(), method});
});
}
_rawSend(message: any): number {
_rawSend(sessionId: string, message: any): number {
const id = ++this._lastId;
message = JSON.stringify(Object.assign({}, message, {id}));
debugProtocol('SEND ► ' + message);
this._transport.send(message);
message.id = id;
if (sessionId)
message.sessionId = sessionId;
const data = JSON.stringify(message);
debugProtocol('SEND ► ' + data);
this._transport.send(data);
return id;
}
@ -97,23 +87,9 @@ export class Connection extends EventEmitter {
this._sessions.delete(object.params.sessionId);
}
}
if (object.sessionId) {
const session = this._sessions.get(object.sessionId);
if (session)
session._onMessage(object);
} else 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));
else
callback.resolve(object.result);
}
} else {
this.emit(object.method, object.params);
}
const session = this._sessions.get(object.sessionId || '');
if (session)
session._onMessage(object);
}
_onClose() {
@ -122,9 +98,6 @@ export class Connection extends EventEmitter {
this._closed = true;
this._transport.onmessage = null;
this._transport.onclose = null;
for (const callback of this._callbacks.values())
callback.reject(rewriteError(callback.error, `Protocol error (${callback.method}): Target closed.`));
this._callbacks.clear();
for (const session of this._sessions.values())
session._onClosed();
this._sessions.clear();
@ -137,15 +110,13 @@ export class Connection extends EventEmitter {
}
async createSession(targetInfo: Protocol.Target.TargetInfo): Promise<CDPSession> {
const {sessionId} = await this.send('Target.attachToTarget', {targetId: targetInfo.targetId, flatten: true});
const { sessionId } = await this.rootSession.send('Target.attachToTarget', { targetId: targetInfo.targetId, flatten: true });
return this._sessions.get(sessionId);
}
async createBrowserSession(): Promise<CDPSession> {
const { sessionId } = await this.send('Target.attachToBrowserTarget');
const session = new CDPSession(this, 'browser', sessionId);
this._sessions.set(sessionId, session);
return session;
const { sessionId } = await this.rootSession.send('Target.attachToBrowserTarget');
return this._sessions.get(sessionId);
}
}
@ -177,7 +148,7 @@ export class CDPSession extends EventEmitter {
): Promise<Protocol.CommandReturnValues[T]> {
if (!this._connection)
return Promise.reject(new Error(`Protocol error (${method}): Session closed. Most likely the ${this._targetType} has been closed.`));
const id = this._connection._rawSend({sessionId: this._sessionId, method, params});
const id = this._connection._rawSend(this._sessionId, { method, params });
return new Promise((resolve, reject) => {
this._callbacks.set(id, {resolve, reject, error: new Error(), method});
});
@ -200,7 +171,7 @@ export class CDPSession extends EventEmitter {
async detach() {
if (!this._connection)
throw new Error(`Session already detached. Most likely the ${this._targetType} has been closed.`);
await this._connection.send('Target.detachFromTarget', {sessionId: this._sessionId});
await this._connection.rootSession.send('Target.detachFromTarget', { sessionId: this._sessionId });
}
_onClosed() {

View File

@ -188,7 +188,7 @@ export class Launcher {
killChrome();
} else if (connection) {
// Attempt to close chrome gracefully
connection.send('Browser.close').catch(error => {
connection.rootSession.send('Browser.close').catch(error => {
debugError(error);
killChrome();
});
@ -273,7 +273,7 @@ export class Launcher {
connection = new Connection(connectionURL, connectionTransport, slowMo);
}
const {browserContextIds} = await connection.send('Target.getBrowserContexts');
const { browserContextIds } = await connection.rootSession.send('Target.getBrowserContexts');
return Browser.create(connection, browserContextIds, ignoreHTTPSErrors, defaultViewport, null, () => connection.send('Browser.close').catch(debugError));
}

View File

@ -678,7 +678,7 @@ export class Page extends EventEmitter {
if (runBeforeUnload) {
await this._client.send('Page.close');
} else {
await this._client._connection.send('Target.closeTarget', { targetId: this._target._targetId });
await this.browser()._closeTarget(this._target);
await this._target._isClosedPromise;
}
}