Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(rpc): do not use server types and events in rpc/client #3219

Merged
merged 1 commit into from
Jul 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
659 changes: 659 additions & 0 deletions src/rpc/channels.ts

Large diffs are not rendered by default.

26 changes: 22 additions & 4 deletions src/rpc/client/accessibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,28 @@
* limitations under the License.
*/

import { PageChannel } from '../channels';
import { PageChannel, AXNode } from '../channels';
import { ElementHandle } from './elementHandle';
import * as types from '../../types';
import { axNodeFromProtocol } from '../serializers';

type SerializedAXNode = Omit<AXNode, 'valueString' | 'valueNumber' | 'children' | 'checked' | 'pressed'> & {
value?: string|number,
checked?: boolean | 'mixed',
pressed?: boolean | 'mixed',
children?: SerializedAXNode[]
};

function axNodeFromProtocol(axNode: AXNode): SerializedAXNode {
const result: SerializedAXNode = {
...axNode,
value: axNode.valueNumber !== undefined ? axNode.valueNumber : axNode.valueString,
checked: axNode.checked === 'checked' ? true : axNode.checked === 'unchecked' ? false : axNode.checked,
pressed: axNode.pressed === 'pressed' ? true : axNode.pressed === 'released' ? false : axNode.pressed,
children: axNode.children ? axNode.children.map(axNodeFromProtocol) : undefined,
};
delete (result as any).valueNumber;
delete (result as any).valueString;
return result;
}

export class Accessibility {
private _channel: PageChannel;
Expand All @@ -27,7 +45,7 @@ export class Accessibility {
this._channel = channel;
}

async snapshot(options: { interestingOnly?: boolean; root?: ElementHandle } = {}): Promise<types.SerializedAXNode | null> {
async snapshot(options: { interestingOnly?: boolean; root?: ElementHandle } = {}): Promise<SerializedAXNode | null> {
const root = options.root ? options.root._elementChannel : undefined;
const result = await this._channel.accessibilitySnapshot({ interestingOnly: options.interestingOnly, root });
return result.rootAXNode ? axNodeFromProtocol(result.rootAXNode) : null;
Expand Down
9 changes: 4 additions & 5 deletions src/rpc/client/browser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@
* limitations under the License.
*/

import * as types from '../../types';
import { BrowserChannel, BrowserInitializer, BrowserNewContextParams } from '../channels';
import { BrowserContext } from './browserContext';
import { Page } from './page';
import { ChannelOwner } from './channelOwner';
import { Events } from '../../events';
import { LoggerSink } from '../../loggerSink';
import { Events } from './events';
import { BrowserType } from './browserType';
import { headersObjectToArray } from '../../converters';
import { BrowserContextOptions } from './types';

export class Browser extends ChannelOwner<BrowserChannel, BrowserInitializer> {
readonly _contexts = new Set<BrowserContext>();
Expand Down Expand Up @@ -50,7 +49,7 @@ export class Browser extends ChannelOwner<BrowserChannel, BrowserInitializer> {
this._closedPromise = new Promise(f => this.once(Events.Browser.Disconnected, f));
}

async newContext(options: types.BrowserContextOptions & { logger?: LoggerSink } = {}): Promise<BrowserContext> {
async newContext(options: BrowserContextOptions = {}): Promise<BrowserContext> {
const logger = options.logger;
options = { ...options, logger: undefined };
return this._wrapApiCall('browser.newContext', async () => {
Expand All @@ -75,7 +74,7 @@ export class Browser extends ChannelOwner<BrowserChannel, BrowserInitializer> {
return this._initializer.version;
}

async newPage(options: types.BrowserContextOptions & { logger?: LoggerSink } = {}): Promise<Page> {
async newPage(options: BrowserContextOptions = {}): Promise<Page> {
const context = await this.newContext(options);
const page = await context.newPage();
page._ownedContext = context;
Expand Down
18 changes: 9 additions & 9 deletions src/rpc/client/browserContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@

import * as frames from './frame';
import { Page, BindingCall } from './page';
import * as types from '../../types';
import * as network from './network';
import { BrowserContextChannel, BrowserContextInitializer } from '../channels';
import { ChannelOwner } from './channelOwner';
import { helper } from '../../helper';
import { Browser } from './browser';
import { Events } from '../../events';
import { Events } from './events';
import { TimeoutSettings } from '../../timeoutSettings';
import { Waiter } from './waiter';
import { headersObjectToArray } from '../../converters';
import { URLMatch, Headers, WaitForEventOptions } from './types';

export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserContextInitializer> {
_pages = new Set<Page>();
private _routes: { url: types.URLMatch, handler: network.RouteHandler }[] = [];
private _routes: { url: URLMatch, handler: network.RouteHandler }[] = [];
readonly _browser: Browser | undefined;
readonly _browserName: string;
readonly _bindings = new Map<string, frames.FunctionWithSource>();
Expand Down Expand Up @@ -138,13 +138,13 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserC
});
}

async setGeolocation(geolocation: types.Geolocation | null): Promise<void> {
async setGeolocation(geolocation: { longitude: number, latitude: number, accuracy?: number } | null): Promise<void> {
return this._wrapApiCall('browserContext.setGeolocation', async () => {
await this._channel.setGeolocation({ geolocation: geolocation || undefined });
});
}

async setExtraHTTPHeaders(headers: types.Headers): Promise<void> {
async setExtraHTTPHeaders(headers: Headers): Promise<void> {
return this._wrapApiCall('browserContext.setExtraHTTPHeaders', async () => {
await this._channel.setExtraHTTPHeaders({ headers: headersObjectToArray(headers) });
});
Expand All @@ -156,7 +156,7 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserC
});
}

async setHTTPCredentials(httpCredentials: types.Credentials | null): Promise<void> {
async setHTTPCredentials(httpCredentials: { username: string, password: string } | null): Promise<void> {
return this._wrapApiCall('browserContext.setHTTPCredentials', async () => {
await this._channel.setHTTPCredentials({ httpCredentials: httpCredentials || undefined });
});
Expand Down Expand Up @@ -186,23 +186,23 @@ export class BrowserContext extends ChannelOwner<BrowserContextChannel, BrowserC
await this.exposeBinding(name, (source, ...args) => playwrightFunction(...args));
}

async route(url: types.URLMatch, handler: network.RouteHandler): Promise<void> {
async route(url: URLMatch, handler: network.RouteHandler): Promise<void> {
return this._wrapApiCall('browserContext.route', async () => {
this._routes.push({ url, handler });
if (this._routes.length === 1)
await this._channel.setNetworkInterceptionEnabled({ enabled: true });
});
}

async unroute(url: types.URLMatch, handler?: network.RouteHandler): Promise<void> {
async unroute(url: URLMatch, handler?: network.RouteHandler): Promise<void> {
return this._wrapApiCall('browserContext.unroute', async () => {
this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler));
if (this._routes.length === 0)
await this._channel.setNetworkInterceptionEnabled({ enabled: false });
});
}

async waitForEvent(event: string, optionsOrPredicate: types.WaitForEventOptions = {}): Promise<any> {
async waitForEvent(event: string, optionsOrPredicate: WaitForEventOptions = {}): Promise<any> {
const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate);
const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate;
const waiter = new Waiter();
Expand Down
2 changes: 1 addition & 1 deletion src/rpc/client/browserServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import { ChildProcess } from 'child_process';
import { BrowserServerChannel, BrowserServerInitializer } from '../channels';
import { ChannelOwner } from './channelOwner';
import { Events } from '../../events';
import { Events } from './events';

export class BrowserServer extends ChannelOwner<BrowserServerChannel, BrowserServerInitializer> {
static from(server: BrowserServerChannel): BrowserServer {
Expand Down
13 changes: 5 additions & 8 deletions src/rpc/client/browserType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,15 @@
* limitations under the License.
*/

import * as types from '../../types';
import { BrowserTypeChannel, BrowserTypeInitializer, BrowserTypeLaunchParams, BrowserTypeLaunchServerParams, BrowserTypeLaunchPersistentContextParams } from '../channels';
import { Browser } from './browser';
import { BrowserContext } from './browserContext';
import { ChannelOwner } from './channelOwner';
import { BrowserServer } from './browserServer';
import { LoggerSink } from '../../loggerSink';
import { headersObjectToArray, envObjectToArray } from '../../converters';
import { serializeArgument } from './jsHandle';
import { assert } from '../../helper';

type FirefoxPrefsOptions = { firefoxUserPrefs?: { [key: string]: string | number | boolean } };
import { LaunchOptions, LaunchServerOptions, BrowserContextOptions, ConnectOptions } from './types';

export class BrowserType extends ChannelOwner<BrowserTypeChannel, BrowserTypeInitializer> {

Expand All @@ -45,7 +42,7 @@ export class BrowserType extends ChannelOwner<BrowserTypeChannel, BrowserTypeIni
return this._initializer.name;
}

async launch(options: types.LaunchOptions & FirefoxPrefsOptions & { logger?: LoggerSink } = {}): Promise<Browser> {
async launch(options: LaunchOptions = {}): Promise<Browser> {
const logger = options.logger;
options = { ...options, logger: undefined };
return this._wrapApiCall('browserType.launch', async () => {
Expand All @@ -64,7 +61,7 @@ export class BrowserType extends ChannelOwner<BrowserTypeChannel, BrowserTypeIni
}, logger);
}

async launchServer(options: types.LaunchServerOptions & FirefoxPrefsOptions & { logger?: LoggerSink } = {}): Promise<BrowserServer> {
async launchServer(options: LaunchServerOptions = {}): Promise<BrowserServer> {
const logger = options.logger;
options = { ...options, logger: undefined };
return this._wrapApiCall('browserType.launchServer', async () => {
Expand All @@ -79,7 +76,7 @@ export class BrowserType extends ChannelOwner<BrowserTypeChannel, BrowserTypeIni
}, logger);
}

async launchPersistentContext(userDataDir: string, options: types.LaunchOptions & types.BrowserContextOptions & { logger?: LoggerSink } = {}): Promise<BrowserContext> {
async launchPersistentContext(userDataDir: string, options: LaunchOptions & BrowserContextOptions = {}): Promise<BrowserContext> {
const logger = options.logger;
options = { ...options, logger: undefined };
return this._wrapApiCall('browserType.launchPersistentContext', async () => {
Expand All @@ -100,7 +97,7 @@ export class BrowserType extends ChannelOwner<BrowserTypeChannel, BrowserTypeIni
}, logger);
}

async connect(options: types.ConnectOptions & { logger?: LoggerSink }): Promise<Browser> {
async connect(options: ConnectOptions): Promise<Browser> {
const logger = options.logger;
options = { ...options, logger: undefined };
return this._wrapApiCall('browserType.connect', async () => {
Expand Down
2 changes: 1 addition & 1 deletion src/rpc/client/channelOwner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import { EventEmitter } from 'events';
import type { Channel } from '../channels';
import type { Connection } from './connection';
import type { LoggerSink } from '../../loggerSink';
import type { LoggerSink } from './types';
import { DebugLoggerSink } from '../../logger';

export abstract class ChannelOwner<T extends Channel = Channel, Initializer = {}> extends EventEmitter {
Expand Down
6 changes: 3 additions & 3 deletions src/rpc/client/chromiumBrowserContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { Page } from './page';
import { BrowserContextInitializer } from '../channels';
import { ChannelOwner } from './channelOwner';
import { CDPSession } from './cdpSession';
import { Events as ChromiumEvents } from '../../chromium/events';
import { Events } from './events';
import { Worker } from './worker';
import { BrowserContext } from './browserContext';

Expand All @@ -32,13 +32,13 @@ export class ChromiumBrowserContext extends BrowserContext {
this._channel.on('crBackgroundPage', ({ page }) => {
const backgroundPage = Page.from(page);
this._backgroundPages.add(backgroundPage);
this.emit(ChromiumEvents.ChromiumBrowserContext.BackgroundPage, backgroundPage);
this.emit(Events.ChromiumBrowserContext.BackgroundPage, backgroundPage);
});
this._channel.on('crServiceWorker', ({worker}) => {
const serviceWorker = Worker.from(worker);
serviceWorker._context = this;
this._serviceWorkers.add(serviceWorker);
this.emit(ChromiumEvents.ChromiumBrowserContext.ServiceWorker, serviceWorker);
this.emit(Events.ChromiumBrowserContext.ServiceWorker, serviceWorker);
});
}

Expand Down
16 changes: 10 additions & 6 deletions src/rpc/client/chromiumCoverage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@
* limitations under the License.
*/

import * as types from '../../types';
import { PageChannel } from '../channels';
import { PageChannel, PageCrStartJSCoverageOptions, PageCrStopJSCoverageResult, PageCrStartCSSCoverageOptions, PageCrStopCSSCoverageResult } from '../channels';

let __dummyJSResult: PageCrStopJSCoverageResult;
type PageCrStopJSCoverageResultEntries = typeof __dummyJSResult.entries;
let __dummyCSSResult: PageCrStopCSSCoverageResult;
type PageCrStopCSSCoverageResultEntries = typeof __dummyCSSResult.entries;

export class ChromiumCoverage {
private _channel: PageChannel;
Expand All @@ -24,19 +28,19 @@ export class ChromiumCoverage {
this._channel = channel;
}

async startJSCoverage(options: types.JSCoverageOptions = {}) {
async startJSCoverage(options: PageCrStartJSCoverageOptions = {}) {
await this._channel.crStartJSCoverage(options);
}

async stopJSCoverage(): Promise<types.JSCoverageEntry[]> {
async stopJSCoverage(): Promise<PageCrStopJSCoverageResultEntries> {
return (await this._channel.crStopJSCoverage()).entries;
}

async startCSSCoverage(options: types.CSSCoverageOptions = {}) {
async startCSSCoverage(options: PageCrStartCSSCoverageOptions = {}) {
await this._channel.crStartCSSCoverage(options);
}

async stopCSSCoverage(): Promise<types.CSSCoverageEntry[]> {
async stopCSSCoverage(): Promise<PageCrStopCSSCoverageResultEntries> {
return (await this._channel.crStopCSSCoverage()).entries;
}
}
4 changes: 3 additions & 1 deletion src/rpc/client/consoleMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@
*/

import * as util from 'util';
import { ConsoleMessageLocation } from '../../types';
import { JSHandle } from './jsHandle';
import { ConsoleMessageChannel, ConsoleMessageInitializer } from '../channels';
import { ChannelOwner } from './channelOwner';

let __dummyInitializer: ConsoleMessageInitializer;
type ConsoleMessageLocation = typeof __dummyInitializer.location;

export class ConsoleMessage extends ChannelOwner<ConsoleMessageChannel, ConsoleMessageInitializer> {
static from(message: ConsoleMessageChannel): ConsoleMessage {
return (message as any)._object;
Expand Down
20 changes: 9 additions & 11 deletions src/rpc/client/electron.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,16 @@
* limitations under the License.
*/

import * as types from '../../types';
import { ElectronChannel, ElectronInitializer, ElectronApplicationChannel, ElectronApplicationInitializer, ElectronLaunchParams } from '../channels';
import { ElectronChannel, ElectronInitializer, ElectronApplicationChannel, ElectronApplicationInitializer, ElectronLaunchParams, ElectronLaunchOptions } from '../channels';
import { BrowserContext } from './browserContext';
import { ChannelOwner } from './channelOwner';
import { Page } from './page';
import { serializeArgument, FuncOn, parseResult, SmartHandle, JSHandle } from './jsHandle';
import { ElectronEvents, ElectronLaunchOptionsBase } from '../../server/electron';
import { TimeoutSettings } from '../../timeoutSettings';
import { Waiter } from './waiter';
import { Events } from '../../events';
import { LoggerSink } from '../../loggerSink';
import { Events } from './events';
import { envObjectToArray } from '../../converters';
import { WaitForEventOptions, Env, LoggerSink } from './types';

export class Electron extends ChannelOwner<ElectronChannel, ElectronInitializer> {
static from(electron: ElectronChannel): Electron {
Expand All @@ -36,7 +34,7 @@ export class Electron extends ChannelOwner<ElectronChannel, ElectronInitializer>
super(parent, type, guid, initializer);
}

async launch(executablePath: string, options: ElectronLaunchOptionsBase & { logger?: LoggerSink } = {}): Promise<ElectronApplication> {
async launch(executablePath: string, options: ElectronLaunchOptions & { env?: Env, logger?: LoggerSink } = {}): Promise<ElectronApplication> {
const logger = options.logger;
options = { ...options, logger: undefined };
return this._wrapApiCall('electron.launch', async () => {
Expand Down Expand Up @@ -66,10 +64,10 @@ export class ElectronApplication extends ChannelOwner<ElectronApplicationChannel
const window = Page.from(page);
(window as any).browserWindow = JSHandle.from(browserWindow);
this._windows.add(window);
this.emit(ElectronEvents.ElectronApplication.Window, window);
this.emit(Events.ElectronApplication.Window, window);
window.once(Events.Page.Close, () => this._windows.delete(window));
});
this._channel.on('close', () => this.emit(ElectronEvents.ElectronApplication.Close));
this._channel.on('close', () => this.emit(Events.ElectronApplication.Close));
}

windows(): Page[] {
Expand All @@ -95,13 +93,13 @@ export class ElectronApplication extends ChannelOwner<ElectronApplicationChannel
await this._channel.close();
}

async waitForEvent(event: string, optionsOrPredicate: types.WaitForEventOptions = {}): Promise<any> {
async waitForEvent(event: string, optionsOrPredicate: WaitForEventOptions = {}): Promise<any> {
const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate);
const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate;
const waiter = new Waiter();
waiter.rejectOnTimeout(timeout, `Timeout while waiting for event "${event}"`);
if (event !== ElectronEvents.ElectronApplication.Close)
waiter.rejectOnEvent(this, ElectronEvents.ElectronApplication.Close, new Error('Electron application closed'));
if (event !== Events.ElectronApplication.Close)
waiter.rejectOnEvent(this, Events.ElectronApplication.Close, new Error('Electron application closed'));
const result = await waiter.waitForEvent(this, event, predicate as any);
waiter.dispose();
return result;
Expand Down
Loading