chore: use channels types instead of a copy in server (#14874)

This is to avoid duplicating types for no reason.
This commit is contained in:
Dmitry Gozman 2022-06-14 22:02:15 -07:00 committed by GitHub
parent e00a26a11d
commit 06c8d8e31c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 135 additions and 347 deletions

View file

@ -16,13 +16,13 @@
*/ */
import type * as dom from './dom'; import type * as dom from './dom';
import type * as types from './types'; import type * as channels from '../protocol/channels';
export interface AXNode { export interface AXNode {
isInteresting(insideControl: boolean): boolean; isInteresting(insideControl: boolean): boolean;
isLeafNode(): boolean; isLeafNode(): boolean;
isControl(): boolean; isControl(): boolean;
serialize(): types.SerializedAXNode; serialize(): channels.AXNode;
children(): Iterable<AXNode>; children(): Iterable<AXNode>;
} }
@ -35,7 +35,7 @@ export class Accessibility {
async snapshot(options: { async snapshot(options: {
interestingOnly?: boolean; interestingOnly?: boolean;
root?: dom.ElementHandle; root?: dom.ElementHandle;
} = {}): Promise<types.SerializedAXNode | null> { } = {}): Promise<channels.AXNode | null> {
const { const {
interestingOnly = true, interestingOnly = true,
root = null, root = null,
@ -65,8 +65,8 @@ function collectInterestingNodes(collection: Set<AXNode>, node: AXNode, insideCo
collectInterestingNodes(collection, child, insideControl); collectInterestingNodes(collection, child, insideControl);
} }
function serializeTree(node: AXNode, whitelistedNodes?: Set<AXNode>): types.SerializedAXNode[] { function serializeTree(node: AXNode, whitelistedNodes?: Set<AXNode>): channels.AXNode[] {
const children: types.SerializedAXNode[] = []; const children: channels.AXNode[] = [];
for (const child of node.children()) for (const child of node.children())
children.push(...serializeTree(child, whitelistedNodes)); children.push(...serializeTree(child, whitelistedNodes));

View file

@ -15,7 +15,6 @@
*/ */
import { debug } from '../../utilsBundle'; import { debug } from '../../utilsBundle';
import type * as types from '../types';
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import fs from 'fs'; import fs from 'fs';
import os from 'os'; import os from 'os';
@ -34,13 +33,13 @@ import { PipeTransport } from '../../protocol/transport';
import { RecentLogsCollector } from '../../common/debugLogger'; import { RecentLogsCollector } from '../../common/debugLogger';
import { gracefullyCloseSet } from '../../utils/processLauncher'; import { gracefullyCloseSet } from '../../utils/processLauncher';
import { TimeoutSettings } from '../../common/timeoutSettings'; import { TimeoutSettings } from '../../common/timeoutSettings';
import type { AndroidWebView } from '../../protocol/channels'; import type * as channels from '../../protocol/channels';
import { SdkObject, serverSideCallMetadata } from '../instrumentation'; import { SdkObject, serverSideCallMetadata } from '../instrumentation';
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-'); const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
export interface Backend { export interface Backend {
devices(options: types.AndroidDeviceOptions): Promise<DeviceBackend[]>; devices(options: channels.AndroidDevicesOptions): Promise<DeviceBackend[]>;
} }
export interface DeviceBackend { export interface DeviceBackend {
@ -75,7 +74,7 @@ export class Android extends SdkObject {
this._timeoutSettings.setDefaultTimeout(timeout); this._timeoutSettings.setDefaultTimeout(timeout);
} }
async devices(options: types.AndroidDeviceOptions): Promise<AndroidDevice[]> { async devices(options: channels.AndroidDevicesOptions): Promise<AndroidDevice[]> {
const devices = (await this._backend.devices(options)).filter(d => d.status === 'device'); const devices = (await this._backend.devices(options)).filter(d => d.status === 'device');
const newSerials = new Set<string>(); const newSerials = new Set<string>();
for (const d of devices) { for (const d of devices) {
@ -101,13 +100,13 @@ export class AndroidDevice extends SdkObject {
readonly _backend: DeviceBackend; readonly _backend: DeviceBackend;
readonly model: string; readonly model: string;
readonly serial: string; readonly serial: string;
private _options: types.AndroidDeviceOptions; private _options: channels.AndroidDevicesOptions;
private _driverPromise: Promise<PipeTransport> | undefined; private _driverPromise: Promise<PipeTransport> | undefined;
private _lastId = 0; private _lastId = 0;
private _callbacks = new Map<number, { fulfill: (result: any) => void, reject: (error: Error) => void }>(); private _callbacks = new Map<number, { fulfill: (result: any) => void, reject: (error: Error) => void }>();
private _pollingWebViews: NodeJS.Timeout | undefined; private _pollingWebViews: NodeJS.Timeout | undefined;
readonly _timeoutSettings: TimeoutSettings; readonly _timeoutSettings: TimeoutSettings;
private _webViews = new Map<string, AndroidWebView>(); private _webViews = new Map<string, channels.AndroidWebView>();
static Events = { static Events = {
WebViewAdded: 'webViewAdded', WebViewAdded: 'webViewAdded',
@ -119,7 +118,7 @@ export class AndroidDevice extends SdkObject {
private _android: Android; private _android: Android;
private _isClosed = false; private _isClosed = false;
constructor(android: Android, backend: DeviceBackend, model: string, options: types.AndroidDeviceOptions) { constructor(android: Android, backend: DeviceBackend, model: string, options: channels.AndroidDevicesOptions) {
super(android, 'android-device'); super(android, 'android-device');
this._android = android; this._android = android;
this._backend = backend; this._backend = backend;
@ -129,7 +128,7 @@ export class AndroidDevice extends SdkObject {
this._timeoutSettings = new TimeoutSettings(android._timeoutSettings); this._timeoutSettings = new TimeoutSettings(android._timeoutSettings);
} }
static async create(android: Android, backend: DeviceBackend, options: types.AndroidDeviceOptions): Promise<AndroidDevice> { static async create(android: Android, backend: DeviceBackend, options: channels.AndroidDevicesOptions): Promise<AndroidDevice> {
await backend.init(); await backend.init();
const model = await backend.runCommand('shell:getprop ro.product.model'); const model = await backend.runCommand('shell:getprop ro.product.model');
const device = new AndroidDevice(android, backend, model.toString().trim(), options); const device = new AndroidDevice(android, backend, model.toString().trim(), options);
@ -244,7 +243,7 @@ export class AndroidDevice extends SdkObject {
this.emit(AndroidDevice.Events.Closed); this.emit(AndroidDevice.Events.Closed);
} }
async launchBrowser(pkg: string = 'com.android.chrome', options: types.BrowserContextOptions): Promise<BrowserContext> { async launchBrowser(pkg: string = 'com.android.chrome', options: channels.BrowserNewContextParams): Promise<BrowserContext> {
debug('pw:android')('Force-stopping', pkg); debug('pw:android')('Force-stopping', pkg);
await this._backend.runCommand(`shell:am force-stop ${pkg}`); await this._backend.runCommand(`shell:am force-stop ${pkg}`);
const socketName = isUnderTest() ? 'webview_devtools_remote_playwright_test' : ('playwright-' + createGuid()); const socketName = isUnderTest() ? 'webview_devtools_remote_playwright_test' : ('playwright-' + createGuid());
@ -262,7 +261,7 @@ export class AndroidDevice extends SdkObject {
return await this._connectToBrowser(socketName); return await this._connectToBrowser(socketName);
} }
private async _connectToBrowser(socketName: string, options: types.BrowserContextOptions = {}): Promise<BrowserContext> { private async _connectToBrowser(socketName: string, options: channels.BrowserNewContextParams = {}): Promise<BrowserContext> {
const socket = await this._waitForLocalAbstract(socketName); const socket = await this._waitForLocalAbstract(socketName);
const androidBrowser = new AndroidBrowser(this, socket); const androidBrowser = new AndroidBrowser(this, socket);
await androidBrowser._init(); await androidBrowser._init();
@ -304,7 +303,7 @@ export class AndroidDevice extends SdkObject {
return defaultContext; return defaultContext;
} }
webViews(): AndroidWebView[] { webViews(): channels.AndroidWebView[] {
return [...this._webViews.values()]; return [...this._webViews.values()];
} }

View file

@ -15,14 +15,14 @@
*/ */
import { debug } from '../../utilsBundle'; import { debug } from '../../utilsBundle';
import type * as types from '../types'; import type * as channels from '../../protocol/channels';
import * as net from 'net'; import * as net from 'net';
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import type { Backend, DeviceBackend, SocketBackend } from './android'; import type { Backend, DeviceBackend, SocketBackend } from './android';
import { assert, createGuid } from '../../utils'; import { assert, createGuid } from '../../utils';
export class AdbBackend implements Backend { export class AdbBackend implements Backend {
async devices(options: types.AndroidDeviceOptions = {}): Promise<DeviceBackend[]> { async devices(options: channels.AndroidDevicesOptions = {}): Promise<DeviceBackend[]> {
const result = await runCommand('host:devices', options.host, options.port); const result = await runCommand('host:devices', options.host, options.port);
const lines = result.toString().trim().split('\n'); const lines = result.toString().trim().split('\n');
return lines.map(line => { return lines.map(line => {

View file

@ -15,6 +15,7 @@
*/ */
import type * as types from './types'; import type * as types from './types';
import type * as channels from '../protocol/channels';
import { BrowserContext, validateBrowserContextOptions } from './browserContext'; import { BrowserContext, validateBrowserContextOptions } from './browserContext';
import { Page } from './page'; import { Page } from './page';
import { Download } from './download'; import { Download } from './download';
@ -48,7 +49,7 @@ export type BrowserOptions = PlaywrightOptions & {
downloadsPath: string, downloadsPath: string,
tracesDir: string, tracesDir: string,
headful?: boolean, headful?: boolean,
persistent?: types.BrowserContextOptions, // Undefined means no persistent context. persistent?: channels.BrowserNewContextParams, // Undefined means no persistent context.
browserProcess: BrowserProcess, browserProcess: BrowserProcess,
customExecutablePath?: string; customExecutablePath?: string;
proxy?: ProxySettings, proxy?: ProxySettings,
@ -75,13 +76,13 @@ export abstract class Browser extends SdkObject {
this.options = options; this.options = options;
} }
abstract doCreateNewContext(options: types.BrowserContextOptions): Promise<BrowserContext>; abstract doCreateNewContext(options: channels.BrowserNewContextParams): Promise<BrowserContext>;
abstract contexts(): BrowserContext[]; abstract contexts(): BrowserContext[];
abstract isConnected(): boolean; abstract isConnected(): boolean;
abstract version(): string; abstract version(): string;
abstract userAgent(): string; abstract userAgent(): string;
async newContext(metadata: CallMetadata, options: types.BrowserContextOptions): Promise<BrowserContext> { async newContext(metadata: CallMetadata, options: channels.BrowserNewContextParams): Promise<BrowserContext> {
validateBrowserContextOptions(options, this.options); validateBrowserContextOptions(options, this.options);
const context = await this.doCreateNewContext(options); const context = await this.doCreateNewContext(options);
if (options.storageState) if (options.storageState)

View file

@ -29,6 +29,7 @@ import { Page, PageBinding } from './page';
import type { Progress } from './progress'; import type { Progress } from './progress';
import type { Selectors } from './selectors'; import type { Selectors } from './selectors';
import type * as types from './types'; import type * as types from './types';
import type * as channels from '../protocol/channels';
import path from 'path'; import path from 'path';
import fs from 'fs'; import fs from 'fs';
import type { CallMetadata } from './instrumentation'; import type { CallMetadata } from './instrumentation';
@ -54,7 +55,7 @@ export abstract class BrowserContext extends SdkObject {
readonly _timeoutSettings = new TimeoutSettings(); readonly _timeoutSettings = new TimeoutSettings();
readonly _pageBindings = new Map<string, PageBinding>(); readonly _pageBindings = new Map<string, PageBinding>();
readonly _options: types.BrowserContextOptions; readonly _options: channels.BrowserNewContextParams;
_requestInterceptor?: network.RouteHandler; _requestInterceptor?: network.RouteHandler;
private _isPersistentContext: boolean; private _isPersistentContext: boolean;
private _closedStatus: 'open' | 'closing' | 'closed' = 'open'; private _closedStatus: 'open' | 'closing' | 'closed' = 'open';
@ -74,7 +75,7 @@ export abstract class BrowserContext extends SdkObject {
private _settingStorageState = false; private _settingStorageState = false;
readonly initScripts: string[] = []; readonly initScripts: string[] = [];
constructor(browser: Browser, options: types.BrowserContextOptions, browserContextId: string | undefined) { constructor(browser: Browser, options: channels.BrowserNewContextParams, browserContextId: string | undefined) {
super(browser, 'browser-context'); super(browser, 'browser-context');
this.attribution.context = this; this.attribution.context = this;
this._browser = browser; this._browser = browser;
@ -156,13 +157,13 @@ export abstract class BrowserContext extends SdkObject {
// BrowserContext methods. // BrowserContext methods.
abstract pages(): Page[]; abstract pages(): Page[];
abstract newPageDelegate(): Promise<PageDelegate>; abstract newPageDelegate(): Promise<PageDelegate>;
abstract addCookies(cookies: types.SetNetworkCookieParam[]): Promise<void>; abstract addCookies(cookies: channels.SetNetworkCookie[]): Promise<void>;
abstract clearCookies(): Promise<void>; abstract clearCookies(): Promise<void>;
abstract setGeolocation(geolocation?: types.Geolocation): Promise<void>; abstract setGeolocation(geolocation?: types.Geolocation): Promise<void>;
abstract setExtraHTTPHeaders(headers: types.HeadersArray): Promise<void>; abstract setExtraHTTPHeaders(headers: types.HeadersArray): Promise<void>;
abstract setOffline(offline: boolean): Promise<void>; abstract setOffline(offline: boolean): Promise<void>;
abstract cancelDownload(uuid: string): Promise<void>; abstract cancelDownload(uuid: string): Promise<void>;
protected abstract doGetCookies(urls: string[]): Promise<types.NetworkCookie[]>; protected abstract doGetCookies(urls: string[]): Promise<channels.NetworkCookie[]>;
protected abstract doGrantPermissions(origin: string, permissions: string[]): Promise<void>; protected abstract doGrantPermissions(origin: string, permissions: string[]): Promise<void>;
protected abstract doClearPermissions(): Promise<void>; protected abstract doClearPermissions(): Promise<void>;
protected abstract doSetHTTPCredentials(httpCredentials?: types.Credentials): Promise<void>; protected abstract doSetHTTPCredentials(httpCredentials?: types.Credentials): Promise<void>;
@ -174,7 +175,7 @@ export abstract class BrowserContext extends SdkObject {
protected abstract doClose(): Promise<void>; protected abstract doClose(): Promise<void>;
protected abstract onClosePersistent(): void; protected abstract onClosePersistent(): void;
async cookies(urls: string | string[] | undefined = []): Promise<types.NetworkCookie[]> { async cookies(urls: string | string[] | undefined = []): Promise<channels.NetworkCookie[]> {
if (urls && !Array.isArray(urls)) if (urls && !Array.isArray(urls))
urls = [ urls ]; urls = [ urls ];
return await this.doGetCookies(urls as string[]); return await this.doGetCookies(urls as string[]);
@ -374,8 +375,8 @@ export abstract class BrowserContext extends SdkObject {
this._origins.add(origin); this._origins.add(origin);
} }
async storageState(): Promise<types.StorageState> { async storageState(): Promise<channels.BrowserContextStorageStateResult> {
const result: types.StorageState = { const result: channels.BrowserContextStorageStateResult = {
cookies: await this.cookies(), cookies: await this.cookies(),
origins: [] origins: []
}; };
@ -386,7 +387,7 @@ export abstract class BrowserContext extends SdkObject {
handler.fulfill({ body: '<html></html>' }).catch(() => {}); handler.fulfill({ body: '<html></html>' }).catch(() => {});
}); });
for (const origin of this._origins) { for (const origin of this._origins) {
const originStorage: types.OriginStorage = { origin, localStorage: [] }; const originStorage: channels.OriginStorage = { origin, localStorage: [] };
const frame = page.mainFrame(); const frame = page.mainFrame();
await frame.goto(internalMetadata, origin); await frame.goto(internalMetadata, origin);
const storage = await frame.evaluateExpression(`({ const storage = await frame.evaluateExpression(`({
@ -405,7 +406,7 @@ export abstract class BrowserContext extends SdkObject {
return this._settingStorageState; return this._settingStorageState;
} }
async setStorageState(metadata: CallMetadata, state: types.SetStorageState) { async setStorageState(metadata: CallMetadata, state: NonNullable<channels.BrowserNewContextParams['storageState']>) {
this._settingStorageState = true; this._settingStorageState = true;
try { try {
if (state.cookies) if (state.cookies)
@ -450,7 +451,7 @@ export function assertBrowserContextIsNotOwned(context: BrowserContext) {
} }
} }
export function validateBrowserContextOptions(options: types.BrowserContextOptions, browserOptions: BrowserOptions) { export function validateBrowserContextOptions(options: channels.BrowserNewContextParams, browserOptions: BrowserOptions) {
if (options.noDefaultViewport && options.deviceScaleFactor !== undefined) if (options.noDefaultViewport && options.deviceScaleFactor !== undefined)
throw new Error(`"deviceScaleFactor" option is not supported with null "viewport"`); throw new Error(`"deviceScaleFactor" option is not supported with null "viewport"`);
if (options.noDefaultViewport && options.isMobile !== undefined) if (options.noDefaultViewport && options.isMobile !== undefined)

View file

@ -30,6 +30,7 @@ import { PipeTransport } from './pipeTransport';
import type { Progress } from './progress'; import type { Progress } from './progress';
import { ProgressController } from './progress'; import { ProgressController } from './progress';
import type * as types from './types'; import type * as types from './types';
import type * as channels from '../protocol/channels';
import { DEFAULT_TIMEOUT, TimeoutSettings } from '../common/timeoutSettings'; import { DEFAULT_TIMEOUT, TimeoutSettings } from '../common/timeoutSettings';
import { debugMode } from '../utils'; import { debugMode } from '../utils';
import { existsAsync } from '../utils/fileUtils'; import { existsAsync } from '../utils/fileUtils';
@ -73,10 +74,10 @@ export abstract class BrowserType extends SdkObject {
return browser; return browser;
} }
async launchPersistentContext(metadata: CallMetadata, userDataDir: string, options: types.LaunchPersistentOptions): Promise<BrowserContext> { async launchPersistentContext(metadata: CallMetadata, userDataDir: string, options: channels.BrowserTypeLaunchPersistentContextOptions & { useWebSocket?: boolean }): Promise<BrowserContext> {
options = this._validateLaunchOptions(options); options = this._validateLaunchOptions(options);
const controller = new ProgressController(metadata, this); const controller = new ProgressController(metadata, this);
const persistent: types.BrowserContextOptions = options; const persistent: channels.BrowserNewContextParams = options;
controller.setLogName('browser'); controller.setLogName('browser');
const browser = await controller.run(progress => { const browser = await controller.run(progress => {
return this._innerLaunchWithRetries(progress, options, persistent, helper.debugProtocolLogger(), userDataDir).catch(e => { throw this._rewriteStartupError(e); }); return this._innerLaunchWithRetries(progress, options, persistent, helper.debugProtocolLogger(), userDataDir).catch(e => { throw this._rewriteStartupError(e); });
@ -84,7 +85,7 @@ export abstract class BrowserType extends SdkObject {
return browser._defaultContext!; return browser._defaultContext!;
} }
async _innerLaunchWithRetries(progress: Progress, options: types.LaunchOptions, persistent: types.BrowserContextOptions | undefined, protocolLogger: types.ProtocolLogger, userDataDir?: string): Promise<Browser> { async _innerLaunchWithRetries(progress: Progress, options: types.LaunchOptions, persistent: channels.BrowserNewContextParams | undefined, protocolLogger: types.ProtocolLogger, userDataDir?: string): Promise<Browser> {
try { try {
return await this._innerLaunch(progress, options, persistent, protocolLogger, userDataDir); return await this._innerLaunch(progress, options, persistent, protocolLogger, userDataDir);
} catch (error) { } catch (error) {
@ -98,7 +99,7 @@ export abstract class BrowserType extends SdkObject {
} }
} }
async _innerLaunch(progress: Progress, options: types.LaunchOptions, persistent: types.BrowserContextOptions | undefined, protocolLogger: types.ProtocolLogger, maybeUserDataDir?: string): Promise<Browser> { async _innerLaunch(progress: Progress, options: types.LaunchOptions, persistent: channels.BrowserNewContextParams | undefined, protocolLogger: types.ProtocolLogger, maybeUserDataDir?: string): Promise<Browser> {
options.proxy = options.proxy ? normalizeProxySettings(options.proxy) : undefined; options.proxy = options.proxy ? normalizeProxySettings(options.proxy) : undefined;
const browserLogsCollector = new RecentLogsCollector(); const browserLogsCollector = new RecentLogsCollector();
const { browserProcess, userDataDir, artifactsDir, transport } = await this._launchProcess(progress, options, !!persistent, browserLogsCollector, maybeUserDataDir); const { browserProcess, userDataDir, artifactsDir, transport } = await this._launchProcess(progress, options, !!persistent, browserLogsCollector, maybeUserDataDir);

View file

@ -30,6 +30,7 @@ import { CRDevTools } from './crDevTools';
import type { BrowserOptions, BrowserProcess, PlaywrightOptions } from '../browser'; import type { BrowserOptions, BrowserProcess, PlaywrightOptions } from '../browser';
import { Browser } from '../browser'; import { Browser } from '../browser';
import type * as types from '../types'; import type * as types from '../types';
import type * as channels from '../../protocol/channels';
import type { HTTPRequestParams } from '../../common/netUtils'; import type { HTTPRequestParams } from '../../common/netUtils';
import { fetchData } from '../../common/netUtils'; import { fetchData } from '../../common/netUtils';
import { getUserAgent } from '../../common/userAgent'; import { getUserAgent } from '../../common/userAgent';
@ -94,7 +95,7 @@ export class Chromium extends BrowserType {
await cleanedUp; await cleanedUp;
}; };
const browserProcess: BrowserProcess = { close: doClose, kill: doClose }; const browserProcess: BrowserProcess = { close: doClose, kill: doClose };
const persistent: types.BrowserContextOptions = { noDefaultViewport: true }; const persistent: channels.BrowserNewContextParams = { noDefaultViewport: true };
const browserOptions: BrowserOptions = { const browserOptions: BrowserOptions = {
...this._playwrightOptions, ...this._playwrightOptions,
slowMo: options.slowMo, slowMo: options.slowMo,

View file

@ -19,7 +19,7 @@ import type { CRSession } from './crConnection';
import type { Protocol } from './protocol'; import type { Protocol } from './protocol';
import type * as dom from '../dom'; import type * as dom from '../dom';
import type * as accessibility from '../accessibility'; import type * as accessibility from '../accessibility';
import type * as types from '../types'; import type * as channels from '../../protocol/channels';
export async function getAccessibilityTree(client: CRSession, needle?: dom.ElementHandle): Promise<{tree: accessibility.AXNode, needle: accessibility.AXNode | null}> { export async function getAccessibilityTree(client: CRSession, needle?: dom.ElementHandle): Promise<{tree: accessibility.AXNode, needle: accessibility.AXNode | null}> {
const { nodes } = await client.send('Accessibility.getFullAXTree'); const { nodes } = await client.send('Accessibility.getFullAXTree');
@ -210,19 +210,19 @@ class CRAXNode implements accessibility.AXNode {
} }
} }
serialize(): types.SerializedAXNode { serialize(): channels.AXNode {
const properties: Map<string, number | string | boolean> = new Map(); const properties: Map<string, number | string | boolean> = new Map();
for (const property of this._payload.properties || []) for (const property of this._payload.properties || [])
properties.set(property.name.toLowerCase(), property.value.value); properties.set(property.name.toLowerCase(), property.value.value);
if (this._payload.description) if (this._payload.description)
properties.set('description', this._payload.description.value); properties.set('description', this._payload.description.value);
const node: {[x in keyof types.SerializedAXNode]: any} = { const node: {[x in keyof channels.AXNode]: any} = {
role: this.normalizedRole(), role: this.normalizedRole(),
name: this._payload.name ? (this._payload.name.value || '') : '', name: this._payload.name ? (this._payload.name.value || '') : '',
}; };
const userStringProperties: Array<keyof types.SerializedAXNode> = [ const userStringProperties: Array<keyof channels.AXNode> = [
'description', 'description',
'keyshortcuts', 'keyshortcuts',
'roledescription', 'roledescription',
@ -233,7 +233,7 @@ class CRAXNode implements accessibility.AXNode {
continue; continue;
node[userStringProperty] = properties.get(userStringProperty); node[userStringProperty] = properties.get(userStringProperty);
} }
const booleanProperties: Array<keyof types.SerializedAXNode> = [ const booleanProperties: Array<keyof channels.AXNode> = [
'disabled', 'disabled',
'expanded', 'expanded',
'focused', 'focused',
@ -254,7 +254,7 @@ class CRAXNode implements accessibility.AXNode {
continue; continue;
node[booleanProperty] = value; node[booleanProperty] = value;
} }
const numericalProperties: Array<keyof types.SerializedAXNode> = [ const numericalProperties: Array<keyof channels.AXNode> = [
'level', 'level',
'valuemax', 'valuemax',
'valuemin', 'valuemin',
@ -264,7 +264,7 @@ class CRAXNode implements accessibility.AXNode {
continue; continue;
node[numericalProperty] = properties.get(numericalProperty); node[numericalProperty] = properties.get(numericalProperty);
} }
const tokenProperties: Array<keyof types.SerializedAXNode> = [ const tokenProperties: Array<keyof channels.AXNode> = [
'autocomplete', 'autocomplete',
'haspopup', 'haspopup',
'invalid', 'invalid',
@ -277,7 +277,7 @@ class CRAXNode implements accessibility.AXNode {
node[tokenProperty] = value; node[tokenProperty] = value;
} }
const axNode = node as types.SerializedAXNode; const axNode = node as channels.AXNode;
if (this._payload.value) { if (this._payload.value) {
if (typeof this._payload.value.value === 'string') if (typeof this._payload.value.value === 'string')
axNode.valueString = this._payload.value.value; axNode.valueString = this._payload.value.value;

View file

@ -26,6 +26,7 @@ import { Frame } from '../frames';
import type { Dialog } from '../dialog'; import type { Dialog } from '../dialog';
import type { ConnectionTransport } from '../transport'; import type { ConnectionTransport } from '../transport';
import type * as types from '../types'; import type * as types from '../types';
import type * as channels from '../../protocol/channels';
import type { CRSession } from './crConnection'; import type { CRSession } from './crConnection';
import { ConnectionEvents, CRConnection } from './crConnection'; import { ConnectionEvents, CRConnection } from './crConnection';
import { CRPage } from './crPage'; import { CRPage } from './crPage';
@ -95,7 +96,7 @@ export class CRBrowser extends Browser {
this._session.on('Browser.downloadProgress', this._onDownloadProgress.bind(this)); this._session.on('Browser.downloadProgress', this._onDownloadProgress.bind(this));
} }
async doCreateNewContext(options: types.BrowserContextOptions): Promise<BrowserContext> { async doCreateNewContext(options: channels.BrowserNewContextParams): Promise<BrowserContext> {
let proxyBypassList = undefined; let proxyBypassList = undefined;
if (options.proxy) { if (options.proxy) {
if (process.env.PLAYWRIGHT_DISABLE_FORCED_CHROMIUM_PROXIED_LOOPBACK) if (process.env.PLAYWRIGHT_DISABLE_FORCED_CHROMIUM_PROXIED_LOOPBACK)
@ -327,7 +328,7 @@ export class CRBrowserContext extends BrowserContext {
declare readonly _browser: CRBrowser; declare readonly _browser: CRBrowser;
constructor(browser: CRBrowser, browserContextId: string | undefined, options: types.BrowserContextOptions) { constructor(browser: CRBrowser, browserContextId: string | undefined, options: channels.BrowserNewContextParams) {
super(browser, options, browserContextId); super(browser, options, browserContextId);
this._authenticateProxyViaCredentials(); this._authenticateProxyViaCredentials();
} }
@ -383,7 +384,7 @@ export class CRBrowserContext extends BrowserContext {
return this._browser._crPages.get(targetId)!; return this._browser._crPages.get(targetId)!;
} }
async doGetCookies(urls: string[]): Promise<types.NetworkCookie[]> { async doGetCookies(urls: string[]): Promise<channels.NetworkCookie[]> {
const { cookies } = await this._browser._session.send('Storage.getCookies', { browserContextId: this._browserContextId }); const { cookies } = await this._browser._session.send('Storage.getCookies', { browserContextId: this._browserContextId });
return network.filterCookies(cookies.map(c => { return network.filterCookies(cookies.map(c => {
const copy: any = { sameSite: 'Lax', ...c }; const copy: any = { sameSite: 'Lax', ...c };
@ -393,11 +394,11 @@ export class CRBrowserContext extends BrowserContext {
delete copy.sameParty; delete copy.sameParty;
delete copy.sourceScheme; delete copy.sourceScheme;
delete copy.sourcePort; delete copy.sourcePort;
return copy as types.NetworkCookie; return copy as channels.NetworkCookie;
}), urls); }), urls);
} }
async addCookies(cookies: types.SetNetworkCookieParam[]) { async addCookies(cookies: channels.SetNetworkCookie[]) {
await this._browser._session.send('Storage.setCookies', { cookies: network.rewriteCookies(cookies), browserContextId: this._browserContextId }); await this._browser._session.send('Storage.setCookies', { cookies: network.rewriteCookies(cookies), browserContextId: this._browserContextId });
} }

View file

@ -19,7 +19,7 @@ import type { CRSession } from './crConnection';
import type { RegisteredListener } from '../../utils/eventsHelper'; import type { RegisteredListener } from '../../utils/eventsHelper';
import { eventsHelper } from '../../utils/eventsHelper'; import { eventsHelper } from '../../utils/eventsHelper';
import type { Protocol } from './protocol'; import type { Protocol } from './protocol';
import type * as types from '../types'; import type * as channels from '../../protocol/channels';
import { assert } from '../../utils'; import { assert } from '../../utils';
export class CRCoverage { export class CRCoverage {
@ -31,19 +31,19 @@ export class CRCoverage {
this._cssCoverage = new CSSCoverage(client); this._cssCoverage = new CSSCoverage(client);
} }
async startJSCoverage(options?: types.JSCoverageOptions) { async startJSCoverage(options: channels.PageStartJSCoverageParams) {
return await this._jsCoverage.start(options); return await this._jsCoverage.start(options);
} }
async stopJSCoverage(): Promise<types.JSCoverageEntry[]> { async stopJSCoverage(): Promise<channels.PageStopJSCoverageResult> {
return await this._jsCoverage.stop(); return await this._jsCoverage.stop();
} }
async startCSSCoverage(options?: types.CSSCoverageOptions) { async startCSSCoverage(options: channels.PageStartCSSCoverageParams) {
return await this._cssCoverage.start(options); return await this._cssCoverage.start(options);
} }
async stopCSSCoverage(): Promise<types.CSSCoverageEntry[]> { async stopCSSCoverage(): Promise<channels.PageStopCSSCoverageResult> {
return await this._cssCoverage.stop(); return await this._cssCoverage.stop();
} }
} }
@ -66,7 +66,7 @@ class JSCoverage {
this._resetOnNavigation = false; this._resetOnNavigation = false;
} }
async start(options: types.JSCoverageOptions = {}) { async start(options: channels.PageStartJSCoverageParams) {
assert(!this._enabled, 'JSCoverage is already enabled'); assert(!this._enabled, 'JSCoverage is already enabled');
const { const {
resetOnNavigation = true, resetOnNavigation = true,
@ -112,7 +112,7 @@ class JSCoverage {
this._scriptSources.set(event.scriptId, response.scriptSource); this._scriptSources.set(event.scriptId, response.scriptSource);
} }
async stop(): Promise<types.JSCoverageEntry[]> { async stop(): Promise<channels.PageStopJSCoverageResult> {
assert(this._enabled, 'JSCoverage is not enabled'); assert(this._enabled, 'JSCoverage is not enabled');
this._enabled = false; this._enabled = false;
const [profileResponse] = await Promise.all([ const [profileResponse] = await Promise.all([
@ -123,7 +123,7 @@ class JSCoverage {
] as const); ] as const);
eventsHelper.removeEventListeners(this._eventListeners); eventsHelper.removeEventListeners(this._eventListeners);
const coverage: types.JSCoverageEntry[] = []; const coverage: channels.PageStopJSCoverageResult = { entries: [] };
for (const entry of profileResponse.result) { for (const entry of profileResponse.result) {
if (!this._scriptIds.has(entry.scriptId)) if (!this._scriptIds.has(entry.scriptId))
continue; continue;
@ -131,9 +131,9 @@ class JSCoverage {
continue; continue;
const source = this._scriptSources.get(entry.scriptId); const source = this._scriptSources.get(entry.scriptId);
if (source) if (source)
coverage.push({ ...entry, source }); coverage.entries.push({ ...entry, source });
else else
coverage.push(entry); coverage.entries.push(entry);
} }
return coverage; return coverage;
} }
@ -156,7 +156,7 @@ class CSSCoverage {
this._resetOnNavigation = false; this._resetOnNavigation = false;
} }
async start(options: types.CSSCoverageOptions = {}) { async start(options: channels.PageStartCSSCoverageParams) {
assert(!this._enabled, 'CSSCoverage is already enabled'); assert(!this._enabled, 'CSSCoverage is already enabled');
const { resetOnNavigation = true } = options; const { resetOnNavigation = true } = options;
this._resetOnNavigation = resetOnNavigation; this._resetOnNavigation = resetOnNavigation;
@ -194,7 +194,7 @@ class CSSCoverage {
} }
} }
async stop(): Promise<types.CSSCoverageEntry[]> { async stop(): Promise<channels.PageStopCSSCoverageResult> {
assert(this._enabled, 'CSSCoverage is not enabled'); assert(this._enabled, 'CSSCoverage is not enabled');
this._enabled = false; this._enabled = false;
const ruleTrackingResponse = await this._client.send('CSS.stopRuleUsageTracking'); const ruleTrackingResponse = await this._client.send('CSS.stopRuleUsageTracking');
@ -219,12 +219,12 @@ class CSSCoverage {
}); });
} }
const coverage: types.CSSCoverageEntry[] = []; const coverage: channels.PageStopCSSCoverageResult = { entries: [] };
for (const styleSheetId of this._stylesheetURLs.keys()) { for (const styleSheetId of this._stylesheetURLs.keys()) {
const url = this._stylesheetURLs.get(styleSheetId)!; const url = this._stylesheetURLs.get(styleSheetId)!;
const text = this._stylesheetSources.get(styleSheetId)!; const text = this._stylesheetSources.get(styleSheetId)!;
const ranges = convertToDisjointRanges(styleSheetIdToCoverage.get(styleSheetId) || []); const ranges = convertToDisjointRanges(styleSheetIdToCoverage.get(styleSheetId) || []);
coverage.push({ url, ranges, text }); coverage.entries.push({ url, ranges, text });
} }
return coverage; return coverage;

View file

@ -30,6 +30,7 @@ import type { PageBinding, PageDelegate } from '../page';
import { Page, Worker } from '../page'; import { Page, Worker } from '../page';
import type { Progress } from '../progress'; import type { Progress } from '../progress';
import type * as types from '../types'; import type * as types from '../types';
import type * as channels from '../../protocol/channels';
import { getAccessibilityTree } from './crAccessibility'; import { getAccessibilityTree } from './crAccessibility';
import { CRBrowserContext } from './crBrowser'; import { CRBrowserContext } from './crBrowser';
import type { CRSession } from './crConnection'; import type { CRSession } from './crConnection';
@ -356,7 +357,7 @@ export class CRPage implements PageDelegate {
await this._mainFrameSession._client.send('Page.enable').catch(e => {}); await this._mainFrameSession._client.send('Page.enable').catch(e => {});
} }
async pdf(options?: types.PDFOptions): Promise<Buffer> { async pdf(options: channels.PagePdfParams): Promise<Buffer> {
return this._pdf.generate(options); return this._pdf.generate(options);
} }

View file

@ -16,7 +16,7 @@
*/ */
import { assert } from '../../utils'; import { assert } from '../../utils';
import type * as types from '../types'; import type * as channels from '../../protocol/channels';
import type { CRSession } from './crConnection'; import type { CRSession } from './crConnection';
import { readProtocolStream } from './crProtocolHelper'; import { readProtocolStream } from './crProtocolHelper';
@ -67,7 +67,7 @@ export class CRPDF {
this._client = client; this._client = client;
} }
async generate(options: types.PDFOptions = {}): Promise<Buffer> { async generate(options: channels.PagePdfParams): Promise<Buffer> {
const { const {
scale = 1, scale = 1,
displayHeaderFooter = false, displayHeaderFooter = false,

View file

@ -14,11 +14,11 @@
* limitations under the License. * limitations under the License.
*/ */
import type * as types from './types'; import type * as channels from '../protocol/channels';
class Cookie { class Cookie {
private _raw: types.NetworkCookie; private _raw: channels.NetworkCookie;
constructor(data: types.NetworkCookie) { constructor(data: channels.NetworkCookie) {
this._raw = data; this._raw = data;
} }
@ -43,7 +43,7 @@ class Cookie {
this._raw.path === other._raw.path; this._raw.path === other._raw.path;
} }
networkCookie(): types.NetworkCookie { networkCookie(): channels.NetworkCookie {
return this._raw; return this._raw;
} }
@ -61,12 +61,12 @@ class Cookie {
export class CookieStore { export class CookieStore {
private readonly _nameToCookies: Map<string, Set<Cookie>> = new Map(); private readonly _nameToCookies: Map<string, Set<Cookie>> = new Map();
addCookies(cookies: types.NetworkCookie[]) { addCookies(cookies: channels.NetworkCookie[]) {
for (const cookie of cookies) for (const cookie of cookies)
this._addCookie(new Cookie(cookie)); this._addCookie(new Cookie(cookie));
} }
cookies(url: URL): types.NetworkCookie[] { cookies(url: URL): channels.NetworkCookie[] {
const result = []; const result = [];
for (const cookie of this._cookiesIterator()) { for (const cookie of this._cookiesIterator()) {
if (cookie.matches(url)) if (cookie.matches(url))
@ -75,7 +75,7 @@ export class CookieStore {
return result; return result;
} }
allCookies(): types.NetworkCookie[] { allCookies(): channels.NetworkCookie[] {
const result = []; const result = [];
for (const cookie of this._cookiesIterator()) for (const cookie of this._cookiesIterator())
result.push(cookie.networkCookie()); result.push(cookie.networkCookie());

View file

@ -274,7 +274,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel> imple
async stopJSCoverage(params: channels.PageStopJSCoverageParams, metadata: CallMetadata): Promise<channels.PageStopJSCoverageResult> { async stopJSCoverage(params: channels.PageStopJSCoverageParams, metadata: CallMetadata): Promise<channels.PageStopJSCoverageResult> {
const coverage = this._page.coverage as CRCoverage; const coverage = this._page.coverage as CRCoverage;
return { entries: await coverage.stopJSCoverage() }; return await coverage.stopJSCoverage();
} }
async startCSSCoverage(params: channels.PageStartCSSCoverageParams, metadata: CallMetadata): Promise<void> { async startCSSCoverage(params: channels.PageStartCSSCoverageParams, metadata: CallMetadata): Promise<void> {
@ -284,7 +284,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel> imple
async stopCSSCoverage(params: channels.PageStopCSSCoverageParams, metadata: CallMetadata): Promise<channels.PageStopCSSCoverageResult> { async stopCSSCoverage(params: channels.PageStopCSSCoverageParams, metadata: CallMetadata): Promise<channels.PageStopCSSCoverageResult> {
const coverage = this._page.coverage as CRCoverage; const coverage = this._page.coverage as CRCoverage;
return { entries: await coverage.stopCSSCoverage() }; return await coverage.stopCSSCoverage();
} }
_onFrameAttached(frame: Frame) { _onFrameAttached(frame: Frame) {

View file

@ -41,7 +41,6 @@ import * as readline from 'readline';
import { RecentLogsCollector } from '../../common/debugLogger'; import { RecentLogsCollector } from '../../common/debugLogger';
import { serverSideCallMetadata, SdkObject } from '../instrumentation'; import { serverSideCallMetadata, SdkObject } from '../instrumentation';
import type * as channels from '../../protocol/channels'; import type * as channels from '../../protocol/channels';
import type { BrowserContextOptions } from '../types';
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-'); const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
@ -211,7 +210,7 @@ export class Electron extends SdkObject {
close: gracefullyClose, close: gracefullyClose,
kill kill
}; };
const contextOptions: BrowserContextOptions = { const contextOptions: channels.BrowserNewContextParams = {
...options, ...options,
noDefaultViewport: true, noDefaultViewport: true,
}; };

View file

@ -52,7 +52,7 @@ export type APIRequestEvent = {
url: URL, url: URL,
method: string, method: string,
headers: { [name: string]: string }, headers: { [name: string]: string },
cookies: types.NameValueList, cookies: channels.NameValue[],
postData?: Buffer postData?: Buffer
}; };
@ -60,7 +60,7 @@ export type APIRequestFinishedEvent = {
requestEvent: APIRequestEvent, requestEvent: APIRequestEvent,
httpVersion: string; httpVersion: string;
headers: http.IncomingHttpHeaders; headers: http.IncomingHttpHeaders;
cookies: types.NetworkCookie[]; cookies: channels.NetworkCookie[];
rawHeaders: string[]; rawHeaders: string[];
statusCode: number; statusCode: number;
statusMessage: string; statusMessage: string;
@ -110,8 +110,8 @@ export abstract class APIRequestContext extends SdkObject {
abstract dispose(): Promise<void>; abstract dispose(): Promise<void>;
abstract _defaultOptions(): FetchRequestOptions; abstract _defaultOptions(): FetchRequestOptions;
abstract _addCookies(cookies: types.NetworkCookie[]): Promise<void>; abstract _addCookies(cookies: channels.NetworkCookie[]): Promise<void>;
abstract _cookies(url: URL): Promise<types.NetworkCookie[]>; abstract _cookies(url: URL): Promise<channels.NetworkCookie[]>;
abstract storageState(): Promise<channels.APIRequestContextStorageStateResult>; abstract storageState(): Promise<channels.APIRequestContextStorageStateResult>;
private _storeResponseBody(body: Buffer): string { private _storeResponseBody(body: Buffer): string {
@ -120,7 +120,7 @@ export abstract class APIRequestContext extends SdkObject {
return uid; return uid;
} }
async fetch(params: channels.APIRequestContextFetchParams, metadata: CallMetadata): Promise<Omit<types.APIResponse, 'body'> & { fetchUid: string }> { async fetch(params: channels.APIRequestContextFetchParams, metadata: CallMetadata): Promise<channels.APIResponse> {
const headers: { [name: string]: string } = {}; const headers: { [name: string]: string } = {};
const defaults = this._defaultOptions(); const defaults = this._defaultOptions();
headers['user-agent'] = defaults.userAgent; headers['user-agent'] = defaults.userAgent;
@ -194,16 +194,16 @@ export abstract class APIRequestContext extends SdkObject {
return { ...fetchResponse, fetchUid }; return { ...fetchResponse, fetchUid };
} }
private _parseSetCookieHeader(responseUrl: string, setCookie: string[] | undefined): types.NetworkCookie[] { private _parseSetCookieHeader(responseUrl: string, setCookie: string[] | undefined): channels.NetworkCookie[] {
if (!setCookie) if (!setCookie)
return []; return [];
const url = new URL(responseUrl); const url = new URL(responseUrl);
// https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4 // https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4
const defaultPath = '/' + url.pathname.substr(1).split('/').slice(0, -1).join('/'); const defaultPath = '/' + url.pathname.substr(1).split('/').slice(0, -1).join('/');
const cookies: types.NetworkCookie[] = []; const cookies: channels.NetworkCookie[] = [];
for (const header of setCookie) { for (const header of setCookie) {
// Decode cookie value? // Decode cookie value?
const cookie: types.NetworkCookie | null = parseCookie(header); const cookie: channels.NetworkCookie | null = parseCookie(header);
if (!cookie) if (!cookie)
continue; continue;
// https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3 // https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3
@ -231,7 +231,7 @@ export abstract class APIRequestContext extends SdkObject {
} }
} }
private async _sendRequest(progress: Progress, url: URL, options: https.RequestOptions & { maxRedirects: number, deadline: number }, postData?: Buffer): Promise<types.APIResponse>{ private async _sendRequest(progress: Progress, url: URL, options: https.RequestOptions & { maxRedirects: number, deadline: number }, postData?: Buffer): Promise<Omit<channels.APIResponse, 'fetchUid'> & { body: Buffer }>{
await this._updateRequestCookieHeader(url, options); await this._updateRequestCookieHeader(url, options);
const requestCookies = (options.headers!['cookie'] as (string | undefined))?.split(';').map(p => { const requestCookies = (options.headers!['cookie'] as (string | undefined))?.split(';').map(p => {
@ -247,7 +247,7 @@ export abstract class APIRequestContext extends SdkObject {
}; };
this.emit(APIRequestContext.Events.Request, requestEvent); this.emit(APIRequestContext.Events.Request, requestEvent);
return new Promise<types.APIResponse>((fulfill, reject) => { return new Promise((fulfill, reject) => {
const requestConstructor: ((url: URL, options: http.RequestOptions, callback?: (res: http.IncomingMessage) => void) => http.ClientRequest) const requestConstructor: ((url: URL, options: http.RequestOptions, callback?: (res: http.IncomingMessage) => void) => http.ClientRequest)
= (url.protocol === 'https:' ? https : http).request; = (url.protocol === 'https:' ? https : http).request;
const request = requestConstructor(url, options, async response => { const request = requestConstructor(url, options, async response => {
@ -455,11 +455,11 @@ export class BrowserContextAPIRequestContext extends APIRequestContext {
}; };
} }
async _addCookies(cookies: types.NetworkCookie[]): Promise<void> { async _addCookies(cookies: channels.NetworkCookie[]): Promise<void> {
await this._context.addCookies(cookies); await this._context.addCookies(cookies);
} }
async _cookies(url: URL): Promise<types.NetworkCookie[]> { async _cookies(url: URL): Promise<channels.NetworkCookie[]> {
return await this._context.cookies(url.toString()); return await this._context.cookies(url.toString());
} }
@ -519,11 +519,11 @@ export class GlobalAPIRequestContext extends APIRequestContext {
return this._options; return this._options;
} }
async _addCookies(cookies: types.NetworkCookie[]): Promise<void> { async _addCookies(cookies: channels.NetworkCookie[]): Promise<void> {
this._cookieStore.addCookies(cookies); this._cookieStore.addCookies(cookies);
} }
async _cookies(url: URL): Promise<types.NetworkCookie[]> { async _cookies(url: URL): Promise<channels.NetworkCookie[]> {
return this._cookieStore.cookies(url); return this._cookieStore.cookies(url);
} }
@ -544,7 +544,7 @@ function toHeadersArray(rawHeaders: string[]): types.HeadersArray {
const redirectStatus = [301, 302, 303, 307, 308]; const redirectStatus = [301, 302, 303, 307, 308];
function parseCookie(header: string): types.NetworkCookie | null { function parseCookie(header: string): channels.NetworkCookie | null {
const pairs = header.split(';').filter(s => s.trim().length > 0).map(p => { const pairs = header.split(';').filter(s => s.trim().length > 0).map(p => {
let key = ''; let key = '';
let value = ''; let value = '';
@ -563,7 +563,7 @@ function parseCookie(header: string): types.NetworkCookie | null {
if (!pairs.length) if (!pairs.length)
return null; return null;
const [name, value] = pairs[0]; const [name, value] = pairs[0];
const cookie: types.NetworkCookie = { const cookie: channels.NetworkCookie = {
name, name,
value, value,
domain: '', domain: '',

View file

@ -19,7 +19,7 @@ import type * as accessibility from '../accessibility';
import type { FFSession } from './ffConnection'; import type { FFSession } from './ffConnection';
import type { Protocol } from './protocol'; import type { Protocol } from './protocol';
import type * as dom from '../dom'; import type * as dom from '../dom';
import type * as types from '../types'; import type * as channels from '../../protocol/channels';
export async function getAccessibilityTree(session: FFSession, needle?: dom.ElementHandle): Promise<{tree: accessibility.AXNode, needle: accessibility.AXNode | null}> { export async function getAccessibilityTree(session: FFSession, needle?: dom.ElementHandle): Promise<{tree: accessibility.AXNode, needle: accessibility.AXNode | null}> {
const objectId = needle ? needle._objectId : undefined; const objectId = needle ? needle._objectId : undefined;
@ -198,12 +198,12 @@ class FFAXNode implements accessibility.AXNode {
return this.isLeafNode() && !!this._name.trim(); return this.isLeafNode() && !!this._name.trim();
} }
serialize(): types.SerializedAXNode { serialize(): channels.AXNode {
const node: {[x in keyof types.SerializedAXNode]: any} = { const node: {[x in keyof channels.AXNode]: any} = {
role: FFRoleToARIARole.get(this._role) || this._role, role: FFRoleToARIARole.get(this._role) || this._role,
name: this._name || '', name: this._name || '',
}; };
const userStringProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Accessibility.AXTree> = [ const userStringProperties: Array<keyof channels.AXNode & keyof Protocol.Accessibility.AXTree> = [
'name', 'name',
'description', 'description',
'roledescription', 'roledescription',
@ -215,7 +215,7 @@ class FFAXNode implements accessibility.AXNode {
continue; continue;
node[userStringProperty] = this._payload[userStringProperty]; node[userStringProperty] = this._payload[userStringProperty];
} }
const booleanProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Accessibility.AXTree> = [ const booleanProperties: Array<keyof channels.AXNode & keyof Protocol.Accessibility.AXTree> = [
'disabled', 'disabled',
'expanded', 'expanded',
'focused', 'focused',
@ -234,7 +234,7 @@ class FFAXNode implements accessibility.AXNode {
continue; continue;
node[booleanProperty] = value; node[booleanProperty] = value;
} }
const numericalProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Accessibility.AXTree> = [ const numericalProperties: Array<keyof channels.AXNode & keyof Protocol.Accessibility.AXTree> = [
'level' 'level'
]; ];
for (const numericalProperty of numericalProperties) { for (const numericalProperty of numericalProperties) {
@ -242,7 +242,7 @@ class FFAXNode implements accessibility.AXNode {
continue; continue;
node[numericalProperty] = this._payload[numericalProperty]; node[numericalProperty] = this._payload[numericalProperty];
} }
const tokenProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Accessibility.AXTree> = [ const tokenProperties: Array<keyof channels.AXNode & keyof Protocol.Accessibility.AXTree> = [
'autocomplete', 'autocomplete',
'haspopup', 'haspopup',
'invalid', 'invalid',
@ -255,7 +255,7 @@ class FFAXNode implements accessibility.AXNode {
node[tokenProperty] = value; node[tokenProperty] = value;
} }
const axNode = node as types.SerializedAXNode; const axNode = node as channels.AXNode;
axNode.valueString = this._payload.value; axNode.valueString = this._payload.value;
if ('checked' in this._payload) if ('checked' in this._payload)
axNode.checked = this._payload.checked === true ? 'checked' : this._payload.checked === 'mixed' ? 'mixed' : 'unchecked'; axNode.checked = this._payload.checked === true ? 'checked' : this._payload.checked === 'mixed' ? 'mixed' : 'unchecked';

View file

@ -24,6 +24,7 @@ import * as network from '../network';
import type { Page, PageBinding, PageDelegate } from '../page'; import type { Page, PageBinding, PageDelegate } from '../page';
import type { ConnectionTransport } from '../transport'; import type { ConnectionTransport } from '../transport';
import type * as types from '../types'; import type * as types from '../types';
import type * as channels from '../../protocol/channels';
import { ConnectionEvents, FFConnection } from './ffConnection'; import { ConnectionEvents, FFConnection } from './ffConnection';
import { FFPage } from './ffPage'; import { FFPage } from './ffPage';
import type { Protocol } from './protocol'; import type { Protocol } from './protocol';
@ -77,7 +78,7 @@ export class FFBrowser extends Browser {
return !this._connection._closed; return !this._connection._closed;
} }
async doCreateNewContext(options: types.BrowserContextOptions): Promise<BrowserContext> { async doCreateNewContext(options: channels.BrowserNewContextParams): Promise<BrowserContext> {
if (options.isMobile) if (options.isMobile)
throw new Error('options.isMobile is not supported in Firefox'); throw new Error('options.isMobile is not supported in Firefox');
const { browserContextId } = await this._connection.send('Browser.createBrowserContext', { removeOnDetach: true }); const { browserContextId } = await this._connection.send('Browser.createBrowserContext', { removeOnDetach: true });
@ -155,7 +156,7 @@ export class FFBrowser extends Browser {
export class FFBrowserContext extends BrowserContext { export class FFBrowserContext extends BrowserContext {
declare readonly _browser: FFBrowser; declare readonly _browser: FFBrowser;
constructor(browser: FFBrowser, browserContextId: string | undefined, options: types.BrowserContextOptions) { constructor(browser: FFBrowser, browserContextId: string | undefined, options: channels.BrowserNewContextParams) {
super(browser, options, browserContextId); super(browser, options, browserContextId);
} }
@ -255,17 +256,17 @@ export class FFBrowserContext extends BrowserContext {
return this._browser._ffPages.get(targetId)!; return this._browser._ffPages.get(targetId)!;
} }
async doGetCookies(urls: string[]): Promise<types.NetworkCookie[]> { async doGetCookies(urls: string[]): Promise<channels.NetworkCookie[]> {
const { cookies } = await this._browser._connection.send('Browser.getCookies', { browserContextId: this._browserContextId }); const { cookies } = await this._browser._connection.send('Browser.getCookies', { browserContextId: this._browserContextId });
return network.filterCookies(cookies.map(c => { return network.filterCookies(cookies.map(c => {
const copy: any = { ... c }; const copy: any = { ... c };
delete copy.size; delete copy.size;
delete copy.session; delete copy.session;
return copy as types.NetworkCookie; return copy as channels.NetworkCookie;
}), urls); }), urls);
} }
async addCookies(cookies: types.SetNetworkCookieParam[]) { async addCookies(cookies: channels.SetNetworkCookie[]) {
const cc = network.rewriteCookies(cookies).map(c => ({ const cc = network.rewriteCookies(cookies).map(c => ({
...c, ...c,
expires: c.expires && c.expires !== -1 ? c.expires : undefined, expires: c.expires && c.expires !== -1 ? c.expires : undefined,

View file

@ -20,16 +20,16 @@ import { Artifact } from '../artifact';
import type { BrowserContext } from '../browserContext'; import type { BrowserContext } from '../browserContext';
import type * as har from './har'; import type * as har from './har';
import { HarTracer } from './harTracer'; import { HarTracer } from './harTracer';
import type { HarOptions } from '../types'; import type * as channels from '../../protocol/channels';
export class HarRecorder { export class HarRecorder {
private _artifact: Artifact; private _artifact: Artifact;
private _isFlushed: boolean = false; private _isFlushed: boolean = false;
private _options: HarOptions; private _options: channels.RecordHarOptions;
private _tracer: HarTracer; private _tracer: HarTracer;
private _entries: har.Entry[] = []; private _entries: har.Entry[] = [];
constructor(context: BrowserContext | APIRequestContext, options: HarOptions) { constructor(context: BrowserContext | APIRequestContext, options: channels.RecordHarOptions) {
this._artifact = new Artifact(context, options.path); this._artifact = new Artifact(context, options.path);
this._options = options; this._options = options;
const urlFilterRe = options.urlRegexSource !== undefined && options.urlRegexFlags !== undefined ? new RegExp(options.urlRegexSource, options.urlRegexFlags) : undefined; const urlFilterRe = options.urlRegexSource !== undefined && options.urlRegexFlags !== undefined ? new RegExp(options.urlRegexSource, options.urlRegexFlags) : undefined;

View file

@ -23,7 +23,7 @@ import { SdkObject } from './instrumentation';
import type { NameValue } from '../common/types'; import type { NameValue } from '../common/types';
import { APIRequestContext } from './fetch'; import { APIRequestContext } from './fetch';
export function filterCookies(cookies: types.NetworkCookie[], urls: string[]): types.NetworkCookie[] { export function filterCookies(cookies: channels.NetworkCookie[], urls: string[]): channels.NetworkCookie[] {
const parsedURLs = urls.map(s => new URL(s)); const parsedURLs = urls.map(s => new URL(s));
// Chromiums's cookies are missing sameSite when it is 'None' // Chromiums's cookies are missing sameSite when it is 'None'
return cookies.filter(c => { return cookies.filter(c => {
@ -50,7 +50,7 @@ export function filterCookies(cookies: types.NetworkCookie[], urls: string[]): t
// 253402300800 == Sat, 1 Jan 1000 00:00:00 +0000 (UTC) // 253402300800 == Sat, 1 Jan 1000 00:00:00 +0000 (UTC)
const kMaxCookieExpiresDateInSeconds = 253402300799; const kMaxCookieExpiresDateInSeconds = 253402300799;
export function rewriteCookies(cookies: types.SetNetworkCookieParam[]): types.SetNetworkCookieParam[] { export function rewriteCookies(cookies: channels.SetNetworkCookie[]): channels.SetNetworkCookie[] {
return cookies.map(c => { return cookies.map(c => {
assert(c.url || (c.domain && c.path), 'Cookie should have a url or a domain/path pair'); assert(c.url || (c.domain && c.path), 'Cookie should have a url or a domain/path pair');
assert(!(c.url && c.domain), 'Cookie should have either url or domain'); assert(!(c.url && c.domain), 'Cookie should have either url or domain');

View file

@ -20,6 +20,7 @@ import * as frames from './frames';
import * as input from './input'; import * as input from './input';
import * as js from './javascript'; import * as js from './javascript';
import * as network from './network'; import * as network from './network';
import type * as channels from '../protocol/channels';
import type { ScreenshotOptions } from './screenshotter'; import type { ScreenshotOptions } from './screenshotter';
import { Screenshotter, validateScreenshotOptions } from './screenshotter'; import { Screenshotter, validateScreenshotOptions } from './screenshotter';
import { TimeoutSettings } from '../common/timeoutSettings'; import { TimeoutSettings } from '../common/timeoutSettings';
@ -86,7 +87,7 @@ export interface PageDelegate {
setScreencastOptions(options: { width: number, height: number, quality: number } | null): Promise<void>; setScreencastOptions(options: { width: number, height: number, quality: number } | null): Promise<void>;
getAccessibilityTree(needle?: dom.ElementHandle): Promise<{tree: accessibility.AXNode, needle: accessibility.AXNode | null}>; getAccessibilityTree(needle?: dom.ElementHandle): Promise<{tree: accessibility.AXNode, needle: accessibility.AXNode | null}>;
pdf?: (options?: types.PDFOptions) => Promise<Buffer>; pdf?: (options: channels.PagePdfParams) => Promise<Buffer>;
coverage?: () => any; coverage?: () => any;
// Work around WebKit's raf issues on Windows. // Work around WebKit's raf issues on Windows.
@ -160,7 +161,7 @@ export class Page extends SdkObject {
readonly _frameManager: frames.FrameManager; readonly _frameManager: frames.FrameManager;
readonly accessibility: accessibility.Accessibility; readonly accessibility: accessibility.Accessibility;
private _workers = new Map<string, Worker>(); private _workers = new Map<string, Worker>();
readonly pdf: ((options?: types.PDFOptions) => Promise<Buffer>) | undefined; readonly pdf: ((options: channels.PagePdfParams) => Promise<Buffer>) | undefined;
readonly coverage: any; readonly coverage: any;
private _clientRequestInterceptor: network.RouteHandler | undefined; private _clientRequestInterceptor: network.RouteHandler | undefined;
private _serverRequestInterceptor: network.RouteHandler | undefined; private _serverRequestInterceptor: network.RouteHandler | undefined;

View file

@ -17,6 +17,7 @@
import type { Size, Point, TimeoutOptions } from '../common/types'; import type { Size, Point, TimeoutOptions } from '../common/types';
export type { Size, Point, Rect, Quad, URLMatch, TimeoutOptions } from '../common/types'; export type { Size, Point, Rect, Quad, URLMatch, TimeoutOptions } from '../common/types';
import type * as channels from '../protocol/channels';
export type StrictOptions = { export type StrictOptions = {
strict?: boolean, strict?: boolean,
@ -77,16 +78,12 @@ export type FilePayload = {
}; };
export type MediaType = 'screen' | 'print'; export type MediaType = 'screen' | 'print';
export const mediaTypes: Set<MediaType> = new Set(['screen', 'print']);
export type ColorScheme = 'dark' | 'light' | 'no-preference'; export type ColorScheme = 'dark' | 'light' | 'no-preference';
export const colorSchemes: Set<ColorScheme> = new Set(['dark', 'light', 'no-preference']);
export type ReducedMotion = 'no-preference' | 'reduce'; export type ReducedMotion = 'no-preference' | 'reduce';
export const reducedMotions: Set<ReducedMotion> = new Set(['no-preference', 'reduce']);
export type ForcedColors = 'active' | 'none'; export type ForcedColors = 'active' | 'none';
export const forcedColors: Set<ForcedColors> = new Set(['active', 'none']);
export type DeviceDescriptor = { export type DeviceDescriptor = {
userAgent: string, userAgent: string,
@ -98,56 +95,6 @@ export type DeviceDescriptor = {
}; };
export type Devices = { [name: string]: DeviceDescriptor }; export type Devices = { [name: string]: DeviceDescriptor };
export type PDFOptions = {
scale?: number,
displayHeaderFooter?: boolean,
headerTemplate?: string,
footerTemplate?: string,
printBackground?: boolean,
landscape?: boolean,
pageRanges?: string,
format?: string,
width?: string,
height?: string,
preferCSSPageSize?: boolean,
margin?: {top?: string, bottom?: string, left?: string, right?: string},
};
export type CSSCoverageOptions = {
resetOnNavigation?: boolean,
};
export type JSCoverageOptions = {
resetOnNavigation?: boolean,
reportAnonymousScripts?: boolean,
};
export type JSRange = {
startOffset: number,
endOffset: number,
count: number
};
export type CSSCoverageEntry = {
url: string,
text?: string,
ranges: {
start: number,
end: number
}[]
};
export type JSCoverageEntry = {
url: string,
scriptId: string,
source?: string,
functions: {
functionName: string,
isBlockCoverage: boolean,
ranges: JSRange[]
}[]
};
export type ProxySettings = { export type ProxySettings = {
server: string, server: string,
bypass?: string, bypass?: string,
@ -202,180 +149,14 @@ export type NormalizedContinueOverrides = {
postData?: Buffer, postData?: Buffer,
}; };
export type NetworkCookie = {
name: string,
value: string,
domain: string,
path: string,
expires: number,
httpOnly: boolean,
secure: boolean,
sameSite: 'Strict' | 'Lax' | 'None'
};
export type SetNetworkCookieParam = {
name: string,
value: string,
url?: string,
domain?: string,
path?: string,
expires?: number,
httpOnly?: boolean,
secure?: boolean,
sameSite?: 'Strict' | 'Lax' | 'None'
};
export type EmulatedSize = { viewport: Size, screen: Size }; export type EmulatedSize = { viewport: Size, screen: Size };
export type HarOptions = { export type LaunchOptions = channels.BrowserTypeLaunchOptions & { useWebSocket?: boolean };
omitContent?: boolean,
path: string,
urlGlob?: string,
urlRegexSource?: string,
urlRegexFlags?: string,
};
export type BrowserContextOptions = {
viewport?: Size,
screen?: Size,
noDefaultViewport?: boolean,
ignoreHTTPSErrors?: boolean,
javaScriptEnabled?: boolean,
bypassCSP?: boolean,
userAgent?: string,
locale?: string,
timezoneId?: string,
geolocation?: Geolocation,
permissions?: string[],
extraHTTPHeaders?: HeadersArray,
offline?: boolean,
httpCredentials?: Credentials,
deviceScaleFactor?: number,
isMobile?: boolean,
hasTouch?: boolean,
colorScheme?: ColorScheme,
reducedMotion?: ReducedMotion,
forcedColors?: ForcedColors,
acceptDownloads?: boolean,
recordVideo?: {
dir: string,
size?: Size,
},
recordHar?: HarOptions,
storageState?: SetStorageState,
strictSelectors?: boolean,
proxy?: ProxySettings,
baseURL?: string,
serviceWorkers?: 'allow' | 'block',
};
export type EnvArray = { name: string, value: string }[];
type LaunchOptionsBase = {
channel?: string,
executablePath?: string,
args?: string[],
ignoreDefaultArgs?: string[],
ignoreAllDefaultArgs?: boolean,
handleSIGINT?: boolean,
handleSIGTERM?: boolean,
handleSIGHUP?: boolean,
timeout?: number,
env?: EnvArray,
headless?: boolean,
devtools?: boolean,
proxy?: ProxySettings,
downloadsPath?: string,
chromiumSandbox?: boolean,
slowMo?: number,
useWebSocket?: boolean,
tracesDir?: string,
};
export type LaunchOptions = LaunchOptionsBase & {
firefoxUserPrefs?: { [key: string]: string | number | boolean },
};
export type LaunchPersistentOptions = LaunchOptionsBase & BrowserContextOptions;
export type ProtocolLogger = (direction: 'send' | 'receive', message: object) => void; export type ProtocolLogger = (direction: 'send' | 'receive', message: object) => void;
export type SerializedAXNode = {
role: string,
name: string,
valueString?: string,
valueNumber?: number,
description?: string,
keyshortcuts?: string,
roledescription?: string,
valuetext?: string,
disabled?: boolean,
expanded?: boolean,
focused?: boolean,
modal?: boolean,
multiline?: boolean,
multiselectable?: boolean,
readonly?: boolean,
required?: boolean,
selected?: boolean,
checked?: 'checked' | 'unchecked' | 'mixed',
pressed?: 'pressed' | 'released' | 'mixed',
level?: number,
valuemin?: number,
valuemax?: number,
autocomplete?: string,
haspopup?: string,
invalid?: string,
orientation?: string,
children?: SerializedAXNode[]
};
export type ConsoleMessageLocation = { export type ConsoleMessageLocation = {
url: string, url: string,
lineNumber: number, lineNumber: number,
columnNumber: number, columnNumber: number,
}; };
export type Error = {
message: string,
name: string,
stack?: string,
};
export type NameValueList = {
name: string;
value: string;
}[];
export type OriginStorage = {
origin: string;
localStorage: NameValueList;
};
export type StorageState = {
cookies: NetworkCookie[],
origins: OriginStorage[]
};
export type SetStorageState = {
cookies?: SetNetworkCookieParam[],
origins?: OriginStorage[]
};
export type APIResponse = {
url: string,
status: number,
statusText: string,
headers: HeadersArray,
body: Buffer,
};
export type AndroidDeviceOptions = {
host?: string,
port?: number,
omitDriverInstall?: boolean,
};

View file

@ -17,7 +17,7 @@ import type * as accessibility from '../accessibility';
import type { WKSession } from './wkConnection'; import type { WKSession } from './wkConnection';
import type { Protocol } from './protocol'; import type { Protocol } from './protocol';
import type * as dom from '../dom'; import type * as dom from '../dom';
import type * as types from '../types'; import type * as channels from '../../protocol/channels';
export async function getAccessibilityTree(session: WKSession, needle?: dom.ElementHandle) { export async function getAccessibilityTree(session: WKSession, needle?: dom.ElementHandle) {
const objectId = needle ? needle._objectId : undefined; const objectId = needle ? needle._objectId : undefined;
@ -167,8 +167,8 @@ class WKAXNode implements accessibility.AXNode {
return false; return false;
} }
serialize(): types.SerializedAXNode { serialize(): channels.AXNode {
const node: types.SerializedAXNode = { const node: channels.AXNode = {
role: WKRoleToARIARole.get(this._payload.role) || this._payload.role, role: WKRoleToARIARole.get(this._payload.role) || this._payload.role,
name: this._name(), name: this._name(),
}; };
@ -195,7 +195,7 @@ class WKAXNode implements accessibility.AXNode {
if ('pressed' in this._payload) if ('pressed' in this._payload)
node.pressed = this._payload.pressed === 'true' ? 'pressed' : this._payload.pressed === 'false' ? 'released' : 'mixed'; node.pressed = this._payload.pressed === 'true' ? 'pressed' : this._payload.pressed === 'false' ? 'released' : 'mixed';
const userStringProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Page.AXNode> = [ const userStringProperties: Array<keyof channels.AXNode & keyof Protocol.Page.AXNode> = [
'keyshortcuts', 'keyshortcuts',
'valuetext' 'valuetext'
]; ];
@ -205,7 +205,7 @@ class WKAXNode implements accessibility.AXNode {
(node as any)[userStringProperty] = this._payload[userStringProperty]; (node as any)[userStringProperty] = this._payload[userStringProperty];
} }
const booleanProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Page.AXNode> = [ const booleanProperties: Array<keyof channels.AXNode & keyof Protocol.Page.AXNode> = [
'disabled', 'disabled',
'expanded', 'expanded',
'focused', 'focused',
@ -227,7 +227,7 @@ class WKAXNode implements accessibility.AXNode {
(node as any)[booleanProperty] = value; (node as any)[booleanProperty] = value;
} }
const numericalProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Page.AXNode> = [ const numericalProperties: Array<keyof channels.AXNode & keyof Protocol.Page.AXNode> = [
'level', 'level',
'valuemax', 'valuemax',
'valuemin', 'valuemin',
@ -237,7 +237,7 @@ class WKAXNode implements accessibility.AXNode {
continue; continue;
(node as any)[numericalProperty] = (this._payload as any)[numericalProperty]; (node as any)[numericalProperty] = (this._payload as any)[numericalProperty];
} }
const tokenProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Page.AXNode> = [ const tokenProperties: Array<keyof channels.AXNode & keyof Protocol.Page.AXNode> = [
'autocomplete', 'autocomplete',
'haspopup', 'haspopup',
'invalid', 'invalid',

View file

@ -25,6 +25,7 @@ import * as network from '../network';
import type { Page, PageBinding, PageDelegate } from '../page'; import type { Page, PageBinding, PageDelegate } from '../page';
import type { ConnectionTransport } from '../transport'; import type { ConnectionTransport } from '../transport';
import type * as types from '../types'; import type * as types from '../types';
import type * as channels from '../../protocol/channels';
import type { Protocol } from './protocol'; import type { Protocol } from './protocol';
import type { PageProxyMessageReceivedPayload } from './wkConnection'; import type { PageProxyMessageReceivedPayload } from './wkConnection';
import { kPageProxyMessageReceived, WKConnection, WKSession } from './wkConnection'; import { kPageProxyMessageReceived, WKConnection, WKSession } from './wkConnection';
@ -82,7 +83,7 @@ export class WKBrowser extends Browser {
this._didClose(); this._didClose();
} }
async doCreateNewContext(options: types.BrowserContextOptions): Promise<BrowserContext> { async doCreateNewContext(options: channels.BrowserNewContextParams): Promise<BrowserContext> {
const createOptions = options.proxy ? { const createOptions = options.proxy ? {
proxyServer: options.proxy.server, proxyServer: options.proxy.server,
proxyBypassList: options.proxy.bypass proxyBypassList: options.proxy.bypass
@ -206,7 +207,7 @@ export class WKBrowser extends Browser {
export class WKBrowserContext extends BrowserContext { export class WKBrowserContext extends BrowserContext {
declare readonly _browser: WKBrowser; declare readonly _browser: WKBrowser;
constructor(browser: WKBrowser, browserContextId: string | undefined, options: types.BrowserContextOptions) { constructor(browser: WKBrowser, browserContextId: string | undefined, options: channels.BrowserNewContextParams) {
super(browser, options, browserContextId); super(browser, options, browserContextId);
this._authenticateProxyViaHeader(); this._authenticateProxyViaHeader();
} }
@ -249,17 +250,17 @@ export class WKBrowserContext extends BrowserContext {
return this._browser._wkPages.get(pageProxyId)!; return this._browser._wkPages.get(pageProxyId)!;
} }
async doGetCookies(urls: string[]): Promise<types.NetworkCookie[]> { async doGetCookies(urls: string[]): Promise<channels.NetworkCookie[]> {
const { cookies } = await this._browser._browserSession.send('Playwright.getAllCookies', { browserContextId: this._browserContextId }); const { cookies } = await this._browser._browserSession.send('Playwright.getAllCookies', { browserContextId: this._browserContextId });
return network.filterCookies(cookies.map((c: types.NetworkCookie) => { return network.filterCookies(cookies.map((c: channels.NetworkCookie) => {
const copy: any = { ... c }; const copy: any = { ... c };
copy.expires = c.expires === -1 ? -1 : c.expires / 1000; copy.expires = c.expires === -1 ? -1 : c.expires / 1000;
delete copy.session; delete copy.session;
return copy as types.NetworkCookie; return copy as channels.NetworkCookie;
}), urls); }), urls);
} }
async addCookies(cookies: types.SetNetworkCookieParam[]) { async addCookies(cookies: channels.SetNetworkCookie[]) {
const cc = network.rewriteCookies(cookies).map(c => ({ const cc = network.rewriteCookies(cookies).map(c => ({
...c, ...c,
session: c.expires === -1 || c.expires === undefined, session: c.expires === -1 || c.expires === undefined,