chore: pull common functionality into the BrowserTypeBase (#2312)
This commit is contained in:
parent
aa0d844c76
commit
f9b437a49e
|
|
@ -14,7 +14,7 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { BrowserContext, BrowserContextOptions } from './browserContext';
|
||||
import { BrowserContext, BrowserContextOptions, BrowserContextBase } from './browserContext';
|
||||
import { Page } from './page';
|
||||
import { EventEmitter } from 'events';
|
||||
import { Download } from './download';
|
||||
|
|
@ -44,6 +44,7 @@ export interface Browser extends EventEmitter {
|
|||
export abstract class BrowserBase extends EventEmitter implements Browser, InnerLogger {
|
||||
readonly _options: BrowserOptions;
|
||||
private _downloads = new Map<string, Download>();
|
||||
_defaultContext: BrowserContextBase | null = null;
|
||||
|
||||
constructor(options: BrowserOptions) {
|
||||
super();
|
||||
|
|
@ -102,4 +103,3 @@ export abstract class BrowserBase extends EventEmitter implements Browser, Inner
|
|||
}
|
||||
}
|
||||
|
||||
export type LaunchType = 'local' | 'server' | 'persistent';
|
||||
|
|
|
|||
|
|
@ -36,7 +36,6 @@ export class CRBrowser extends BrowserBase {
|
|||
readonly _connection: CRConnection;
|
||||
_session: CRSession;
|
||||
private _clientRootSessionPromise: Promise<CRSession> | null = null;
|
||||
readonly _defaultContext: CRBrowserContext | null = null;
|
||||
readonly _contexts = new Map<string, CRBrowserContext>();
|
||||
_crPages = new Map<string, CRPage>();
|
||||
_backgroundPages = new Map<string, CRPage>();
|
||||
|
|
@ -123,7 +122,7 @@ export class CRBrowser extends BrowserBase {
|
|||
if (!context) {
|
||||
// TODO: auto attach only to pages from our contexts.
|
||||
// assert(this._defaultContext);
|
||||
context = this._defaultContext;
|
||||
context = this._defaultContext as CRBrowserContext;
|
||||
}
|
||||
|
||||
if (targetInfo.type === 'other' && targetInfo.url.startsWith('devtools://devtools') && this._devtools) {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ import { Protocol } from './protocol';
|
|||
export class FFBrowser extends BrowserBase {
|
||||
_connection: FFConnection;
|
||||
readonly _ffPages: Map<string, FFPage>;
|
||||
readonly _defaultContext: FFBrowserContext | null = null;
|
||||
readonly _contexts: Map<string, FFBrowserContext>;
|
||||
private _eventListeners: RegisteredListener[];
|
||||
|
||||
|
|
@ -91,7 +90,7 @@ export class FFBrowser extends BrowserBase {
|
|||
_onAttachedToTarget(payload: Protocol.Browser.attachedToTargetPayload) {
|
||||
const {targetId, browserContextId, openerId, type} = payload.targetInfo;
|
||||
assert(type === 'page');
|
||||
const context = browserContextId ? this._contexts.get(browserContextId)! : this._defaultContext;
|
||||
const context = browserContextId ? this._contexts.get(browserContextId)! : this._defaultContext as FFBrowserContext;
|
||||
assert(context, `Unknown context id:${browserContextId}, _defaultContext: ${this._defaultContext}`);
|
||||
const session = this._connection.createSession(payload.sessionId, type);
|
||||
const opener = openerId ? this._ffPages.get(openerId)! : null;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import { EventEmitter } from 'events';
|
|||
import { helper } from '../helper';
|
||||
import { RootLogger } from '../logger';
|
||||
import { TimeoutSettings } from '../timeoutSettings';
|
||||
import { LaunchOptionsBase } from './browserType';
|
||||
import { LaunchOptions } from './browserType';
|
||||
|
||||
export class WebSocketWrapper {
|
||||
readonly wsEndpoint: string;
|
||||
|
|
@ -54,11 +54,11 @@ export class BrowserServer extends EventEmitter {
|
|||
private _process: ChildProcess | undefined;
|
||||
private _gracefullyClose: (() => Promise<void>) | undefined;
|
||||
private _webSocketWrapper: WebSocketWrapper | null = null;
|
||||
private _launchOptions: LaunchOptionsBase;
|
||||
readonly _launchOptions: LaunchOptions;
|
||||
readonly _logger: RootLogger;
|
||||
readonly _launchDeadline: number;
|
||||
|
||||
constructor(options: LaunchOptionsBase) {
|
||||
constructor(options: LaunchOptions) {
|
||||
super();
|
||||
this._launchOptions = options;
|
||||
this._logger = new RootLogger(options.logger);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,10 @@
|
|||
import { BrowserContext } from '../browserContext';
|
||||
import { BrowserServer } from './browserServer';
|
||||
import * as browserPaths from '../install/browserPaths';
|
||||
import { Logger } from '../logger';
|
||||
import { Logger, RootLogger } from '../logger';
|
||||
import { ConnectionTransport, WebSocketTransport } from '../transport';
|
||||
import { BrowserBase, BrowserOptions, Browser } from '../browser';
|
||||
import { assert } from '../helper';
|
||||
|
||||
export type BrowserArgOptions = {
|
||||
headless?: boolean,
|
||||
|
|
@ -25,7 +28,7 @@ export type BrowserArgOptions = {
|
|||
devtools?: boolean,
|
||||
};
|
||||
|
||||
export type LaunchOptionsBase = BrowserArgOptions & {
|
||||
type LaunchOptionsBase = BrowserArgOptions & {
|
||||
executablePath?: string,
|
||||
ignoreDefaultArgs?: boolean | string[],
|
||||
handleSIGINT?: boolean,
|
||||
|
|
@ -46,9 +49,11 @@ export type ConnectOptions = {
|
|||
slowMo?: number,
|
||||
logger?: Logger,
|
||||
};
|
||||
export type LaunchType = 'local' | 'server' | 'persistent';
|
||||
export type LaunchOptions = LaunchOptionsBase & { slowMo?: number };
|
||||
export type LaunchServerOptions = LaunchOptionsBase & { port?: number };
|
||||
export interface BrowserType<Browser> {
|
||||
|
||||
export interface BrowserType {
|
||||
executablePath(): string;
|
||||
name(): string;
|
||||
launch(options?: LaunchOptions): Promise<Browser>;
|
||||
|
|
@ -57,7 +62,7 @@ export interface BrowserType<Browser> {
|
|||
connect(options: ConnectOptions): Promise<Browser>;
|
||||
}
|
||||
|
||||
export abstract class AbstractBrowserType<Browser> implements BrowserType<Browser> {
|
||||
export abstract class BrowserTypeBase implements BrowserType {
|
||||
private _name: string;
|
||||
private _executablePath: string | undefined;
|
||||
readonly _browserPath: string;
|
||||
|
|
@ -79,8 +84,44 @@ export abstract class AbstractBrowserType<Browser> implements BrowserType<Browse
|
|||
return this._name;
|
||||
}
|
||||
|
||||
abstract launch(options?: LaunchOptions): Promise<Browser>;
|
||||
abstract launchServer(options?: LaunchServerOptions): Promise<BrowserServer>;
|
||||
abstract launchPersistentContext(userDataDir: string, options?: LaunchOptions): Promise<BrowserContext>;
|
||||
abstract connect(options: ConnectOptions): Promise<Browser>;
|
||||
async launch(options: LaunchOptions = {}): Promise<Browser> {
|
||||
assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
|
||||
const browserServer = new BrowserServer(options);
|
||||
const { transport, downloadsPath } = await this._launchServer(options, 'local', browserServer);
|
||||
return await browserServer._initializeOrClose(async () => {
|
||||
return this._connectToServer(browserServer, false, transport!, downloadsPath);
|
||||
});
|
||||
}
|
||||
|
||||
async launchPersistentContext(userDataDir: string, options: LaunchOptions = {}): Promise<BrowserContext> {
|
||||
const browserServer = new BrowserServer(options);
|
||||
const { transport, downloadsPath } = await this._launchServer(options, 'persistent', browserServer, userDataDir);
|
||||
|
||||
return await browserServer._initializeOrClose(async () => {
|
||||
const browser = await this._connectToServer(browserServer, true, transport!, downloadsPath);
|
||||
const context = browser._defaultContext!;
|
||||
if (!options.ignoreDefaultArgs || Array.isArray(options.ignoreDefaultArgs))
|
||||
await context._loadDefaultContext();
|
||||
return context;
|
||||
});
|
||||
}
|
||||
|
||||
async launchServer(options: LaunchServerOptions = {}): Promise<BrowserServer> {
|
||||
const browserServer = new BrowserServer(options);
|
||||
await this._launchServer(options, 'server', browserServer);
|
||||
return browserServer;
|
||||
}
|
||||
|
||||
async connect(options: ConnectOptions): Promise<Browser> {
|
||||
const logger = new RootLogger(options.logger);
|
||||
return await WebSocketTransport.connect(options.wsEndpoint, async transport => {
|
||||
if ((options as any).__testHookBeforeCreateBrowser)
|
||||
await (options as any).__testHookBeforeCreateBrowser();
|
||||
return this._connectToTransport(transport, { slowMo: options.slowMo, logger, downloadsPath: '' });
|
||||
}, logger);
|
||||
}
|
||||
|
||||
abstract _launchServer(options: LaunchServerOptions, launchType: LaunchType, browserServer: BrowserServer, userDataDir?: string): Promise<{ transport?: ConnectionTransport, downloadsPath: string }>;
|
||||
abstract _connectToServer(browserServer: BrowserServer, persistent: boolean, transport: ConnectionTransport, downloadsPath: string): Promise<BrowserBase>;
|
||||
abstract _connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<BrowserBase>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,17 +25,16 @@ import * as ws from 'ws';
|
|||
import { launchProcess } from './processLauncher';
|
||||
import { kBrowserCloseMessageId } from '../chromium/crConnection';
|
||||
import { PipeTransport } from './pipeTransport';
|
||||
import { LaunchOptions, BrowserArgOptions, ConnectOptions, LaunchServerOptions, AbstractBrowserType, processBrowserArgOptions } from './browserType';
|
||||
import { LaunchType } from '../browser';
|
||||
import { BrowserArgOptions, LaunchServerOptions, BrowserTypeBase, processBrowserArgOptions, LaunchType } from './browserType';
|
||||
import { BrowserServer, WebSocketWrapper } from './browserServer';
|
||||
import { Events } from '../events';
|
||||
import { ConnectionTransport, ProtocolRequest, WebSocketTransport } from '../transport';
|
||||
import { BrowserContext } from '../browserContext';
|
||||
import { InnerLogger, logError, RootLogger } from '../logger';
|
||||
import { ConnectionTransport, ProtocolRequest } from '../transport';
|
||||
import { InnerLogger, logError } from '../logger';
|
||||
import { BrowserDescriptor } from '../install/browserPaths';
|
||||
import { CRDevTools } from '../chromium/crDevTools';
|
||||
import { BrowserBase, BrowserOptions } from '../browser';
|
||||
|
||||
export class Chromium extends AbstractBrowserType<CRBrowser> {
|
||||
export class Chromium extends BrowserTypeBase {
|
||||
private _devtools: CRDevTools | undefined;
|
||||
|
||||
constructor(packagePath: string, browser: BrowserDescriptor) {
|
||||
|
|
@ -48,52 +47,28 @@ export class Chromium extends AbstractBrowserType<CRBrowser> {
|
|||
return new CRDevTools(path.join(this._browserPath, 'devtools-preferences.json'));
|
||||
}
|
||||
|
||||
async launch(options: LaunchOptions = {}): Promise<CRBrowser> {
|
||||
assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
|
||||
const browserServer = new BrowserServer(options);
|
||||
const { transport, downloadsPath } = await this._launchServer(options, 'local', browserServer);
|
||||
return await browserServer._initializeOrClose(async () => {
|
||||
let devtools = this._devtools;
|
||||
if ((options as any).__testHookForDevTools) {
|
||||
devtools = this._createDevTools();
|
||||
await (options as any).__testHookForDevTools(devtools);
|
||||
}
|
||||
return await CRBrowser.connect(transport!, {
|
||||
slowMo: options.slowMo,
|
||||
headful: !processBrowserArgOptions(options).headless,
|
||||
logger: browserServer._logger,
|
||||
downloadsPath,
|
||||
ownedServer: browserServer,
|
||||
}, devtools);
|
||||
});
|
||||
async _connectToServer(browserServer: BrowserServer, persistent: boolean, transport: ConnectionTransport, downloadsPath: string): Promise<BrowserBase> {
|
||||
const options = browserServer._launchOptions;
|
||||
let devtools = this._devtools;
|
||||
if ((options as any).__testHookForDevTools) {
|
||||
devtools = this._createDevTools();
|
||||
await (options as any).__testHookForDevTools(devtools);
|
||||
}
|
||||
return await CRBrowser.connect(transport, {
|
||||
slowMo: options.slowMo,
|
||||
persistent,
|
||||
headful: !processBrowserArgOptions(options).headless,
|
||||
logger: browserServer._logger,
|
||||
downloadsPath,
|
||||
ownedServer: browserServer,
|
||||
}, devtools);
|
||||
}
|
||||
|
||||
async launchServer(options: LaunchServerOptions = {}): Promise<BrowserServer> {
|
||||
const browserServer = new BrowserServer(options);
|
||||
await this._launchServer(options, 'server', browserServer);
|
||||
return browserServer;
|
||||
_connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<CRBrowser> {
|
||||
return CRBrowser.connect(transport, options);
|
||||
}
|
||||
|
||||
async launchPersistentContext(userDataDir: string, options: LaunchOptions = {}): Promise<BrowserContext> {
|
||||
const browserServer = new BrowserServer(options);
|
||||
const { transport, downloadsPath } = await this._launchServer(options, 'persistent', browserServer, userDataDir);
|
||||
return await browserServer._initializeOrClose(async () => {
|
||||
const browser = await CRBrowser.connect(transport!, {
|
||||
slowMo: options.slowMo,
|
||||
persistent: true,
|
||||
logger: browserServer._logger,
|
||||
downloadsPath,
|
||||
headful: !processBrowserArgOptions(options).headless,
|
||||
ownedServer: browserServer
|
||||
}, this._devtools);
|
||||
const context = browser._defaultContext!;
|
||||
if (!options.ignoreDefaultArgs || Array.isArray(options.ignoreDefaultArgs))
|
||||
await context._loadDefaultContext();
|
||||
return context;
|
||||
});
|
||||
}
|
||||
|
||||
private async _launchServer(options: LaunchServerOptions, launchType: LaunchType, browserServer: BrowserServer, userDataDir?: string): Promise<{ transport?: ConnectionTransport, downloadsPath: string }> {
|
||||
async _launchServer(options: LaunchServerOptions, launchType: LaunchType, browserServer: BrowserServer, userDataDir?: string): Promise<{ transport?: ConnectionTransport, downloadsPath: string }> {
|
||||
const {
|
||||
ignoreDefaultArgs = false,
|
||||
args = [],
|
||||
|
|
@ -163,15 +138,6 @@ export class Chromium extends AbstractBrowserType<CRBrowser> {
|
|||
return { transport, downloadsPath };
|
||||
}
|
||||
|
||||
async connect(options: ConnectOptions): Promise<CRBrowser> {
|
||||
const logger = new RootLogger(options.logger);
|
||||
return await WebSocketTransport.connect(options.wsEndpoint, async transport => {
|
||||
if ((options as any).__testHookBeforeCreateBrowser)
|
||||
await (options as any).__testHookBeforeCreateBrowser();
|
||||
return CRBrowser.connect(transport, { slowMo: options.slowMo, logger, downloadsPath: '' });
|
||||
}, logger);
|
||||
}
|
||||
|
||||
private _defaultArgs(options: BrowserArgOptions = {}, launchType: LaunchType, userDataDir: string): string[] {
|
||||
const { devtools, headless } = processBrowserArgOptions(options);
|
||||
const { args = [] } = options;
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export class ElectronApplication extends ExtendedEventEmitter {
|
|||
constructor(logger: InnerLogger, browser: CRBrowser, nodeConnection: CRConnection) {
|
||||
super();
|
||||
this._logger = logger;
|
||||
this._browserContext = browser._defaultContext!;
|
||||
this._browserContext = browser._defaultContext as CRBrowserContext;
|
||||
this._browserContext.on(Events.BrowserContext.Close, () => this.emit(ElectronEvents.ElectronApplication.Close));
|
||||
this._browserContext.on(Events.BrowserContext.Page, event => this._onPage(event));
|
||||
this._nodeConnection = nodeConnection;
|
||||
|
|
|
|||
|
|
@ -20,73 +20,46 @@ import * as os from 'os';
|
|||
import * as path from 'path';
|
||||
import * as util from 'util';
|
||||
import * as ws from 'ws';
|
||||
import { LaunchType } from '../browser';
|
||||
import { BrowserContext } from '../browserContext';
|
||||
import { TimeoutError } from '../errors';
|
||||
import { Events } from '../events';
|
||||
import { FFBrowser } from '../firefox/ffBrowser';
|
||||
import { kBrowserCloseMessageId } from '../firefox/ffConnection';
|
||||
import { helper, assert, debugAssert } from '../helper';
|
||||
import { BrowserServer, WebSocketWrapper } from './browserServer';
|
||||
import { BrowserArgOptions, LaunchOptions, LaunchServerOptions, ConnectOptions, AbstractBrowserType, processBrowserArgOptions } from './browserType';
|
||||
import { BrowserArgOptions, LaunchServerOptions, BrowserTypeBase, processBrowserArgOptions, LaunchType } from './browserType';
|
||||
import { launchProcess, waitForLine } from './processLauncher';
|
||||
import { ConnectionTransport, SequenceNumberMixer, WebSocketTransport } from '../transport';
|
||||
import { RootLogger, InnerLogger, logError } from '../logger';
|
||||
import { InnerLogger, logError } from '../logger';
|
||||
import { BrowserDescriptor } from '../install/browserPaths';
|
||||
import { BrowserBase, BrowserOptions } from '../browser';
|
||||
|
||||
const mkdtempAsync = util.promisify(fs.mkdtemp);
|
||||
|
||||
export class Firefox extends AbstractBrowserType<FFBrowser> {
|
||||
export class Firefox extends BrowserTypeBase {
|
||||
constructor(packagePath: string, browser: BrowserDescriptor) {
|
||||
super(packagePath, browser);
|
||||
}
|
||||
|
||||
async launch(options: LaunchOptions = {}): Promise<FFBrowser> {
|
||||
assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
|
||||
const browserServer = new BrowserServer(options);
|
||||
const { downloadsPath } = await this._launchServer(options, 'local', browserServer);
|
||||
return await browserServer._initializeOrClose(async () => {
|
||||
const browser = await WebSocketTransport.connect(browserServer.wsEndpoint()!, transport => {
|
||||
return FFBrowser.connect(transport, {
|
||||
slowMo: options.slowMo,
|
||||
logger: browserServer._logger,
|
||||
downloadsPath,
|
||||
headful: !processBrowserArgOptions(options).headless,
|
||||
ownedServer: browserServer,
|
||||
});
|
||||
}, browserServer._logger);
|
||||
return browser;
|
||||
});
|
||||
_connectToServer(browserServer: BrowserServer, persistent: boolean, transport: ConnectionTransport, downloadsPath: string): Promise<BrowserBase> {
|
||||
const options = browserServer._launchOptions;
|
||||
// TODO: connect to the underlying socket.
|
||||
return WebSocketTransport.connect(browserServer.wsEndpoint()!, transport => {
|
||||
return FFBrowser.connect(transport, {
|
||||
slowMo: options.slowMo,
|
||||
logger: browserServer._logger,
|
||||
persistent,
|
||||
downloadsPath,
|
||||
headful: !processBrowserArgOptions(options).headless,
|
||||
ownedServer: browserServer,
|
||||
});
|
||||
}, browserServer._logger);
|
||||
}
|
||||
|
||||
async launchServer(options: LaunchServerOptions = {}): Promise<BrowserServer> {
|
||||
const browserServer = new BrowserServer(options);
|
||||
await this._launchServer(options, 'server', browserServer);
|
||||
return browserServer;
|
||||
_connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<FFBrowser> {
|
||||
return FFBrowser.connect(transport, options);
|
||||
}
|
||||
|
||||
async launchPersistentContext(userDataDir: string, options: LaunchOptions = {}): Promise<BrowserContext> {
|
||||
const browserServer = new BrowserServer(options);
|
||||
const { downloadsPath } = await this._launchServer(options, 'persistent', browserServer, userDataDir);
|
||||
return await browserServer._initializeOrClose(async () => {
|
||||
const browser = await WebSocketTransport.connect(browserServer.wsEndpoint()!, transport => {
|
||||
return FFBrowser.connect(transport, {
|
||||
slowMo: options.slowMo,
|
||||
logger: browserServer._logger,
|
||||
persistent: true,
|
||||
downloadsPath,
|
||||
ownedServer: browserServer,
|
||||
headful: !processBrowserArgOptions(options).headless,
|
||||
});
|
||||
}, browserServer._logger);
|
||||
const context = browser._defaultContext!;
|
||||
if (!options.ignoreDefaultArgs || Array.isArray(options.ignoreDefaultArgs))
|
||||
await context._loadDefaultContext();
|
||||
return context;
|
||||
});
|
||||
}
|
||||
|
||||
private async _launchServer(options: LaunchServerOptions, launchType: LaunchType, browserServer: BrowserServer, userDataDir?: string): Promise<{ downloadsPath: string }> {
|
||||
async _launchServer(options: LaunchServerOptions, launchType: LaunchType, browserServer: BrowserServer, userDataDir?: string): Promise<{ downloadsPath: string }> {
|
||||
const {
|
||||
ignoreDefaultArgs = false,
|
||||
args = [],
|
||||
|
|
@ -143,7 +116,7 @@ export class Firefox extends AbstractBrowserType<FFBrowser> {
|
|||
// We try to gracefully close to prevent crash reporting and core dumps.
|
||||
const transport = await WebSocketTransport.connect(browserWSEndpoint!, async transport => transport);
|
||||
const message = { method: 'Browser.close', params: {}, id: kBrowserCloseMessageId };
|
||||
await transport.send(message);
|
||||
transport.send(message);
|
||||
},
|
||||
onkill: (exitCode, signal) => {
|
||||
browserServer.emit(Events.BrowserServer.Close, exitCode, signal);
|
||||
|
|
@ -162,15 +135,6 @@ export class Firefox extends AbstractBrowserType<FFBrowser> {
|
|||
return { downloadsPath };
|
||||
}
|
||||
|
||||
async connect(options: ConnectOptions): Promise<FFBrowser> {
|
||||
const logger = new RootLogger(options.logger);
|
||||
return await WebSocketTransport.connect(options.wsEndpoint, async transport => {
|
||||
if ((options as any).__testHookBeforeCreateBrowser)
|
||||
await (options as any).__testHookBeforeCreateBrowser();
|
||||
return FFBrowser.connect(transport, { slowMo: options.slowMo, logger, downloadsPath: '' });
|
||||
}, logger);
|
||||
}
|
||||
|
||||
private _defaultArgs(options: BrowserArgOptions = {}, launchType: LaunchType, userDataDir: string, port: number): string[] {
|
||||
const { devtools, headless } = processBrowserArgOptions(options);
|
||||
const { args = [] } = options;
|
||||
|
|
|
|||
|
|
@ -24,62 +24,37 @@ import * as os from 'os';
|
|||
import * as util from 'util';
|
||||
import { helper, assert } from '../helper';
|
||||
import { kBrowserCloseMessageId } from '../webkit/wkConnection';
|
||||
import { LaunchOptions, BrowserArgOptions, LaunchServerOptions, ConnectOptions, AbstractBrowserType, processBrowserArgOptions } from './browserType';
|
||||
import { ConnectionTransport, SequenceNumberMixer, WebSocketTransport } from '../transport';
|
||||
import { BrowserArgOptions, LaunchServerOptions, BrowserTypeBase, processBrowserArgOptions, LaunchType } from './browserType';
|
||||
import { ConnectionTransport, SequenceNumberMixer } from '../transport';
|
||||
import * as ws from 'ws';
|
||||
import { LaunchType } from '../browser';
|
||||
import { BrowserServer, WebSocketWrapper } from './browserServer';
|
||||
import { Events } from '../events';
|
||||
import { BrowserContext } from '../browserContext';
|
||||
import { InnerLogger, logError, RootLogger } from '../logger';
|
||||
import { BrowserDescriptor } from '../install/browserPaths';
|
||||
import { BrowserBase, BrowserOptions } from '../browser';
|
||||
|
||||
export class WebKit extends AbstractBrowserType<WKBrowser> {
|
||||
export class WebKit extends BrowserTypeBase {
|
||||
constructor(packagePath: string, browser: BrowserDescriptor) {
|
||||
super(packagePath, browser);
|
||||
}
|
||||
|
||||
async launch(options: LaunchOptions = {}): Promise<WKBrowser> {
|
||||
assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
|
||||
const browserServer = new BrowserServer(options);
|
||||
const { transport, downloadsPath } = await this._launchServer(options, 'local', browserServer);
|
||||
return await browserServer._initializeOrClose(async () => {
|
||||
return await WKBrowser.connect(transport!, {
|
||||
slowMo: options.slowMo,
|
||||
headful: !processBrowserArgOptions(options).headless,
|
||||
logger: browserServer._logger,
|
||||
downloadsPath,
|
||||
ownedServer: browserServer
|
||||
});
|
||||
_connectToServer(browserServer: BrowserServer, persistent: boolean, transport: ConnectionTransport, downloadsPath: string): Promise<BrowserBase> {
|
||||
const options = browserServer._launchOptions;
|
||||
return WKBrowser.connect(transport, {
|
||||
slowMo: options.slowMo,
|
||||
headful: !processBrowserArgOptions(options).headless,
|
||||
logger: browserServer._logger,
|
||||
persistent,
|
||||
downloadsPath,
|
||||
ownedServer: browserServer
|
||||
});
|
||||
}
|
||||
|
||||
async launchServer(options: LaunchServerOptions = {}): Promise<BrowserServer> {
|
||||
const browserServer = new BrowserServer(options);
|
||||
await this._launchServer(options, 'server', browserServer);
|
||||
return browserServer;
|
||||
_connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<WKBrowser> {
|
||||
return WKBrowser.connect(transport, options);
|
||||
}
|
||||
|
||||
async launchPersistentContext(userDataDir: string, options: LaunchOptions = {}): Promise<BrowserContext> {
|
||||
const browserServer = new BrowserServer(options);
|
||||
const { transport, downloadsPath } = await this._launchServer(options, 'persistent', browserServer, userDataDir);
|
||||
return await browserServer._initializeOrClose(async () => {
|
||||
const browser = await WKBrowser.connect(transport!, {
|
||||
slowMo: options.slowMo,
|
||||
headful: !processBrowserArgOptions(options).headless,
|
||||
logger: browserServer._logger,
|
||||
persistent: true,
|
||||
downloadsPath,
|
||||
ownedServer: browserServer
|
||||
});
|
||||
const context = browser._defaultContext!;
|
||||
if (!options.ignoreDefaultArgs || Array.isArray(options.ignoreDefaultArgs))
|
||||
await context._loadDefaultContext();
|
||||
return context;
|
||||
});
|
||||
}
|
||||
|
||||
private async _launchServer(options: LaunchServerOptions, launchType: LaunchType, browserServer: BrowserServer, userDataDir?: string): Promise<{ transport?: ConnectionTransport, downloadsPath: string, logger: RootLogger }> {
|
||||
async _launchServer(options: LaunchServerOptions, launchType: LaunchType, browserServer: BrowserServer, userDataDir?: string): Promise<{ transport?: ConnectionTransport, downloadsPath: string, logger: RootLogger }> {
|
||||
const {
|
||||
ignoreDefaultArgs = false,
|
||||
args = [],
|
||||
|
|
@ -144,15 +119,6 @@ export class WebKit extends AbstractBrowserType<WKBrowser> {
|
|||
return { transport, downloadsPath, logger };
|
||||
}
|
||||
|
||||
async connect(options: ConnectOptions): Promise<WKBrowser> {
|
||||
const logger = new RootLogger(options.logger);
|
||||
return await WebSocketTransport.connect(options.wsEndpoint, async transport => {
|
||||
if ((options as any).__testHookBeforeCreateBrowser)
|
||||
await (options as any).__testHookBeforeCreateBrowser();
|
||||
return WKBrowser.connect(transport, { slowMo: options.slowMo, logger, downloadsPath: '' });
|
||||
}, logger);
|
||||
}
|
||||
|
||||
_defaultArgs(options: BrowserArgOptions = {}, launchType: LaunchType, userDataDir: string, port: number): string[] {
|
||||
const { devtools, headless } = processBrowserArgOptions(options);
|
||||
const { args = [] } = options;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ const DEFAULT_USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) Appl
|
|||
export class WKBrowser extends BrowserBase {
|
||||
private readonly _connection: WKConnection;
|
||||
readonly _browserSession: WKSession;
|
||||
readonly _defaultContext: WKBrowserContext | null = null;
|
||||
readonly _contexts = new Map<string, WKBrowserContext>();
|
||||
readonly _wkPages = new Map<string, WKPage>();
|
||||
private readonly _eventListeners: RegisteredListener[];
|
||||
|
|
@ -132,7 +131,7 @@ export class WKBrowser extends BrowserBase {
|
|||
context = this._contexts.get(pageProxyInfo.browserContextId) || null;
|
||||
}
|
||||
if (!context)
|
||||
context = this._defaultContext;
|
||||
context = this._defaultContext as WKBrowserContext;
|
||||
if (!context)
|
||||
return;
|
||||
const pageProxySession = new WKSession(this._connection, pageProxyId, `The page has been closed.`, (message: any) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue