From 744af78dc263c136a0590953fc2afb96f2a04f24 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Fri, 28 Aug 2020 10:23:02 -0700 Subject: [PATCH] feat(rpc): simplify browser name detection on the client side (#3670) --- src/browserServerImpl.ts | 4 +--- src/client/browser.ts | 3 --- src/client/connection.ts | 25 ++++++++------------- src/dispatchers/browserContextDispatcher.ts | 4 +++- src/dispatchers/browserDispatcher.ts | 8 ++++++- src/protocol/channels.ts | 5 ++++- src/protocol/protocol.yml | 4 ++++ 7 files changed, 28 insertions(+), 25 deletions(-) diff --git a/src/browserServerImpl.ts b/src/browserServerImpl.ts index 9ef52b5535..99c60d769e 100644 --- a/src/browserServerImpl.ts +++ b/src/browserServerImpl.ts @@ -22,7 +22,6 @@ import { Browser } from './server/browser'; import { ChildProcess } from 'child_process'; import { EventEmitter } from 'ws'; import { DispatcherScope, DispatcherConnection } from './dispatchers/dispatcher'; -import { BrowserTypeDispatcher } from './dispatchers/browserTypeDispatcher'; import { BrowserDispatcher } from './dispatchers/browserDispatcher'; import { BrowserContextDispatcher } from './dispatchers/browserContextDispatcher'; import { BrowserNewContextParams, BrowserContextChannel } from './protocol/channels'; @@ -106,8 +105,7 @@ export class BrowserServerImpl extends EventEmitter implements BrowserServer { connection.dispatch(JSON.parse(Buffer.from(message).toString())); }); socket.on('error', () => {}); - const browserType = new BrowserTypeDispatcher(connection.rootDispatcher(), this._browserType); - const browser = new ConnectedBrowser(browserType._scope, this._browser); + const browser = new ConnectedBrowser(connection.rootDispatcher(), this._browser); socket.on('close', () => { // Avoid sending any more messages over closed socket. connection.onmessage = () => {}; diff --git a/src/client/browser.ts b/src/client/browser.ts index 80926b14b7..84c0865af9 100644 --- a/src/client/browser.ts +++ b/src/client/browser.ts @@ -19,7 +19,6 @@ import { BrowserContext } from './browserContext'; import { Page } from './page'; import { ChannelOwner } from './channelOwner'; import { Events } from './events'; -import { BrowserType } from './browserType'; import { BrowserContextOptions } from './types'; import { validateHeaders } from './network'; import { headersObjectToArray } from '../utils/utils'; @@ -29,7 +28,6 @@ export class Browser extends ChannelOwner; - readonly _browserType: BrowserType; _isRemote = false; static from(browser: channels.BrowserChannel): Browser { @@ -42,7 +40,6 @@ export class Browser extends ChannelOwner this._didClose()); this._closedPromise = new Promise(f => this.once(Events.Browser.Disconnected, f)); } diff --git a/src/client/connection.ts b/src/client/connection.ts index 11bab69ea4..b6604f7cb8 100644 --- a/src/client/connection.ts +++ b/src/client/connection.ts @@ -132,33 +132,26 @@ export class Connection { case 'BindingCall': result = new BindingCall(parent, type, guid, initializer); break; - case 'Browser': - if ((parent as BrowserType).name() === 'chromium') + case 'Browser': { + const browserName = (initializer as channels.BrowserInitializer).name; + if (browserName === 'chromium') result = new ChromiumBrowser(parent, type, guid, initializer); - else if ((parent as BrowserType).name() === 'webkit') + else if (browserName === 'webkit') result = new WebKitBrowser(parent, type, guid, initializer); - else if ((parent as BrowserType).name() === 'firefox') + else if (browserName === 'firefox') result = new FirefoxBrowser(parent, type, guid, initializer); else result = new Browser(parent, type, guid, initializer); break; - case 'BrowserContext': - let browserName = ''; - if (parent instanceof ElectronApplication) { - // Launching electron produces ElectronApplication parent for BrowserContext. - browserName = 'electron'; - } else if (parent instanceof Browser) { - // Launching a browser produces Browser parent for BrowserContext. - browserName = parent._browserType.name(); - } else { - // Launching persistent context produces BrowserType parent for BrowserContext. - browserName = (parent as BrowserType).name(); - } + } + case 'BrowserContext': { + const browserName = (initializer as channels.BrowserContextInitializer).browserName; if (browserName === 'chromium') result = new ChromiumBrowserContext(parent, type, guid, initializer); else result = new BrowserContext(parent, type, guid, initializer, browserName); break; + } case 'BrowserType': result = new BrowserType(parent, type, guid, initializer); break; diff --git a/src/dispatchers/browserContextDispatcher.ts b/src/dispatchers/browserContextDispatcher.ts index 8e458b9dd3..eb79f224ec 100644 --- a/src/dispatchers/browserContextDispatcher.ts +++ b/src/dispatchers/browserContextDispatcher.ts @@ -26,7 +26,7 @@ export class BrowserContextDispatcher extends Dispatcher { + if (this._object._browser._options.name !== 'chromium') + throw new Error(`CDP session is only available in Chromium`); const crBrowserContext = this._object as CRBrowserContext; return { session: new CDPSessionDispatcher(this._scope, await crBrowserContext.newCDPSession((params.page as PageDispatcher)._object)) }; } diff --git a/src/dispatchers/browserDispatcher.ts b/src/dispatchers/browserDispatcher.ts index 4d0f3b0ac2..edde7e05b7 100644 --- a/src/dispatchers/browserDispatcher.ts +++ b/src/dispatchers/browserDispatcher.ts @@ -24,7 +24,7 @@ import { PageDispatcher } from './pageDispatcher'; export class BrowserDispatcher extends Dispatcher implements channels.BrowserChannel { constructor(scope: DispatcherScope, browser: Browser, guid?: string) { - super(scope, browser, 'Browser', { version: browser.version() }, true, guid); + super(scope, browser, 'Browser', { version: browser.version(), name: browser._options.name }, true, guid); browser.on(Browser.Events.Disconnected, () => this._didClose()); } @@ -42,16 +42,22 @@ export class BrowserDispatcher extends Dispatcher { + if (this._object._options.name !== 'chromium') + throw new Error(`CDP session is only available in Chromium`); const crBrowser = this._object as CRBrowser; return { session: new CDPSessionDispatcher(this._scope, await crBrowser.newBrowserCDPSession()) }; } async crStartTracing(params: channels.BrowserCrStartTracingParams): Promise { + if (this._object._options.name !== 'chromium') + throw new Error(`Tracing is only available in Chromium`); const crBrowser = this._object as CRBrowser; await crBrowser.startTracing(params.page ? (params.page as PageDispatcher)._object : undefined, params); } async crStopTracing(): Promise { + if (this._object._options.name !== 'chromium') + throw new Error(`Tracing is only available in Chromium`); const crBrowser = this._object as CRBrowser; const buffer = await crBrowser.stopTracing(); return { binary: buffer.toString('base64') }; diff --git a/src/protocol/channels.ts b/src/protocol/channels.ts index 11c373ed62..746a983833 100644 --- a/src/protocol/channels.ts +++ b/src/protocol/channels.ts @@ -319,6 +319,7 @@ export type BrowserTypeLaunchPersistentContextResult = { // ----------- Browser ----------- export type BrowserInitializer = { version: string, + name: string, }; export interface BrowserChannel extends Channel { on(event: 'close', callback: (params: BrowserCloseEvent) => void): this; @@ -426,7 +427,9 @@ export type BrowserCrStopTracingResult = { }; // ----------- BrowserContext ----------- -export type BrowserContextInitializer = {}; +export type BrowserContextInitializer = { + browserName: string, +}; export interface BrowserContextChannel extends Channel { on(event: 'bindingCall', callback: (params: BrowserContextBindingCallEvent) => void): this; on(event: 'close', callback: (params: BrowserContextCloseEvent) => void): this; diff --git a/src/protocol/protocol.yml b/src/protocol/protocol.yml index ce3985b12a..2639d3975b 100644 --- a/src/protocol/protocol.yml +++ b/src/protocol/protocol.yml @@ -300,6 +300,7 @@ Browser: initializer: version: string + name: string commands: @@ -380,6 +381,9 @@ Browser: BrowserContext: type: interface + initializer: + browserName: string + commands: addCookies: